Recently I saw this while loop condition in C in the example below but I have no idea what the while condition really means and how the compiler knows when it is done. Could someone explain it to me?
This is what I believe it means: while loop iterates through the char array until the ending of the array since there is nothing else then the while loop ends, or am I wrong? I tried to use the same while loop but in another language such as Go, however, the compiler threw an error saying that I cannot use a non-bool.
// C program to demonstrate
// example of tolower() function.
#include <ctype.h>
#include <stdio.h>
int main()
{
int j = 0;
char str[] = "GEEKSFORGEEKS\n";
// Character to be converted to lowercase
char ch = 'G';
// convert ch to lowercase using toLower()
char ch;
while (str[j]) { // <- this part, how is this a condition?
ch = str[j];
// convert ch to lowercase using toLower()
putchar(tolower(ch));
j++;
}
return 0;
}
the while loop can be understood as "while this string has characters" and as known in C strings or an array of chars contain a '\0' => Null character, in the end, once the while loop achieves it, it will stop the iteration.
So yeap! you are right.
You can think of an array of chars as following:
So as you see in the picture an array of chars is already a pointer, and each of the characters has an address, as well that the address of a pointer is the address of the first element, so when you declared
char str[] = "GEEKSFORGEEKS\n";
it was allocated in the memory like below:
[G][E][E][K][S][F][O][R][G][E][E][K][S][\n][\0]
The program will crash because you have a redeclaration of ch variable, as well there is no need to initialize the char ch = 'G'; since you're overriding it in the while loop and it will take str[j], and so you started iterating at j = 0 which the 1st index in the array [G], as you're incrementing the loop will go until the null character [\0] and stop because there's no iteration after the NULL, in other examples you might see the following condition in the loop: while(str[j] != '\0') which is similar to your condition but just more specific.
You can gain more performance by iterating through the pointer just like the following:
#include <ctype.h>
#include <stdio.h>
int main()
{
char *str = "GEEKSFORGEEKS\n";
while (*str)
putchar(tolower(*str++));
return 0;
}
Although, you got your answer. Still, I wanna add some more details or an explanatory answer here.
In C, a conditional statement will have either the value 1 or 0. In the end, they all are evaluated to Boolean values true or false or 1 or 0.
So first, try to understand or dry run that while(str[j]). Guess what will be the value of str[j] when j = 0. It'll be the first character "G". Similarly in the next iteration, you'll get the next character until NULL character or String Termination character. Now, anything in between those parentheses in while(str[j]) will be considered as a conditional statement and they all are evaluated to 1 or 0. Now here's the thing that anyhow if that conditional statement isn't being evaluated specifically to 0, then It'll be supposed to have the value of 1.
So, here str[j] when j = 0 will be evaluated as 1, then next character and so on. Now, when we find \0 which is an escape character equivalent to 0. So, at \0 while loop will terminate as the condition will be false.
Can, you tell me what will be the output of this program?
#include<stdio.h>
int main()
{
if(printf("Hello TraineeGuy\n"))
printf("TRUE");
else
printf("FALSE");
return 0;
}
Related
I know what the null-terminator in C is represented by \0 and has the numerical value of 0. However, when I execute the following code below, the program treats the null terminator as %. I searched this up online but I couldn't find anyone with this issue.
int main(){
char* forward = "hello";
int forward_length = 0;
while (*(forward++) != '\0') {
printf("%d\n", forward_length++);
}
if(*forward == '%'){
printf("Terminator Found");
}
}
The output is:
0
1
2
3
4
Terminator Found
Clearly, forward[5] does not equal the char %. Can someone please let me know what is wrong with the program?
The construction leaves forward advanced too far. This is because the post-increment will run even if the loop condition is false (as it is inside the loop condition). The obvious fixed loop is as follows:
for (;*forward != '\0'; ++forward)
printf("%d\n", forward_length++);
If you prefer to keep the while loop, --forward after the while loop will fix it.
Sorry if this seems like a stupid question, but I came across this code that transforms a mixed-case string to a lower-case one, I understand it except the string iteration:
for (int i=0; str[i]; i++) {
str[i] = tolower(str[i]);
}
In my understanding the expression str[i] means continue iterating if str[i] exists, is that correct? And does C not check the boundaries of an array which means that the loop code go on forever?
Having the guard as str[i] is the same as str[i] != '\0', whereby the '\0' is the null-terminating character of a string. The guard of for loops either evaluates to true or false, or 0 and 1 in this case. Simply using str[i] checks if the character is valid(true), and not a null-terminating character(false), which marks the end of a string.
If your new to C strings, you can also just use strlen() from <string.h> for your guard. This function just returns the length of the string. Your code would then look like this:
for (int i=0; i < strlen(str); i++) {
str[i] = tolower(str[i]);
}
Although this is valid, using the first approach is much easier to use and more C like.
The condition str[i] tests for the end of the string. C-strings are null-terminated, so when the character '\0' is reached, the loop terminates.
No, C does not check array bounds.
It will not go forever because every string (char*) has to end with '\0'. So it loops until str[i] is not 0.
In C every C-string ie. constant you would type is represented as for example:
string a = {'x', 'y', 'z', 0}
for
a = "xyz"
Therefore, the loop terminates when meets the last character since the last element is NULL (0) which is obviously false.
You are right about the expression meaning "if(str[i])" exists, then continue iterating. However, the loop will NOT go on forever because once the value of "i" becomes greater than or equal to (>=) length of the array "str[]", the condition "if(str[i])" will fail. Thus, the loop will only execute as many times as the number of elements in the "str[]" array.
I am a total beginner and recently started studying strings in C programming.
I understand that we need to supply the '\0' (null) character at the end of the string (to act as a end of string marker).
So if my character array is
char string[]={'H','E','L','L','O','\0'};
This makes it a 6 element array.
So I was going through this simple example of copying one string to another string. Here is the code.
#include<stdio.h>
int main()
{
char string1[80],string2[80];
int i;
printf("Enter a string \n");
gets(string2);
for(i=0; string2[i]!= '\0';i++)
{
string1[i]=string2[i];
}
string1[i]='\0'; /*here is my problem*/
printf("The copied string is \n");
printf("%s",string1);
printf("\n");
printf("The number of character are \t");
printf("%d \n",i);
}
why isn't it string1[i+1]='\0'??
I mean, isn't by putting string1[i]='\0' overwrite the last element that was just stored in the above for loop?
The code is correct, because of the way the for loop works:
for(A; B; C)
CODE;
Is equivalent to:
A;
while (B)
{
CODE;
C;
}
(Except for the use of continue, that will jump to the increment expression, not the condition, as it would happen with a while).
And since the loop ends when string2[i] != '\0', it is obvious that upon exiting, i is the index for the proper NUL byte. So after that:
string1[i] = '\0';
will write the \0 at the same place as it is in string2.
Usually for this kind of analysis it is helpful to think about preconditions and postconditions. That is, assuming there are no break and no goto, you are guaranteed that at the beginning of a for or while loop the condition is always true. And just after the end of a for or while loop the condition is always false.
Your particular code, illustrated with assert calls:
for(i=0; string2[i] != '\0'; i++)
{
asssert(string2[i] != '\0');
string1[i] = string2[i];
}
asssert(string2[i] == '\0');
string1[i] = '\0';
Looking at the code, it seems as if i is incremented as long as the character is not '\0'. So, the last time it's incremented, it increments to a new position that hasn't had a character written to it yet.
So, at the end of the loop, there's a space to write the null character to.
I'm trying to understand function which copies characters from stdin but I can't understand the while loop and the code following it exactly..... How does the while loop here work??
From what I understand it means until ith character from to[] isn't equal to ith character of from[] keep on adding i am I correct??
If yes than how does the ith character be equal in both the variables ??
Here is a short code :
void copy(char to[] , char from[])
{
int i;
i = 0 ;
while ((to[i] = from[i]) != '\0')
++i;
}
Rewriting it might help:
do{
to[i] = from[i];
++i;
}while (from[i-1] != '\0') // -1 here because we incremented i in the line before and need to check the copied position
Do you understand now?
The condition in the while loop uses the fact that in C an assignment expression has a value which is the value assigned in the assignment. This means that the condition in the while loop can be implemented to have a side-effect, namely the element-wise assignment of the source to the destination. In total, the actual work of the loop is carried out in its condition, while the loop's body just increases the index i.
It's how assignments work. An assignment (a = b) returns a value (b). What you're doing there, is moving from[i] to to[i], and comparing the return value (in this case, from[i]) to the character '\0'.
The null character (0x00) terminates any string, and is thus the terminating character of the string you're copying.
I'd be careful with this code, however, as you don't check the bounds on the array and are leaving yourself open to a segmentation fault if you were to encounter a string that isn't properly null terminated, or where the to[] string is too short.
It first copy from ith character to to ith position and check that, if its the end of string. if not then it increments i(position or index that will point now to next character) and perform this operation until its matches end of string i.e '\0' .
Your code is the same as
void copy(char to[] , char from[])
{
int i;
i = 0 ;
while (from[i] != '\0')
{
to[i] = from[i];
++i;
}
to[i] = '\0';
}
So while it's not at the end of to, it continue copying from in to.
I am learning C now and I'm at the point where I don't really get what is the difference of initializing the end of the string with NULL '\0' character. Below is the example from the book:
#include <stdio.h>
#include <string.h>
int main(){
int i;
char str1[] = "String to copy";
char str2[20];
for(i = 0; str1[i]; i++)
str2[i] = str1[i];
str2[i] = '\0'; //<====WHY ADDING THIS LINE??
printf("String str2 %s\n\n", str2);
return 0;
}
So, why do I have to add NULL character? Because it works without that line as well. Also, is there a difference if I use:
for (i = 0; str1[i]; i++){
str2[i] = str1[i];
}
Thanks for your time.
The line you're referring to is added in general use for safety. When you copy values to a string you always want to be sure that it's null terminated, otherwise when reading the string it will continue past the point where you want the end of that string to be (because it doesn't know where to stop due to lack of the null terminator).
There is no difference with the alternate code you posted since you are separating only the line below the for statement to be in the loop, which happens by default anyway if you don't use the curly braces {}
In C, the end of the string is detected by the null character. Consider the string 'abcd'. If the variable in the actual binary have the next variable immediately after the 'd' character, C will think that the next characters in the platform are part of that string and you will continue. This is called buffer overrun.
Your initial statement allowing 20 bytes for str2 will usually fill it with 20 zeroes, However, this is not required and may not occur. Additionally, let us say you move a 15 character string into str2. Since it starts with 20 zeroes, this will work. However, say that you then copy a 10 character string into str2. The remaining 5 characters will be unchanged and you will then have a 15 character string consisting of the new 10 characters, followed by the five characters previously copied in.
In the code above the for loop says move the character in str1 to str2 and point to the next character. If the character now pointed to in str1 is not 0, loop back and do again. Otherwise drop out of the loop. Now add the null character to the end of the str2. If you left that out, the null character at the end of str1 would not be copied to str2, and you would have no null character at the end of str2.
This can be expressed as
i = 0;
label:
if (str1[i] == 0) goto end;
str2[i] = str1[i];
i = i + 1;
goto label;
end: /* This is the end of the loop*/
Note that the '\0' character has not yet been moved into str2.
Since C requires brackets to show the range of the for, only the first line after the for is part of the loop. If i had local scope and is lost after the loop, you would not be able to just wait to fall out of the loop and make it 0. You would no longer have a valid i pointer to tell you where in str2 you need to add the 0.
An example is C++ or some compilers in C which would allow (syntactically)
for (int i = 0; str1[i]; i++)
{
str2[i] = str1[i];
}
str2[i] = 0;
This would fail because i would be reset to whatever it happened to be before it entered the loop (probably 0) as it falls out of the loop. If it had not been defined before the loop, you would get an undefined variable compiler error.
I see that you fixed the indentation, but had the original indentation stayed there, the following comment would apply.
C does not work solely by indentation (as Python does, for example). If it did, the logic would be as follows and it would fail because str2 would be overwritten as all 0.
for (int i = 0; str1[i]; i++)
{
str2[i] = str1[i];
str2[i] = 0;
}
You should only add a \0 (also called the null byte) in the end of the string. Do as follows:
...
for(i = 0; str1[i]; i++) {
str2[i] = str1[i];
}
str2[i] = '\0'; //<====WHY ADDING THIS LINE??
...
(note that I simply added braces to make the code more readable, it was confusing before)
For me, that is clearer. What you were doing before is basically take advantage of the fact that the integer i that you declared is still available after you ran the loop to add a \0 in the end of str2.
The way strings work in C is that they are basically a pointer to the location of the first character and string functions (such as the ones you can find in string.h) will read every single char until they find a \0 (null byte). It is simply a convention for marking the end of the string.
Some further reading: http://www.cs.nyu.edu/courses/spring05/V22.0201-001/c_tutorial/classes/String.html
'\0' is used for denoting end of string. It is not for the compiler, it is for the libraries and possibly your code. C does not support arrays properly. You can have local arrays, but there is no way to pass them about. If you try you just pass the start address (address of first element). So you can ever have the last element be special e.g. '\0' or always pass the size, being careful not to mess up.
For example:
If your string is like this:
char str[]="Hello \0 World";
will you tell me what would display if you print str ?
Output is:
Hello
This will be the case in character arrays, Hence to be in safer side, it is good to add '\0'at the end of string.
If you didnt add '\0', some garbage values might get printed out, and it will keep on printing till it reached '\0'
In C, char[] do not know the length of the string. It is therefore important character '\0' (ASCII 0) to indicate the end of the string. Your "For" command will not copy '\0', so output is a string > str2 (until found '\ 0' last stop)
Try:
#include <stdio.h>
#include <string.h>
int main(){
int i;
char str[5] = "1234";
str[4] = '5';
printf("String %s\n\n", str);
return 0;
}