When I run the code below my output is not what I expect.
My way of understanding it is that ptr points to the address of the first element of the Str array. I think ptr + 5 should lead to the + 5th element which is f. So the output should only display f and not both fg.
Why is it showing fg? Does it have to do with how cout displays an array?
#include <iostream>
using namespace std;
int main()
{
char *ptr;
char Str[] = "abcdefg";
ptr = Str;
ptr += 5;
cout << ptr;
return 0;
}
Expected output: f
Actual output: fg
When you declare:
char Str[] = "abcdefg"
The string abcdefg is stored implicitly with an extra character \0 which marks the end of the string.
So, when you cout a char* the output will be all the characters stored where the char * points and all the characters stored in consecutive memory locations after the char* until a \0 character is encountered at one of the memory locations! Since, \0 character is after g in your example hence 2 characters are printed.
In case you only want to print the current character, you shall do this ::
cout << *ptr;
Why is it showing fg?
The reason why std::cout << char* prints the string till the end instead of a single char of the string is , because std::cout treats a char * as a pointer to the first character of a C-style string and prints it as such.1
Your array:
char Str[] = "abcdefg";
gets implicitly assigned an '\0'at the end and it is treated as a C-style string.
Does it have to do with how std::cout displays an array?
This has to do with how std::cout handles C-style strings, to test this change the array type to int and see the difference, i.e. it will print a single element.
1. This is because in C there are no string types and strings are manipulated through pointers of type char, indicating the beginning and termination character: '\0', indicating the end.
Related
I initialized a C++ string with a string literal and replaced a char with NULL.
When printed with cout << the full string is printed and the NULL char prints as blank.
When printed as c_str the string print stop at the NULL char as expected.
I'm a little confused. Does the action came from cout? or string?
int main(){
std::string a("ab0cd");
a[2] = '\0'; // '\0' is null char
std::cout << a << std::endl; // abcd
std::cout << a.c_str() << std::endl; // ab
}
Test it online.
I'm not sure whether the environment is related, anyway, I work with VSCode in Windows 10
First you can narrow down your program to the following:
#include <iostream>
#include <string>
int main(){
std::string a("ab0cd");
a[2] = '\0'; // replace '0' with '\0' (same result as NULL, just cleaner)
std::cout << a << "->" << a.c_str();
}
This prints
abcd->ab
That's because the length of a std::string is known. So it will print all of it's characters and not stop when encountering the null-character. The null-character '\0' (which is equivalent to the value of NULL [both have a value of 0, with different types]), is not printable, so you see only 4 characters. (But this depends on the terminal you use, some might print a placeholder instead)
A const char* represents (usually) a null-terminated string. So when printing a const char* it's length is not known and characters are printed until a null-character is encountered.
Contrary to what you seem to think, C++ string are not null terminated.
The difference in behavior came from the << operator overloads.
This code:
cout << a.c_str(); // a.c_str() is char*
As explained here, use the << overloads that came with cout, it print a char array C style and stop at the first null char. (the char array should be null terminated).
This code:
cout << a; // a is string
As explained here, use the << overloads that came with string, it print a string object that internally known is length and accept null char.
string end limit (boundary) is not 0 (NULL) like simple char* but its size keep internally in its member data as it's actually user-defined type (an instantiated object) as opposed to primitive type, so
int main(){
string a("abc0d");
a[3] = 0; // '\0' is null char
a.resize(2);
std::cout << a << std::endl; // ab
std::cout << a.c_str() << std::endl; // ab
}
i'm sorry change your code to be more comfortable, watch as it results in
ab
ab
good learning: http://www.cplusplus.com/reference/string/string/find/index.html
I am trying to reverse a string (but that's not the problem that I have). The problem is trying to change the value of the string array given a certain index. However, every time I try to change the value at the index, I get a bus error. Namely, Bus error: 10. I'm not sure what this means. Also, I tried str[0] = "a" but this also gives me a bus error. Any suggestions to fix this?
#include <iostream>
using namespace std;
void reverse(char* str){
str[0] = 'a';
}
int main(){
char* str = "hello";
reverse(str);
}
Allocate your string as an array on the stack and not as a pointer into a possibly read-only segment of your program.
char str[] = "hello";
First of all, this line should atleast give you a warning:
char* str = "hello";
you are converting a string constant to a pointer, which is not allowed.
To fix your code, you should use, char str[] = "hello" in main().
When you pass this array in reverse(), it decays to char*, now the question which you asked in previous answer's comment.
But when I write cout << str << endl;, why does it print out "hello"? Shouldn't it print only the first character of the string since it points to the first element of the array?
It is because the << operator on std::cout is overloaded. If you give it a char* or const char*, it treats the operand as a pointer to (the first character of) a C-style string, and prints the contents of that string:
const char * str= "hello";
cout << str; // prints "hello"
If you give it a char value, it prints that value as a character:
cout << *str; // prints "h"
cout << str[0]; // prints "h"
Code:
#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
char testChar[] = {'a','b','c'};
char *testPointer = testChar ;
cout << testPointer << endl;
return 0;
}
Question:
When I use cout << mypointer,
Why does to print each letter of the array and the mess(refer to
output) at the end? My assumption is when I see out the pointer
points to the first letter prints then the second then etc and
prints the stuff at the end.
What is the mess (refer to output) at the end , the address?
Comments:
I know at the end of the array there's suppose to be a null pointer right?
I learnt this a year ago and forget please help me recall what is going on.
Output:
abc 310 367 277_ 377
Program ended with exit code: 0
When printing out a string (or char array in your case), it must be terminated by a null character \0, otherwise cout will continue to print out characters located in memory past the intended string until it either hits a null character, or it accesses memory it is not allowed to read from which results in a segmentation fault.
That "mess" at the end that is being printed are the values located in the memory locations immediately past the char array.
Also after initializing char testChar[] = "abc"; you actually don't need 'char *testPointer = testChar' statement since testChar is itself an address to the first element of the array. So cout << testChar << endl;will do.
I am currently trying to learn C++ from a book that I got from a friend of mine a couple of days ago. I I've seen some codes as a quiz in the book that I need to solve. So I tried to solve them but I'm not sure if my assumption is right.
This is the first one
char* r(char *g){ // can someone explain this line for me? I'm not sure what is it saying
char ch = 'B'; // is the code going to be correct if I changed char ch to char* ch?
return &ch; // since this is &ch, then the previous line should be char* ch, am I right?
}
The second code:
char* a;
a = new char[strlen(b)]; // will this line cause a compiling error just because b is undefined ? since there is no length for b because it's not even there?
strcpy(a,b); // since we're using strcpy() a and b has to be pointers am I right?
I am not asking for the answers, I need someone to tell me whether am right or wrong and why please.
char* r(char *g){ // can someone explain this line for me? I'm not sure what is it saying
Declares a function, r which takes one argument, a pointer g to contain the address of one or more characters.
char ch = 'B';
Declares a variable, ch of type char and assigns it a value 'B'. That is - it will contain a number which is the position in the ASCII chart of the letter B. It's going to contain the number 66, but when you print it out, it will produce the letter 'B'. (see http://www.asciitable.com/)
This variable will likely be on the stack. It could be in a register, but compilers are generally smart and the next line will ensure it is on the stack.
return &ch;
In this context, & is the address of operator.
return address_of(ch);
Since ch is of type char, &ch produces a value which is of type char*.
char* a;
Declares a variable a with no initial value. This is a bad thing to get into the habbit of writing.
a = new char[strlen(b)];
You say that b doesn't exist, but I think it's assumed to be of type char* - a pointer to one or more characters. In C and C++ a "C-String" is an array of 'char' values (characters) terminated by a char of value 0 (not the character '0', which has an ASCII value of 48, but 0, or '\0'). This is called a 'terminating nul' or a 'nul character' or a 'nul byte'.
The string "hello" is actually representable as an array { 'h', 'e', 'l', 'l', 'o', 0 }. Contrast with "hell0", which would be { 'h', 'e', 'l', 'l', '0', 0 };
The function strlen counts the number of characters from the address it is called with until it finds a nul. If b was the address of "hello", strlen would return 5.
new allocates memory for an object, or in this case an array of objects of type char, the number of which is the return value of strlen.
size_t len = strlen(b);
char* a = new char[len];
At this point in the code, recall my explanation about terminating nul and that strlen returns the number of characters before it finds the 0. To store a C-string you need the number of characters PLUS space for a terminating NULL.
If b is the string "A", it consists one character ('A') but two *char*s - 'A', and 0. Strlen returns the number of characters.
strcpy(a, b);
This will copy the characters pointed to by b to the address at a, *including the terminating nul.
The bug here is that you only allocated enough memory for the characters.
char* a = new char[strlen(b) + 1];
strcpy(a, b);
Again - strlen is always going to return the length - the number of characters, and you're always going to want one more than that, for the nul.
would be correct - otherwise you're going to overwrite the memory allocated to you and cause a corruption.
--- EDIT ---
Throwing some of this together, live demo here: http://ideone.com/X8HPxP
#include
#include
int main() {
char a[] = "hello";
std::cout << "a starts out as [" << a << "]\n";
// C/C++ arrays are 0-based, that is:
a[0] = 'H'; // changes a to "Hello"
std::cout << "a is now [" << a << "]\n";
std::cout << "strlen(a) returns " << strlen(a) << "\n";
// But that is based on counting characters until the 0.
a[3] = 0; // one way to write it,
a[3] = '\0'; // some people prefer writing it this way.
std::cout << "a changed to [" << a << "]\n";
std::cout << "strlen(a) is now " << strlen(a) << "\n";
return 0;
}
First Code:
r is function name having return type char* i.e. reference type and accepting parameter of reference type char* g.
'B' is assigned to ch variable.
r function returns the address of ch variable.
According to me no correction required in First code.
Second Code:
Yes it will cause compilation error at line 2 as b is not declared or defined.
1st Code:
You are defining a function called r which accepts a pointer to a char and returns a pointer to a char.
char* r(char *g){
//stack char variable ch is initialized to B
//changing char ch to char *ch will compile (with a warning) but then the address pointed by ch will contain garbage (value of 'B' projected as an address).
char ch = 'B';
//you are returning the address of ch which as seen above is a stack variable so you are causing undefined behavior. You should avoid this.
return &ch;
}
2nd Code:
char* a;
// if b is undefined as you state then following line will cause compiling error. strlen() will calculate the length of the area at runtime so b must be at lease defined first.
a = new char[strlen(b)];
//a is a pointer as you defined it above and points to the heap memory allocated by new
strcpy(a,b);
char* r(char *g){
here r() is function which take char* as argument and return char*
char ch = 'B';
return &ch;
Here, ch is char locally defined and you are returning it. This is not good. Better use char*. Also char will have only one character whereas if you use char* you can have more than one.
char* ch = "Thats My string";
return ch; //Notice ch is a pointer. No need to use &
Second Code:
char* a;
a = new char[strlen(b)];
If b is undefined, sure there will be error. If b is char* with some value assigned to it strlen will provide you length of string which b is having. so this looks good.
strcpy(a,b); // since we're using strcpy() a and b has to be pointers am I right?
Yes you are right! You can use strncpy instead.
I have a big number stored in a string and try to extract a single digit. But what are the differences between those calls?
#include <iostream>
#include <string>
int main(){
std::string bigNumber = "93485720394857230";
char tmp = bigNumber.at(5);
int digit = atoi(&tmp);
int digit2 = atoi(&bigNumber.at(5))
int digit3 = atoi(&bigNumber.at(12));
std::cout << "digit: " << digit << std::endl;
std::cout << "digit2: " << digit2 << std::endl;
std::cout << "digit3: " << digit3 << std::endl;
}
This will produce the following output.
digit: 7
digit2: 2147483647
digit3: 57230
The first one is the desired result. The second one seems to me to be a random number, which I cannot find in the string. The third one is the end of the string, but not just a single digit as I expected, but up from the 12th index to the end of the string. Can somebody explain the different outputs to me?
EDIT: Would this be an acceptable solution?
char tmp[2] = {bigNumber.at(5), '\0'};
int digit = atoi(tmp);
std::cout << "digit: " << digit << std::endl;
It is all more or less explicable.
int main(){
std::string bigNumber = "93485720394857230";
This line copies the single character '5' into the character variable. atoi will convert this correctly. atoi expects that the string parameter is a valid 0 terminated string. &tmp is only a pointer to the character variable - the behaviour of this call is undefined since the memory immediately following the character in memory is unknown. To be exact, you would have to create a null terminated string and pass that in.*
char tmp = bigNumber.at(5);
int digit = atoi(&tmp);
This line gets a pointer to the character in position 5 in the string. This happens to be a pointer into the original big number string above - so the string parameter to atoi looks like the string "5720394857230". atoi will clearly oveflow trying to turn this into an integer since no 32 bit integer will hold this.
int digit2 = atoi(&bigNumber.at(5))
This line gets a pointer into the string at position 12. The parameter to atoi is the string
"57230". This is converted into the integer 57230 correctly.
int digit3 = atoi(&bigNumber.at(12));
...
}
Since you are using C++, there are nicer methods to convert strings of characters into integers. One that I am partial to is the Boost lexical_cast library. You would use it like this:
char tmp = bigNumber.at(5);
// convert the character to a string then to an integer
int digit = boost::lexical_cast<int>(std::string(tmp));
// this copies the whole target string at position 5 and then attempts conversion
// if the conversion fails, then a bad_lexical_cast is thrown
int digit2=boost::lexical_cast<int>(std::string(bigNumber.at(5)));
* Strictly, atoi will scan through the numeric characters until a non-numeric one is found. It is clearly undefined when it would find one and what it will do when reading over invalid memory locations.
I know why the 2nd number is displayed.
From the atoi reference.
If the correct value is out of the range of representable values, INT_MAX or INT_MIN is returned.
2147483647 is INT_MAX
bigNumber.at() doesn't return a new string with a single character but the address of a character in the string. So the second call is actually:
atoi("720394857230")
which causes the internal algorithm to overflow.
Also, the first call is very dangerous since it depends on the (random) value in memory at (&tmp)+1.
You have to allocate a string with two characters, assign the single character from bigNumber.at() to the first and \0 to the second and then call atoi() with the address of the temporary string.
The argument to atoi should be a zero-terminated string.
Function at gives pointer to char in the string. Function atoi converts string to int, not only one char.