Str[i] auto boolean check in the for loop - c++

printArrayWithoutLength(char str [])
{
for(int i=0;str[i];i++)
cout<< str[i]<< endl;
}
Why does the above work? I am not using a boolean check on the length.

In C, any condition that isn't a direct boolean expression (that is, some other type than boolean and doesn't involve a comparison operator [>, <, ==, !=, etc]) will automatically compare as a not equal to zero, so you could rewrite your code as:
for(int i=0;str[i] != 0;i++)
or
for(int i=0;str[i] != '\0';i++)
or
for(int i=0; 0 != str[i]; i++)
with exactly the same result and exactly the same code being generated. Just a bit more or less typing, and depending on the familiarity with C or C++, you may find that it's more or less easy to read one over another.
Of course, this only works for traditional C-style strings that are terminated with a nul-character (character with the value zero). There are other ways to store strings, and this code, in whichever form would naturally not work if the string is not actually terminated with a zero character.

Writing str[i] as a conditional expression of for is equivalent to str[i] != '\0' (your string should be null terminated). When str[i] becomes \0, loop will terminate.

Whether this function (without return type)
printArrayWithoutLength(char str [])
{
for(int i=0;str[i];i++)
cout<< str[i]<< endl;
}
will or will not work depends on what the array used as the argument contains. If it contains a string that is a sequence of characters terminated by zero then this function will work because inside the loop there is condition
str[i]
that will be equal to false if the value of str[i] contains zero for some i.
According to the C++ Standard (4.12 Boolean conversions [conv.bool])
1 A prvalue of arithmetic, unscoped enumeration, pointer, or pointer
to member type can be converted to a prvalue of type bool. A zero
value, null pointer value, or null member pointer value is converted
to false; any other value is converted to true.
Otherwise if the array does not contain a string the behaviour of the function is undefined.

Related

what does ++array[str[i]]; does?

I found a program to print out the most frequent character in an array of char.
Here is the code.
void main()
{
int array[255] = {0}; // initialize all elements to 0
char str[] = "thequickbrownfoxjumpedoverthelazydog";
int i, max, index;
for(i = 0; str[i] != 0; i++)
{
++array[str[i]];
}
// then find the most used charater ...
}
I don't really understand what ++array[str[i]];does.
We initialized the array as int array[255] but it still accepts the index as str[i] which I believe is char type.
Is it because str[i] automatically turn into ASCII ? And what ++ preceding the command does ?
In this code
++array[str[i]];
i walks the length of str (because of the setup of the loop we are inside...).
For each character inside str, the expression str[i] gets the value of that character. I use "value" instead of "character", because it later is treated as an integer index.
With that value the expression array[str[i]] accesses one of the entries in the array. Each entry in that array corresponds to one possible ASCII "character".
The ++ increments the value in the array. I.e. it counts the number of occurrences of e.g. 'a'.
In total, the code makes a histogram of ASCII character frequency inside str.
Note however the important warning by WhozCraig, in case you intend to use this. You have to match the assumptions the code makes (copied with permission, for completeness):
Just fyi, not casting that index to unsigned char is a recipe for disaster. Further, this is not using a table guaranteed to hold enough slots to cover the domain. i.e. 1 << CHAR_BIT in width. It will "work" (term used loosely) for your input string presented here. It is not an end-all general solution to char counting.
First, the initialization of the array to size 255 is because the ascii values of the characters are in this range. so for example when you call str[i]=a it translate to the value 97 which is a part of the array. you could see the values in the following ascii table, http://www.asciitable.com
Second, the operator ++array[str[i]]; is called pre-increment which is just adds 1 to the value in the array, in the following case you could use the post-increment and you will get the same result, array[str[i]]++;
reference to read about the post/pre increment:
https://www.geeksforgeeks.org/pre-increment-and-post-increment-in-c/

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.

c++ work around comparison between pointer and integer

do {
getline (myfile,temp);
if (temp[0] != "="){
MyAlbums[i].tracks.push_back(temp);
}
else {
break;
}
}while(true);
gives me this error:
ISO C++ forbids comparison between pointer and integer [-fpermissive]
i am trying to loop through lines in a text file and 'push_pack' if the line does not begin with an "=" equals character. else i want to break out of the loop.
Any help is very much appriceated!
if (temp[0] != "="){
should be
if (temp[0] != '='){
The reason is that temp[0] is of type char (assume temp is the string you read in), you should compare it with char literal '=' not string literal "=". I am assuming that you read temp successfully, so you may need to check for that if this is not the case.
EDIT(thanks Adam Liss)
strings literals like "=" are of (const char *) type, they are enclosed in double-quotes; individual characters are enclosed in single-quotes. therefore, you have that compile complain message about comparing a char (char literal are integers) with const char *.
Quoting from here:IBM C++ documentation
C A character literal has type int.
C++ A character literal that contains only one character has type char,
which is an integral type.
First, make sure that getline succeeded. Evaluate it in a boolean context to figure that out:
while (getline(myfile, temp)) {
/* code goes here */
}
instead of
do {
getline(myfile, temp);
/* code goes here */
} while (true);
Never, ever do input without checking if it failed immediately, or you will get really annoying bugs to track down.
Second, make sure temp is at least 1 character long. temp.size() >= 1 will be true if it is safe to do temp[0]. If getline ever gives you a string of length 0, doing temp[0] on it will result in undefined behavior. Undefined behavior is really annoying to track down, because it can behave completely innocuous in one situation, and then bite you in an unexpected place later.
Third, do temp[0] != '=' instead of temp[0] != "=". '=' is a character, "=" is a buffer of 2 characters the first one is '=' the second is '\0'. The array of two characters denoted by "=" is implicitly converted into a pointer to the first character when you try to do !=, which then generates an error (because it has no idea how to compare a pointer to a character to a character).

'\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?