How to store adresses in an array - C++? - c++

My Code example:
char* array = new char[10];
char* str;
int j = 0;
MyClass(char* input){ //input = sentence columns terminated by '\n'
str = new char[strlen(input)];
for(int i=0; i<strlen(input); i++){
if (input[i] == '\n'){ //look for end of line
str[i] = '\0'; //add \0 Terminator for char[]
array[j] = &(str[i]); //store address of sentence beginning in array
j++;
}
else{
str[i] = input[i];
}
}
}
How do i store an address into an array. So i can get the beginning address of a sentence by number. I created a solution with a vector storing my sentences as char* objects. But there must be a way without vectors?!
EDIT:
This is my solution.
#include <iostream>
using namespace std;
class Pointer{
public:
char** array = new char*[10];
char* str;
char* buffer;
int j = 1;
Pointer(char* input){
str = new char[strlen(input)];
array[0] = str;
for (int i = 0; i < strlen(input); i++){
if (input[i] == '\n'){
str[i] = '\0';
array[j] = &(str[i]) + sizeof(char);
j++;
}
else{
str[i] = input[i];
}
}
}
void output(int i){
buffer = array[i];
cout<<buffer;
}
};
Thanks for your help! :)

The best way would be to use std containers for that (std::vector<std::string>). Anyway, if you do need to have it the C way:
In this line:
array[j] = &(str[i]);
you are storing an address of ith character of the string. If you want to store the pointer to entire string, use:
array[j] = str;
Please note you have numerous other errors in your code.
For example, you should not be using a constant size array for that, as you're risking undefined behaviour in case you have more lines in your text.
Btw. MyClass is a function, not a class.

Answer to actual question:
char ** array = new (char *)[10];
What you should probably do instead:
std::vector<std::string> array;

char* array[10]
char* str;
int j = 0;
MyClass(char* input){ //input = sentence columns terminated by '\n'
str = new char[strlen(input)];
for(int i=0; i<strlen(input); i++){
if (input[i] == '\n'){ //look for end of line
str[i] = '\0'; //add \0 Terminator for char[]
array[j] = str; //store address of sentence beginning in array
// or you can use
// array[j] = &(str[0]);
j++;
}
else{
str[i] = input[i];
}
}
}
Hope it helps!

class Pointer{
public:
Pointer(std::string input){
addresses = split(input, '\n', addresses);
}
void output(int i){
std::cout << addresses.at(i);
}
private:
std::vector<std::string> addresses;
};

Related

How can I reverse the words in a sentence without using built-in functions?

This was the interview question:
How to convert Dogs like cats to cats like Dogs ?
My code shows: cats like cats. Where am I making the mistakes?
#include <iostream>
using namespace std;
int main()
{
char sentence[] = ("dogs like cats");
cout << sentence << endl;
int len = 0;
for (int i = 0; sentence[i] != '\0'; i++)
{
len++;
}
cout << len << endl;
char reverse[len];
int k = 0;
for (int j = len - 1; j >= 0; j--)
{
reverse[k] = sentence[j];
k++;
}
cout << reverse << endl;
int words = 0;
char str[len];
for (int l = 0; reverse[l] != '\0'; l++)
{
if (reverse[l] == ' ' || reverse[l] == '\0') // not sure about this part
{
for (int m = l; m >= 0; m--)
{
str[words] = reverse[m];
words++;
}
}
}
cout << str;
return 0;
}
I know you can do this using pointers, stack, vectors... but interviewer was not interested in that!
This is a fixed version of your sample code:
Your principal problem is that every time you found and ' ' or '\0' you copy the bytes of the reverse string from the beginning to that point. Example in loop 5 you copy from index 0-5 (stac) from reverse to str in reverse order, but in in loop 10 you copy from index 0-10 (stac ekil) from reverse to str in reverse order, until here you have already the printed result string ('cats like cats'), and the same in loop 15 all of this incrementing the index of str, in the last loop you are written pass the end of the valid memory of str (and because of that not printed as output).
You need to keep track when end the last word reversed to reverse only the actual word, and not the string from the beginning to the actual index.
You don't want to count the special character (' ' and '\0') in the reversing of the words, you would end with cats like\0dogs
Modified sample code provided:
#include <iostream>
using namespace std;
int main() {
char sentence[] = ("dogs like cats");
cout << sentence << endl;
int len = 0;
for (int i = 0; sentence[i] != '\0'; i++) {
len++;
}
cout << len << endl;
char reverse[len];
int k = 0;
for (int j = len - 1; j >= 0; j--) {
reverse[k] = sentence[j];
k++;
}
cout << reverse << endl;
int words = 0;
char str[len];
// change here added last_l to track the end of the last word reversed, moved
// the check of the end condition to the end of loop body for handling the \0
// case
for (int l = 0, last_l = 0; ; l++) {
if (reverse[l] == ' ' || reverse[l] == '\0')
{
for (int m = l - 1; m >= last_l; m--) { // change here, using last_t to
str[words] = reverse[m]; // only reverse the last word
words++; // without the split character
}
last_l = l + 1; // update the end of the last
// word reversed
str[words] = reverse[l]; // copy the split character
words++;
}
if (reverse[l] == '\0') // break the loop
break;
}
cout << str << endl;
return 0;
}
Some code, written with the restriction of using the most simple features of the language.
#include <iostream>
// reverse any block of text.
void reverse(char* left, char* right) {
while (left < right) {
char tmp = *left;
*left = *right;
*right = tmp;
left++;
right--;
}
}
int main() {
char sentence[] = "dogs like cats";
std::cout << sentence << std::endl;
// The same length calculation as sample code.
int len = 0;
for (int i = 0; sentence[i] != '\0'; i++) {
len++;
}
std::cout << len << std::endl;
// reverse all the text (ex: 'stac ekil sgod')
reverse(sentence, sentence + len - 1);
// reverse word by word.
char* end = sentence;
char* begin = sentence;
while (end < sentence + len) {
if (*end != ' ')
end++;
if (end == sentence + len || *end == ' ') {
reverse(begin, end - 1);
begin = end + 1;
end = begin;
}
}
std::cout << sentence << std::endl;
return 0;
}
Dissecting your algorithm in pieces. First, you find the length of the string, not including the null char terminator. This is correct, though could be simplified.
size_t len = 0;
for (int i = 0; sentence[i] != '\0'; i++) {
len++;
}
cout << len << endl;
This could easily be written simply as:
size_t len = 0;
while (sentence[len])
++len;
Next, you reverse the entire string, but the first defect surfaces. The VLA (variable length array) you declare here, (which you don't need and shouldn't use, as it is a C++ extension and non-standard) does not account for, nor set, a terminating null-char.
char reverse[len]; // !! should be len+1
int k = 0;
for (int j = len - 1; j >= 0; j--) {
reverse[k] = sentence[j];
k++;
}
// !! Should have reverse[k] = 0; here.
cout << reverse << endl; // !! Undefined-behavior. no terminator.
This temporary buffer string is not needed at all. There is no reason you can't do this entire operation in-place. Once we calculate len correctly, you simply do something like the following to reverse the entire sequence, which retains the null char terminator in proper position:
// reverse entire sequence
int i = 0, j = len;
while (i < j--)
{
char c = sentence[i];
sentence[i++] = sentence[j];
sentence[j] = c;
}
Next we move to where you try to reverse each internal word. Again, just as before, the buffer length is not correct. It should be len+1. Worse (hard to imagine), you never remember where you left off when finding the end point of a word. That location should be the next point you start checking for, and skipping, whitespace. Without retaining that you copy from current point all the way back to the beginning of the string. which essentially blasts cats over dogs.
int words = 0;
char str[len]; // !! should be len+1
for (int l = 0; reverse[l] != '\0'; l++)
{
if (reverse[l] == ' ' || reverse[l] == '\0') // not sure about this part
{
for (int m = l; m >= 0; m--) {
str[words] = reverse[m];
words++;
}
}
}
cout << str; //!! Undefined behavior. non-terminated string.
Once again, this can be done in-place without difficulty at all. One such algorithm looks like this (and notice the loop that reverses the actual word is not-coincidentally the same algorithm as reversing our entire buffer):
// walk again, reversing each word.
i = 0;
while (sentence[i])
{
// skip ws; root 'i' at beginning of word
while (sentence[i] == ' ') // or use std::isspace(sentence[i])
++i;
// skip until ws or eos; root 'j' at one-past end of word
j = i;
while (sentence[j] && sentence[j] != ' ') // or use !std::isspace(sentence[j])
++j;
// remember the last position
size_t last = j;
// same reversal algorithm we had before
while (i < j--)
{
char c = sentence[i];
sentence[i++] = sentence[j];
sentence[j] = c;
}
// start at the termination point where we last stopped
i = last;
}
Putting It All Together
Though considerably simpler to use pointers than all these index variables, the following will do what you're attempting, in place.
#include <iostream>
int main()
{
char s[] = "dogs like cats";
std::cout << s << '\n';
size_t len = 0, i, j;
while (s[len])
++len;
// reverse entire sequence
i = 0, j = len;
while (i < j--)
{
char c = s[i]; // or use std::swap
s[i++] = s[j];
s[j] = c;
}
// walk again, reversing each word.
i = 0;
while (s[i])
{
// skip ws; root 'i' at beginning of word
while (s[i] == ' ') // or use std::isspace
++i;
// skip until ws or eos; root 'j' at one-past end of word
j = i;
while (s[j] && s[j] != ' ') // or use !std::isspace
++j;
// remember the last position
size_t last = j;
while (i < j--)
{
char c = s[i]; // or use std::swap
s[i++] = s[j];
s[j] = c;
}
// start at last-left posiion
i = last;
}
std::cout << s << '\n';
return 0;
}
Output
dogs like cats
cats like dogs
My advise would be to break up the original string into an array of words, reverse that array. Then add those words to your reversed sentence with a space in between.
Since they asked for no libraries, I assumed no std::string, no vectors, nothing at all and so I wrote it in C.. the only thing used is printf. Everything else is from scratch :l
The idea is that you reverse the array first. Then split the array by space and reverse each word.
Example: http://ideone.com/io6Bh9
Code:
#include <stdio.h>
int strlen(const char* s)
{
int l = 0;
while (*s++) ++l;
return l;
}
void reverse(char* str)
{
int i = 0, j = strlen(str) - 1;
for(; i < j; ++i, --j)
{
str[i] ^= str[j];
str[j] ^= str[i];
str[i] ^= str[j];
}
}
void nulltok(char* str, char tok, int* parts)
{
int i = 0, len = strlen(str);
*parts = 1;
for (; i < len; ++i)
{
if (str[i] == tok)
{
str[i] = '\0';
++(*parts);
}
}
}
char* reverse_sentence(char* str)
{
char* tmp = str;
reverse(str);
int i = 0, parts = 0, len = strlen(str);
nulltok(str, 0x20, &parts);
while(parts--)
{
reverse(str);
str += strlen(str) + 1;
}
for(; i < len; ++i)
if (tmp[i] == '\0')
tmp[i] = 0x20;
return tmp;
}
int main(void)
{
char str[] = "dogs like cats";
printf("%s", reverse_sentence(str));
return 0;
}
My solution
#include<iostream>
#include<string.h>
using namespace std;
int main()
{
string str;
cout<<"enter the sentence"<<endl;
getline(cin,str);
char* pch;
pch = strtok((char*)str.c_str()," ");
string rev = "";
while(NULL != pch)
{
rev.insert(0,pch);
rev.insert(0," ");
pch = strtok(NULL," ");
}
cout<<"the reversed string is :"<<rev<<endl;
return 0;
}

Null terminator at the end of char array in C++

Why it isn't necessary to store null character at the end of the string named temp in the following code
char source[50] = "hello world";
char temp[50] = "anything";
int i = 0;
int j = 0;
while (source[i] != '\0')
{
temp[j] = source[i];
i = i + 1;
j = j + 1;
}
cout << temp; // hello world
while in the case below it becomes necessary
char source[50] = "hello world";
char temp[50];
int i = 0;
int j = 0;
while (source[i] != '\0')
{
temp[j] = source[i];
i = i + 1;
j = j + 1;
}
cout << temp; // will give garbage after hello world
// in order to correct this we need to put temp[j] = '\0' after the loop
The difference is in the way of the definition of temp.
In the first case
char temp[50] = "anything";
temp is initialized. All its elements that was not assigned a character from the string literal were zero initialized.
In the second case
char temp[50];
temp was not initialized so its elements contain any arbitrary values.
There is a third case when temp had static storage duration. In this case if it is defined as
char temp[50];
all its elements are initialized by zero.
For example
#include <iostream>
char temp[50];
int main()
{
char source[50] = "hello world";
int i = 0;
int j = 0;
while (source[i] != '\0')
{
temp[j] = source[i];
i = i + 1;
j = j + 1;
}
std::cout << temp;
}
Also take into account that it would be more safe and effective to use standard C function strcpy to copy source into temp. For example
#include <cstring>
//...
std::strcpy( temp, source );
To add something.. in the definition of temp[] in the first sample you use the following code:
char source[50] = "hello world";
char temp[50] = "anything";
int i = 0;
int j = 0;
You see, the length of source (strlen) is 12, the length of temp is 9.. you also initialized the variable i and j to zero..
The location of i and j variables in the memory are actually right after the temp array.. So, for temp array, at location 12 (at the length of source array) this location has been already initialized to 0 by the definition and declaration of i and j variables.
So, you don't need the temp[j] = '\0' anymore..

Convert string vector to *char

void getParameters(char *query) {
vector<string> temp;
vector<string> elements;
for (int i = 0; i < 10; i++)
{
if (query[i] == '\0') {
temp.push_back('\0');
// Here I want to convert temp values to string and append it to elements
elements.push_back(temp);
break;
}
if (query[i] == ' ')
{
temp.push_back('\0');
elements.push_back(temp);
temp.clear();
continue;
}
temp.push_back(query[i]);
}
}
I want to append as a string all values of temp vector to elements vector.
For example:
temp[0] = "t";
temp[1] = "e";
temp[2] = "s";
temp[3] = "t";
temp[4] = "\0";
Result:
elements[0] = "test";
I don't know the length of the query so this is why I'm using vector for temp.
The example of the query:
select id from user
The final result should be:
elements[0] = "select";
elements[1] = "id";
elements[2] = "from";
elements[3] = "user";
Use std::stringstream
std::vector<std::string> getParameters(const char *query)
{
std::vector<std::string> elements;
std::stringstream ss(query);
std::string q;
while (ss >> q)
elements.push_back(q);
return elements;
}
And then,
char *s="select id from user";
std::vector<std::string> elements= getParameters(s);
See HERE
#include <sstream>
#include <vector>
#include <string>
std::vector<std::string> getParameters(const char *query) {
std::ostringstream split(query);
std::vector<std::string> elements;
std::string element;
while (split >> element)
elements.push_back(element);
return elements;
}
Only one vector is enough. Of course, stringstream is much more simple.
void getParameters(char *query) {
const int length = 10;
char temp[length];
vector<string> elements;
for (int i = 0, j = 0; i < 10; i++, j++)
{
if (query[i] == '\0') {
temp[j] = '\0';
elements.push_back((string)temp);
break;
}
if (query[i] == ' ')
{
temp[j] = '\0';
elements.push_back((string)temp);
j = -1;
continue;
}
temp[j] = query[i];
}
}
string str1 = "helo";
string str2 = "world";
string str = str1 + str2;
const char *cstr = str.c_str();
Just to provide a short and neat way for solving the final step you are asking for. I.e. concatenate a vector of strings into one single string:
std::string concatenated = std::accumulate(temp.begin(),temp.end(),string());

Strange behavior with getline C++

I am writing a simple program, where all the 'spaces' will be replaced by '%20'.
#include <iostream>
#include <string>
using namespace std;
int main (int argc, char* argv[]){
string input;
cout << "please enter the string where spaces will be replaced by '%20'" << endl;
getline(cin, input);
//count the number of spaces
int countSpaces = 0;
for (int i = 0 ; i < input.length() ; i++){
if (input[i] == ' '){
countSpaces++;
}
}
int size = input.length() + (2 * countSpaces) + 1;
//char cstr1[size];
char *cstr1 = new char[size];
char *cstr = cstr1;
for (int i = 0 ; i < input.length() ; i++){
if(input[i] == ' '){
*cstr++ = '%';
*cstr++ = '2';
*cstr++ = '0';
}
else{
*cstr++ = input[i];
}
}
*cstr == '\0';
cout << cstr1 << endl;
delete[] cstr1;
return 0;
}
I get the following strange behavior:
With the test input "this is strange " I get "this%20is%20strange%20%20his is" , where I just expect "this%20is%20strange%20%20"
If I hard code the same string, I get the correct results.
Replacing char *cstr1 = new char[size]; with char cstr1[size]; & removing the delete[] while still fetching the input via getline also removes the error.
I am using i686-apple-darwin10-g++-4.2.1:
Any help is much appreciated.
The last line must be *cstr = '\0'; not ==
Change the *cstr == '\0'; in the end of your code to *cstr = '\0';
ViolĂ !
*cstr == '\0';
this line checks if *cstr is equal to '\0' or not and return 1 or 0 accordingly
that is wrong as you want to insert the \0 character at the end of the string
so write single = instead of double =

Split string into array of chars

I'm writing a program that requires a string to be inputted, then broken up into individual letters. Essentially, I need help finding a way to turn "string" into ["s","t","r","i","n","g"]. The strings are also stored using the string data type instead of just an array of chars by default. I would like to keep it that way and avoid char but will use it if necessary.
Assuming you already have the string inputted:
string s("string");
vector<char> v(s.begin(), s.end());
This will fill the vector v with the characters from a string.
string a = "hello";
cout << a[1];
I hope that explains it
A string is just a sequence of the underlying character (i.e. char for std::string and wchar_t for std::wstring).
Because of that, you easily get each letter:
for (std::string::size_type l = 0; l < str.length(); ++l)
{
std::string::value_type c = str[l];
}
Try using the c_str() method of std::string:
#include <string>
using namespace std;
int main(void)
{
string text = "hello";
size_t length = text.length() + sizeof('\0');
char * letters = new char[length];
strcpy(letters, length.c_str());
for (unsigned int i = 0; i < length; ++i)
{
cout << '[' << i << "] == '" << letters[i] << "'\n";
}
return EXIT_SUCCESS;
}
string input ="some string for example my cat is handsome";
vector<string> split_char_to_vector(string input) {
vector<string> output;
for(size_t i=0;i<=input.length();i++) {
output.push_back(input[i]));
}
return output;
}
if you want to convert split strings into character the first traverse the string and write for each characters of string to the i'th position of char array ie
char array[1000];
std::string input="i dont think love never ends";
for(size_t i=0;i<=input.length();/*or string::npos;*/i++)
{
if (input[i] != '\0')
{
array[i] = input[i];
}
else
{
break;
}
}
for (size_t i = 0; i < 100; i++)
{
std::cout << array[i] << std::endl;
}
if you want to convert split strings into character the first traverse the string and write for each characters of string to the i'th position of char array ie
char array[1000];
std::string input="i dont think love never ends";
for(size_t i=0;i<=input.length();/*or string::npos;*/i++)
{
if (input[i] != '\0')
{
array[i] = input[i];
}
else
{
break;
}
}
//to avoid noise after position input.length();
for (size_t i = input.length(); i <= 1000; i++)
{
array[i] = '\0';
}
//ie return array; or print
for (size_t i = 0; i < 100; i++)
{
std::cout << array[i] << std::endl;
}
You can use a for loop to iterate through the characters of a string.
std::string str = "word"
for(char i : str){
std::cout << i << std::endl;
}