Testing conditions using Character pointers - c++

int main()
{
char *p,c;
for(p="Hello World";c=*p;++p)
{
printf("%c",c);
}
}
In the above code,i know that ++p will make pointer 'p' point to next character in the "Hello World".And i also know that there is no boundary checking performed on arrays in C or C++.The output of the program is 'Hello World'. How am i able to test conditions using
c=*p;
What does 'c=*p' return.As far as my understanding goes, when '++p' reaches the end of the 'hello world', pointer 'p' should point to some garbage value and the loop should print some garbage values.

c=*p; doesn't return anything, it's an expression. The for loop evaluates the value of c after the assignment.
when '++p' reaches the end of the 'hello world', pointer 'p' should point to some garbage value
Not really. Before reaching the end, it reaches the null terminating character - '\0'. Which is 0. Which is assigned to c and evaluates the break condition to false. So the loop finishes before it goes out of bounds.

C strings are by definition terminated by a NULL character '\0', if it is a string then it has to end it in a NULL. therefore c = *p will point to a NULL character when the string ends, which is in your case the immediately next character of 'd'. And the NULL character in the ASCII table has an integer value 0, which evaluates to false and gets out of the for loop.
Note that if a C string does not end in a NULL character (then at first it is not a C string), then basically there is no way of detecting that it is a string, as it will be stores as a sequence of bytes. In that case it will be simply a byte array or a string, will depend on how we interpret.
Also not that c = *p does not return anything, it is an expression and it is evaluated. e = *p transfers the value pointed by the current value of p into the var c, the value of which is the final evaluation of the expression.

Strings are terminated by a null character (aka with \0), so then at the end p should point to the null character that terminates the string, thus c would be \0 which is considered a false condition.

Related

Explanation of the Function that Defines strlen

I'm learning about pointers in c++.
I have researched and found the manual function that defines strlen to be something like this.
int strlen(const char *a){
const char *b;
for (b=a;*b;++b);
return b-a;
}
Would anyone be able to explain this block of code in plain english? In particular, why is *b set as the terminating condition in the for loop?
This is not an answer to homework. It's just a question that arose while I was researching. Thanks.
This is a particularly terse piece of C code, with a for loop that does not have a body.
The idea is to set pointer b to the beginning of the string a, and keep advancing it until you hit character '\0', which indicates the end of the stirng (i.e. serves as null terminator). Nothing else needs to be done in that loop, hence its body is empty.
Once the loop is over, subtracting a from b yields the number of characters between the initial character of the string and its null terminator, i.e. the length of the string.
Here is a more readable way to write the same loop:
for (b=a ; *b != '\0' ; ++b) // Use explicit comparison to zero
; // Put semicolon on a separate line
When C expression is used in a statement that requires a logical expression, an implicit comparison to zero is applied. Hence, *b != '\0' is the same as *b.
In both C and C++ strings are really called null terminated byte strings. That null terminator is equal to zero. And in both C and C++ the value zero is equivalent to false.
What the loop does is to iterate until the "current character" (pointed to by b) becomes equal to the terminator.

what does cout << "\n"[a==N]; do?

In the following example:
cout<<"\n"[a==N];
I have no clue about what the [] option does in cout, but it does not print a newline when the value of a is equal to N.
I have no clue about what the [] option does in cout
This is actually not a cout option, what is happening is that "\n" is a string literal. A string literal has the type array of n const char, the [] is simply an index into an array of characters which in this case contains:
\n\0
note \0 is appended to all string literals.
The == operator results in either true or false, so the index will be:
0 if false, if a does not equal N resulting in \n
1 if true, if a equals N resulting in \0
This is rather cryptic and could have been replaced with a simple if.
For reference the C++14 standard(Lightness confirmed the draft matches the actual standard) with the closest draft being N3936 in section 2.14.5 String literals [lex.string] says (emphasis mine):
string literal has type “array of n const char”, where n is the
size of the string as defined below, and has static storage duration
(3.7).
and:
After any necessary concatenation, in translation phase 7 (2.2),
’\0’ is appended to every string literal so that programs that scan a string can find its end.
section 4.5 [conv.prom] says:
A prvalue of type bool can be converted to a prvalue of type int, with
false becoming zero and true becoming one.
Writing a null character to a text stream
The claim was made that writing a null character(\0) to a text stream is undefined behavior.
As far as I can tell this is a reasonable conclusion, cout is defined in terms of C stream, as we can see from 27.4.2 [narrow.stream.objects] which says:
The object cout controls output to a stream buffer associated with the object stdout, declared in
<cstdio> (27.9.2).
and the C11 draft standard in section 7.21.2 Streams says:
[...]Data read in from a text stream will necessarily compare equal to the data
that were earlier written out to that stream only if: the data consist only of printing
characters and the control characters horizontal tab and new-line;
and printing characters are covered in 7.4 Character handling <ctype.h>:
[...]the term control character
refers to a member of a locale-specific set of characters that are not printing
characters.199) All letters and digits are printing characters.
with footnote 199 saying:
In an implementation that uses the seven-bit US ASCII character set, the printing characters are those
whose values lie from 0x20 (space) through 0x7E (tilde); the control characters are those whose
values lie from 0 (NUL) through 0x1F (US), and the character 0x7F (DEL).
and finally we can see that the result of sending a null character is not specified and we can see this is undefined behavior from section 4 Conformance which says:
[...]Undefined behavior is otherwise
indicated in this International Standard by the words ‘‘undefined behavior’’ or by the
omission of any explicit definition of behavior.[...]
We can also look to the C99 rationale which says:
The set of characters required to be preserved in text stream I/O are those needed for writing C
programs; the intent is that the Standard should permit a C translator to be written in a maximally
portable fashion. Control characters such as backspace are not required for this purpose, so their
handling in text streams is not mandated.
cout<<"\n"[a==N];
I have no clue about what the [] option does in cout
In C++ operator Precedence table, operator [] binds tighter than operator <<, so your code is equivalent to:
cout << ("\n"[a==N]); // or cout.operator <<("\n"[a==N]);
Or in other words, operator [] does nothing directly with cout. It is used only for indexing of string literal "\n"
For example for(int i = 0; i < 3; ++i) std::cout << "abcdef"[i] << std::endl; will print characters a, b and c on consecutive lines on the screen.
Because string literals in C++ are always terminated with null character('\0', L'\0', char16_t(), etc), a string literal "\n" is a const char[2] holding the characters '\n' and '\0'
In memory layout this looks like:
+--------+--------+
| '\n' | '\0' |
+--------+--------+
0 1 <-- Offset
false true <-- Result of condition (a == n)
a != n a == n <-- Case
So if a == N is true (promoted to 1), expression "\n"[a == N] results in '\0' and '\n' if result is false.
It is functionally similar (not same) to:
char anonymous[] = "\n";
int index;
if (a == N) index = 1;
else index = 0;
cout << anonymous[index];
valueof "\n"[a==N] is '\n' or '\0'
typeof "\n"[a==N] is const char
If the intention is to print nothing (Which may be different from printing '\0' depending on platform and purpose), prefer the following line of code:
if(a != N) cout << '\n';
Even if your intention is to write either '\0' or '\n' on the stream, prefer a readable code for example:
cout << (a == N ? '\0' : '\n');
It's probably intended as a bizarre way of writing
if ( a != N ) {
cout<<"\n";
}
The [] operator selects an element from an array. The string "\n" is actually an array of two characters: a new line '\n' and a string terminator '\0'. So cout<<"\n"[a==N] will print either a '\n' character or a '\0' character.
The trouble is that you're not allowed to send a '\0' character to an I/O stream in text mode. The author of that code might have noticed that nothing seemed to happen, so he assumed that cout<<'\0' is a safe way to do nothing.
In C and C++, that is a very poor assumption because of the notion of undefined behavior. If the program does something that is not covered by the specification of the standard or the particular platform, anything can happen. A fairly likely outcome in this case is that the stream will stop working entirely — no more output to cout will appear at all.
In summary, the effect is,
"Print a newline if a is not equal to N. Otherwise, I don't know. Crash or something."
… and the moral is, don't write things so cryptically.
It is not an option of cout but an array index of "\n"
The array index [a==N] evaluates to [0] or [1], and indexes the character array represented by "\n" which contains a newline and a nul character.
However passing nul to the iostream will have undefined results, and it would be better to pass a string:
cout << &("\n"[a==N]) ;
However, the code in either case is not particularly advisable and serves no particular purpose other than to obfuscate; do not regard it as an example of good practice. The following is preferable in most instances:
cout << (a != N ? "\n" : "") ;
or just:
if( a != N ) cout << `\n` ;
Each of the following lines will generate exactly the same output:
cout << "\n"[a==N]; // Never do this.
cout << (a==N)["\n"]; // Or this.
cout << *((a==N)+"\n"); // Or this.
cout << *("\n"+(a==N)); // Or this.
As the other answers have specified, this has nothing to do with std::cout. It instead is a consequence of
How the primitive (non-overloaded) subscripting operator is implemented in C and C++.
In both languages, if array is a C-style array of primitives, array[42] is syntactic sugar for *(array+42). Even worse, there's no difference between array+42 and 42+array. This leads to interesting obfuscation: Use 42[array] instead of array[42] if your goal is to utterly obfuscate your code. It goes without saying that writing 42[array] is a terrible idea if your goal is to write understandable, maintainable code.
How booleans are transformed to integers.
Given an expression of the form a[b], either a or b must be a pointer expression and the other; the other must be an integer expression. Given the expression "\n"[a==N], the "\n" represents the pointer part of that expression and the a==N represents the integer part of the expression. Here, a==N is a boolean expression that evaluates to false or true. The integer promotion rules specify that false becomes 0 and true becomes 1 on promotion to an integer.
How string literals degrade into pointers.
When a pointer is needed, arrays in C and C++ readily degrade into a pointer that points to the first element of the array.
How string literals are implemented.
Every C-style string literal is appended with the null character '\0'. This means the internal representation of your "\n" is the array {'\n', '\0'}.
Given the above, suppose a==N evaluates to false. In this case, the behavior is well-defined across all systems: You'll get a newline. If, on the other hand, a==N evaluates to true, the behavior is highly system dependent. Based on comments to answers to the question, Windows will not like that. On Unix-like systems where std::cout is piped to the terminal window, the behavior is rather benign. Nothing happens.
Just because you can write code like that doesn't mean you should. Never write code like that.

What does '\0' mean?

I can't understand what the '\0' in the two different place mean in the following code:
string x = "hhhdef\n";
cout << x << endl;
x[3]='\0';
cout << x << endl;
cout<<"hhh\0defef\n"<<endl;
Result:
hhhdef
hhhef
hhh
Can anyone give me some pointers?
C++ std::strings are "counted" strings - i.e., their length is stored as an integer, and they can contain any character. When you replace the third character with a \0 nothing special happens - it's printed as if it was any other character (in particular, your console simply ignores it).
In the last line, instead, you are printing a C string, whose end is determined by the first \0 that is found. In such a case, cout goes on printing characters until it finds a \0, which, in your case, is after the third h.
C++ has two string types:
The built-in C-style null-terminated strings which are really just byte arrays and the C++ standard library std::string class which is not null terminated.
Printing a null-terminated string prints everything up until the first null character. Printing a std::string prints the whole string, regardless of null characters in its middle.
\0 is the NULL character, you can find it in your ASCII table, it has the value 0.
It is used to determinate the end of C-style strings.
However, C++ class std::string stores its size as an integer, and thus does not rely on it.
You're representing strings in two different ways here, which is why the behaviour differs.
The second one is easier to explain; it's a C-style raw char array. In a C-style string, '\0' denotes the null terminator; it's used to mark the end of the string. So any functions that process/display strings will stop as soon as they hit it (which is why your last string is truncated).
The first example is creating a fully-formed C++ std::string object. These don't assign any special meaning to '\0' (they don't have null terminators).
The \0 is treated as NULL Character. It is used to mark the end of the string in C.
In C, string is a pointer pointing to array of characters with \0 at the end. So following will be valid representation of strings in C.
char *c =”Hello”; // it is actually Hello\0
char c[] = {‘Y’,’o’,’\0′};
The applications of ‘\0’ lies in determining the end of string .For eg : finding the length of string.
The \0 is basically a null terminator which is used in C to terminate the end of string character , in simple words its value is null in characters basically gives the compiler indication that this is the end of the String Character
Let me give you example -
As we write printf("Hello World"); /* Hello World\0
here we can clearly see \0 is acting as null ,tough printinting the String in comments would give the same output .

How to make sure nothing else is in array

I'm doing an assignment for school and I seem to have a problem with other characters being in the array. (Amongst other problems...)
In one function, I declared the array..
const int MAXSIZE = 100;
char inFix[MAXSIZE];
And this code is used to put chars into the array
//loop to store user input until enter is pressed
while((inputChar = static_cast<char>(cin.get()))!= '\n')
{
//if function to decide if the input should be stored or not
if(isOperator(inputChar) || isdigit(static_cast<int>(inputChar)) || inputChar == '(' || inputChar == ')')
{
inFix[a] = inputChar; //stores input
a++;
}
}
At the end of this, I append the null character to the array though I wasn't sure if I should do this:
inFix[MAXSIZE] = '\0';
Or if I should've used strcat.. either way... in my next function, I use strcat to append a parenthesis to the end.
But I've been having problems with the code, so I ran a for loop to print what is inside the infix array at the beginning of my next function, just to see...
And I get this annoying beeping sound, and a string of weird characters like hearts, and music signs... and.. a whole list of odd characters. What could be the problem? Thanks.
EDIT: by the way, I input 9*4, and I run the for loop after i append the parenthesis, so at the beginning of the output, I get:
9*4) and then the string of odd characters...
so I ran a for loop to print what is inside the infix array at the beginning of my next function, just to see...
And I get this annoying beeping sound, and a string of weird characters like hearts, and music signs... and.. a whole list of odd characters. What could be the problem?
The problem is that you're printing out array elements which you never initialized. The answer you have currently accepted advises you to initialize all those elements. Although this will not cause errors it is a mistake to let this answer prevent you from fully understanding the problem you encountered.
Reconsider your code where you inserted a null character at the end of the array:
inFix[MAXSIZE] = '\0';
You apparently know that a null character has something to do with marking the end of the string, but you've mistaken how to do that correctly. Everything from the beginning of the array until a null character will be treated as part of your string. If you copy three characters from the input 9*4 into your array then you should only want those three characters to be seen as part of your string. What you do not want is for everything in the array past those three characters, up to MAXSIZE to also be treated as part of your string. So you need to put the end-of-string marker, the '\0', right after the characters you care about.
(BTW, inFix[MAXSIZE] = '\0'; not only puts the end-of-string marker at the end of the array, it puts it outside the array, which you are not allowed to do. The program will behave unpredictably.)
inFix[0] = '9';
inFix[1] = '*';
inFix[2] = '4';
inFix[3] = '\0'; // <-- this is where you need to put the end-of-string marker, because this is the end of the characters you care about.
Putting the end-of-string marker at the end of the array effectively does this:
inFix[0] = '9';
inFix[1] = '*';
inFix[2] = '4';
inFix[3] = ???
inFix[4] = ???
.
.
.
inFix[98] = ???
inFix[99] = ??? // annoying bell noise? musical note symbol?
inFix[100] = '\0'; // Yes, Please!
The reason initializing the array to all zeros (which can also be done like this char inFix[MAXSIZE] = {};, empty braces instead of a 0) worked for you is because that means that no matter where you stop writing characters you care about, the next character will be a '\0'. That position, right after the characters you care about, is the only place it matters.
Since the loop that's copying the characters knows exactly where it stops it also knows exactly where to insert the end-of-string marker. It would be easy to just insert a single '\0' in the correct place.
Try appending the '\0' to position a in the array instead - that is, exactly after the last char you've read. Otherwise you're putting your characters in the array, then a random sequence of what was in the array before, and then after that is the \0 (or, in this case, it's one after the end of the array, which is even worse).
You say you null terminate string using inFix[MAXSIZE] = '\0' as you currently understand this should converted into inFix[MAXSIZE - 1] = '\0' but in this case you say that you have an string that ended in last possible character!! so how you should add something( for example a parenthesis ) to it?? because it is full and it can't accept any more characters.
So may be this is better to use inFix[a] = '\0' because you know that a point to end of string, and now if a < MAXSIZE then you have enough space to add more items to the string otherwise you may increase MAXSIZE (using strcat for example) or show some error to the user.
You declared the array with:
char inFix[MAXSIZE];
At this point in time, the content of the array is not initialized. Printing out these uninitialized characters will lead to the behavior you see (strange characters, sounds, etc.).
However, the contents of that array are not initialized. If you want to initialize this array, change this line to:
char inFix[MAXSIZE] = {0};
This initialization syntax causes the elements in the array to be initialized. The first elements are initialized to the values provided in the brackets, while any values not in the brackets will be initialized to 0. In the case above, all of the array elements will be initialized to 0 (which happens to correspond to the NULL character \0).
Since all the characters are initialized to NULL in this case, you don't need to append the null character after your input.
That said, a better solution would be not to use a C-Style array at all, but a std::vector<char>, or simply a std::string, as pointed out above.

'\0' related issue

Looking at this loop that copies one c-string to another:
void strcpyr(char *s, char *t)
{
while(*s++=*t++)// Why does this work?
;
}
Why do we not check for the '\0' character in the while loop, like this?
while((*s++=*r++)!='\0')..
How does the first loop terminate?
The statement *s++=*t++ not only assigns the next character from t to s but also returns the current value of *t as the result of the expression. The while loop terminates on any false value, including '\0'.
Think of it this way. If you did:
char c = *s++ = *t++;
in addition to copying a char from *t to *s and incrementing both, it would also set c to the current value of *t.
When we hit the '\0' in the string initially pointed to by t, the *s++=*t++, which does the assignment, also returns the value that's assigned to the position pointed to by s, or '\0', which evaluates to false and terminates the loop.
In your second example, you explicitly rely on the fact that the assignment returns the assigned character, while the first example implicitly uses this fact (and the fact that the 0 character (also written '\0') is considered to be false, while all other characters evaluate to true, so the expression c != '\0' will yield the same result as c.
The loop is going to terminate because '\0' is effectively 0, and the what the "while" is evaluating is not a the result of an equality test (==), but the right-value of the assignment expression.
The reason we are not explicitly checking for zero is that in C 0 is false.
Therefore the loop
while(*s++=*t++)
;
will terminate when the character pointed to by t is 0.
-Adam
I think you mean to write this:
void strcpyr(char *s, char *t) {
while (*s++ = *t++);
}
The loop terminates when the value pointed to by "t" is zero. For C (and C++) loops and conditionals, any integer that is non-zero is true.
The while loop is testing the result of the assignment.
The result of an assignment is the value assigned into the left-hand side of the statement. On the last iteration, when *t == '\0', the '\0' is assigned into s, which becomes the value the while loop considers before deciding it is time to quit.
In C, a=b is actually an expression which is evaluated as 'b'. It is easier to write:
if(a=b) {
//some block
}
then:
a=b;
if(a!=0) {
//some block
}
In C language within if, while, for statement the check that is made is: is expression not zero?