string not printing properly - c++

I've used the following code for getting a string and using its first character to make another string:
char gramG[100],aug[100],start;
cout<<"\nEnter the grammar:\n";
cin.getline(gramG,100,'.');
start=gramG[0];
aug[0]=start;
aug[1]='\'';
aug[2]='-';
aug[3]='>';
aug[4]=start;
aug[5]=char(13);
cout<<aug;
cout<<aug[0];
In the above code when i'm printing 'aug' it prints as ' ¶'->A ' if A is my start symbol. If i am printing only aug[0] then it is printing correctly A. But when i am printing the string as a whole the aug[0] value is printed as some garbage. Please help.

aug is treated as a 0-terminated character array. 0-terminate it.
aug[6] = 0;

you have to terminate the string with null value
for c++ the null value is \0
use this
aug[6] = '\0';
this should work;

Related

Reading characters from a line of a file

The first line of my file must be exactly a two digit number which I read into firstline[2]. I use sscanf to read the data from that buffer and store it into an int to represent the number of lines (not including the first one) in the file. If there is a third character I must exit with an error code.
I've tried introducing a new char buffer thirdchar[1] and comparing it to a new line (10 or '\n'). If thirdchar does not equal newline then it should exit with an error code. Later in my program I use sscanf to read firstline and store that number into an int called numberoflines. When I intriduce thirdchar, it appends an extra two zeros to numberoflines to the end of what was in firstline.
//If the first line was "20"
int numberoflines;
char firstline[2];
file.get(firstline[0]);//should be '2'
file.get(firstline[1]);//should be '0'
char thridchar[1];
file.get(thirdchar[0]);//should be '\n'
if (thirdchar !=10){exit();}//10 is the value gdb spits out to represent '\n'
sscanf(firstline, "%d", &numberoflines);//numberoflines should be 20
I debugged this and firstline and thirdchar are the expected values, but numberoflines becomes 2000! I've removed the code related to thirdchar and it works fine, but doesnt meet the requirement of it being a 2 digit number. Am I misunderstanding what sscanf does? Is there a better way to implement this? Thanks.
---------------UPDATE------------------
So I've updated my code to use std::string and std::getline:
std::string firstline;
std::getline(file, firstline);
And I get the following error when trying to print the value of firstline
$1 = Python Exception <class 'gdb.error'> There is no member named _M_dataplus.:
sscanf requires the input string to be null-terminated. You are not passing it a null-terminated string so it's not behaving as expected.
As suggested, you would be better placed reading in the string using std::getline and converting the std::string into an integer.
Further reading here if using C++11 onwards, or here otherwise.

Why does a C++ string need a \0?

I was hoping that I could get some further explanation. I was told that I need to explicitly add \0 to the end of a string. Apparently this is for the C++ string class and that it is actually an array of characters that seems to be parsed under the hood. I was told that we must use the \0 in order to tell where the end of the string is as seen below:
int main()
{
char str[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
cout << str << endl;
return 0;
}
However, if I have a user input their name, for example, I don't believe that C++ automatically uses the \0 to terminate the string. So the argument that the \0 must be there to know where the string ends makes no sense. Why cant we use the .length() function to account for the length of the string?
I wrote the following program to illustrate that the length of the input can be found from the .length() function.
int main()
{
string firstName;
cout << "Enter your first name: ";
cin >> firstName;
cout << "First Name = " << firstName << endl;
cout << "String Length = " << firstName.length() << endl;
return 0;
}
So, if the user inputs the name "Tom". Then the output would be the following:
First Name = Tom
String Length = 3
I brought this to my professor's attention and also this article http://www.cplusplus.com/reference/string/string/length/
and I was told that is why I am in college because it cannot be done this way. Can any one offer any insight, since I don't understand what I am missing?
The "C string" was adopted into C++ from the C language. The C language did not have a string type. Strings in C were represented as an array of char, and the string was terminated with the NUL byte (\0). A plain string literal in C++ still has these semantics.
The C++ string type maintains the length within the object, as you say, so in a string, the NUL is not required. To get a "C string" from a string, you can use the c_str() method on the string. This is useful if you need to pass the contents of the C++ string to a function that only understands the NUL terminated variety.
std::string s("a string"); // s is initialized,
// the length is computed when \0 is encountered.
assert(s.size() == sizeof("a string")-1);
// sizeof string literal includes the \0
assert(s.c_str()[s.size()] == '\0');
// c_str() includes the \0
In your first program, you are initializing an array of char with an initializer list. The initialization is equivalent to the following:
char str[6] = "Hello";
This style of initializing an array of char is a special allowance that C++ provides since it is the syntax accepted by C.
In your second program, you are getting the name from the standard input. When C++ scans the input to populate the string argument, it essentially scans byte by byte until it encounters a separator (whitespace characters, by default). It may or may not insert a NUL byte at the end.
You're not missing anything per se. The null terminator is used on character arrays to indicate the end. However, the string class takes care of all of that for you. The length attribute is a perfectly acceptable way of doing it since you're using strings.
However, if you're using a character array, then yes, you would need to check if you're on the null terminator, as you may not know the length of your string.
The following will give you no issues.
int length = 2;
char str[] = "AB";
However, try the following, and you'll see some issues.
int length = 5;
char str[length + 1] = "ABCDE"; // +1 makes room for automatic \0
char str2[length + 1] = "ABC";
Try the second snipped using your for loop method knowing the length, and the first one will give you ABCDE, but the second one will give you "ABC" followed by one junk character. It's only one because you'll have [A][B][C][\0][JUNK] in your array. Make length larger and you'll see more junk.

How could I copy data that contain '\0' character

I'm trying to copy data that conatin '\0'. I'm using C++ .
When the result of the research was negative, I decide to write my own fonction to copy data from one char* to another char*. But it doesn't return the wanted result !
My attempt is the following :
#include <iostream>
char* my_strcpy( char* arr_out, char* arr_in, int bloc )
{
char* pc= arr_out;
for(size_t i=0;i<bloc;++i)
{
*arr_out++ = *arr_in++ ;
}
*arr_out = '\0';
return pc;
}
int main()
{
char * out= new char[20];
my_strcpy(out,"12345aa\0aaaaa AA",20);
std::cout<<"output data: "<< out << std::endl;
std::cout<< "the length of my output data: " << strlen(out)<<std::endl;
system("pause");
return 0;
}
the result is here:
I don't understand what is wrong with my code.
Thank you for help in advance.
Your my_strcpy is working fine, when you write a char* to cout or calc it's length with strlen they stop at \0 as per C string behaviour. By the way, you can use memcpy to copy a block of char regardless of \0.
If you know the length of the 'string' then use memcpy. Strcpy will halt its copy when it meets a string terminator, the \0. Memcpy will not, it will copy the \0 and anything that follows.
(Note: For any readers who are unaware that \0 is a single-character byte with value zero in string literals in C and C++, not to be confused with the \\0 expression that results in a two-byte sequence of an actual backslash followed by an actual zero in the string... I will direct you to Dr. Rebmu's explanation of how to split a string in C for further misinformation.)
C++ strings can maintain their length independent of any embedded \0. They copy their contents based on this length. The only thing is that the default constructor, when initialized with a C-string and no length, will be guided by the null terminator as to what you wanted the length to be.
To override this, you can pass in a length explicitly. Make sure the length is accurate, though. You have 17 bytes of data, and 18 if you want the null terminator in the string literal to make it into your string as part of the data.
#include <iostream>
using namespace std;
int main() {
string str ("12345aa\0aaaaa AA", 18);
string str2 = str;
cout << str;
cout << str2;
return 0;
}
(Try not to hardcode such lengths if you can avoid it. Note that you didn't count it right, and when I corrected another answer here they got it wrong as well. It's error prone.)
On my terminal that outputs:
12345aaaaaaa AA
12345aaaaaaa AA
But note that what you're doing here is actually streaming a 0 byte to the stdout. I'm not sure how formalized the behavior of different terminal standards are for dealing with that. Things outside of the printable range can be used for all kinds of purposes depending on the kind of terminal you're running... positioning the cursor on the screen, changing the color, etc. I wouldn't write out strings with embedded zeros like that unless I knew what the semantics were going to be on the stream receiving them.
Consider that if what you're dealing with are bytes, not to confuse the issue and to use a std::vector<char> instead. Many libraries offer alternatives, such as Qt's QByteArray
Your function is fine (except that you should pass to it 17 instead of 20). If you need to output null characters, one way is to convert the data to std::string:
std::string outStr(out, out + 17);
std::cout<< "output data: "<< outStr << std::endl;
std::cout<< "the length of my output data: " << outStr.length() <<std::endl;
I don't understand what is wrong with my code.
my_strcpy(out,"12345aa\0aaaaa AA",20);
Your string contains character '\' which is interpreted as escape sequence. To prevent this you have to duplicate backslash:
my_strcpy(out,"12345aa\\0aaaaa AA",20);
Test
output data: 12345aa\0aaaaa AA
the length of my output data: 18
Your string is already terminated midway.
my_strcpy(out,"12345aa\0aaaaa AA",20);
Why do you intend to have \0 in between like that? Have some other delimiter if yo so desire
Otherwise, since std::cout and strlen interpret a \0 as a string terminator, you get surprises.
What I mean is that follow the convention i.e. '\0' as string terminator

Reading characters displays all characters followed by some rubbish characters

I have a program that reads a .DAT file that contains a list of:
removepeer 452
addpeer 6576
removepeer 54245
At some point, it reads out rubbish text: H�
Here is a part of my code where I find fault in:
getline(abc, info, '\n'); //data here displays pretty fine
int count = info.size();
char text[count];
for(int a=0; a<count; a++){
text[a] = data[a];
}
cout << text << endl; //Some rubbish text found in some printout!
It prints out the last line followed by some rubbish text
The text array will not be null terminated, which is required when using operator<< with char[] as they are treated as null terminated c-style strings. Random characters from memory will be written until a null terminator is by chance located. Technically, accessing beyond the bounds of an array is undefined behaviour.
To correct, append a null terminator to text. As your compiler has as an extension for variable length arrays (which are not standard C++, but are in C99) you could change it to:
char text[count + 1];
// snip...
text[count] = 0;
Having said that, I am unsure why you are copying from a std::string instance to a char[]. std::string instances also be written to streams using operator<<.

C++: Checking whether a string character is a digit using isdigit. .

I am reading input for my program in a loop using getline.
string temp(STR_SIZE, ' ');
string str_num(STR_SIZE, ' ');
...
getline(cin, temp, '\n');
After which, I use a function to find the next delimiter(white space) and assign all the characters before the white space to str_num. Looks something like this:
str_num.assign(temp, 0, next_white_space(0));
I have verified that this works well. The next step in my solution would be to convert str_num to an int(this part also works well), but I should check to make sure each character in str_num is a digit. Here's the best of what I've tried:
if(!isdigit(str_num[0] - '0')) {
cout << "Error: Not an appropriate value\n";
break; /* Leave control structure */
}
For some reason, This always prints the error message and exits the structure.
Why is that?
I've used operator[] for string objects before, and it seemed to work well. But, here, it's totally messing me up.
Thanks.
std::isdigit takes a char's integer value and checks it.
So, remove the - '0' and just pass str_num[index] to isdigit().
Note: because this function comes from C, the old style of treating chars as integers shows through in the method taking an int. However, chars can promote to int values, so a char becomes an int just fine and this works.