Reverse of a string in C program? - c

I found this program for reversing this program online.
I have just started learning C.
I am not able to understand few things here.
Why while is ended with ;
what does while(str[++i]!='\0'); mean?
Is rev[j++] = str[--i]; same as writing j++; and i--; inside the while loop?
This is the program:
#include<stdio.h>
int main(){
char str[50];
char rev[50];
int i=-1,j=0;
printf("Enter any string : ");
scanf("%s",str);
while(str[++i]!='\0');
while(i>=0)
rev[j++] = str[--i];
rev[j]='\0';
printf("Reverse of string is : %s",rev);
return 0;
}

while(str[++i]!='\0');
is equivalent to
while(str[++i]!='\0')
/*do nothing*/;
which is equivalent to
++i;
while (str[i]!='\0') {
++i;
}
and
while(i>=0)
rev[j++] = str[--i];
is equivalent to
while (i>=0) {
--i;
rev[j] = str[i];
++j;
}
Note that i is decremented before the statement since --i is a pre-decrement, whereas j is incremented after the statement since j++ is a post-increment.

I'll try to answer as best as i can...
Why while is ended with ;
This is valid syntax, it's often used to cause the program to wait at that line until a certain flag is set in an embedded scenario. In this case it's used to find the length of the string.
All strings are terminated with a null character, which is '\0', and the preincrement on i means that after that line i will hold the value for the length of the string.
Effectively its equivalent to this:
/* If the ith position of the string is not the end */
while (str[i] != '\0') {
/* Increment i and repeat */
i = i + 1;
}
The main concept here is the difference between postincrement and preincrement operators - might be worth reading up on that.
What does while(str[++i]!='\0'); mean?
See above.
3.Is rev[j++] = str[--i]; same as writing j++; and i--; inside the while loop?
If you're asking if its in the while loop, its entirely equivelant to:
while(i>=0) {
rev[j++] = str[i--];
}
Since there is only a single operation in the while loop the brackets aren't needed.
Just a note, and this is entirely subjective, but the majority of coding standards I've come accross use brackets even in this scenario.
Your questions seem to be related mainly to the syntax of C - it might be worth getting a book out or watching some tutorials to familiarise yourself with it.

The ; is there to close the loop
2: while(str[++i]!='\0'); means "Go throuch each char of str until the \0 char is reached".\0 is the ending char of a string
3: Yes

First of all, while(str[++i]!='\0'); increments i until it finds the last character. In C all strings end with \0 or NULL (both are the same).
The second one, no. It is not the same --i than i++.
Check the following code snipet:
int a,b,x=10,y=10;
a = x--;
b = --y;
At the end of execution, a = 10 but b = 9. This is because --y is a pre-decrement. It decrements the value first and then assigns its value to b.

Here's a commented version of the program:
// Include standard input output functions
#include<stdio.h>
// declares the main function. It accept an undefined number
// of parameters but it does not handles them, and returns an integer
int main(){
// declares tho arrays of 50 characters initialized with random values
char str[50];
char rev[50];
// declare and initialize two integer variables
int i=-1,j=0;
printf("Enter any string : ");
scanf("%s",str);
// executes the ';' instruction while the condition is satisfied.
// ';' is an empty statement. Thus do nothing.
// The only action executes here, is the increment of the i variable with
// a preincrement. Because the i variable was initialized with
// -1, the first control start checking if str[0] != '\0'
// If the post increment operator was used, the variable must
// have been initialized with 0 to have the same behaviour.
while(str[++i]!='\0');
// at the end of the previous while, the i variable holds the
// str lenght + 1 (including the '\0')
// starting from the end (excluding the '\0', using the pre-decrement on the i variable)
// assign to rev[j] the variable of str[i], then (post increment)
// increment the j variable
while(i>=0)
rev[j++] = str[--i];
// now j is equals to str lenth +1
// therefore in this position add the null byte
rev[j]='\0';
// print result
printf("Reverse of string is : %s",rev);
// return 0 to the OS
return 0;
}

; means the end of a statement in c.
while(condition)
{
//do something
}
do something means at least one statement should be executed. For this the ; is used here.
while(str[++i]!='\0'); '\0' represents end of the string. Here the loop is terminated at the end of the string and ++i increases i.
Is rev[j++] = str[--i]; same as writing j++; and i--; inside the while loop?
Yes. But as --i increases i before executing rev[j++] = str[--i] so i-- should be before rev[j] = str[i] and j++ increases j after executing rev[j++] = str[--i] so j++ should be after rev[j] = str[i]

The key here is understanding the difference in behaviour between prefix (++i), and postfix (i--) operators.
The prefix operator will increment its operand (i), and then evaluate to the new value.
The postfix operator will evaluate to its operands current value, and then increments the operand afterwards.
As for:
int i = -1;
while (str[++i] != '\0');
This is a loop with no block, because all of the statements can be expressed in the conditional. On each iteration:
Increment i by one.
Get the char at the position i evaluates to.
continue if it is not the NUL character.
This might be better understood when written as:
int i = -1;
do {
i++;
} while (str[i] != '\0');
The result of this operation is that i now holds the position of the NUL character in the string, since all valid character strings must end with the NUL character.
In the next section of the program, the prefix operator is used again to immediately get the character one position before the NUL character, and then one position before that, and so on, until we get the first character of the string, and then we're done.
while(i>=0)
rev[j++] = str[--i];

Why while is ended:
while(str[++i]!='\0')
Once str is an asciiz string it ends with a '\0' character. So while will end whenever the while reaches the end of the string.
The line above means:
=> ++i : Increments the string index before getting the corresponding character.
=> Checks if str[index] != '\0' // End of the string reached
On the end of while the i variable will contain the string length (excluding the '\0' character).
It would be easier to use this:
i = strlen(str);
Is rev[j++] = str[--i]; same as writing j++; and i--; inside the while loop?
No.
This line is the same as:
while(i>=0)
{
i = i - 1;
rev[j] = str[i];
j = j + 1;
}
--i : Gets the string character after decrementing i.
If you changed to i-- the code would get the str[i] before decrementing i, but it is not what you want.

Related

Iterate through an array of characters in C

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;
}

Trimming a string, why is there a semicolon after while loop?

So I was reading some code from my C-programming course, and came across to this question asking:
Trim the string: " make trim " into "make trim".
This was the code:
#include <stdio.h>
#include <string.h>
#define MAX 100
void trim(char *s) {
char *d = s;
while (isspace(*s++))
;
s--;
while (*d++ = *s++)
;
d--;
while (isspace(*--d))
*d = 0;
}
int main() {
char s[MAX];
gets(s);
printf("[%s] -> ", s);
trim(s);
printf("[%s]", s);
return 0;
}
So, what I want to ask is, what are
while (isspace(*s++))
;
s--;
while (*d++ = *s++)
;
d--;
while (isspace(*--d))
*d = 0;
the incremented string (*s++), the ; after the while() loop doing, and how do they work?
Thanks in advance
The empty body is simply because the condition of the while has a side effect so the whole loop is encapsulated in the condition and there is nothing to put in the body.
So:
while (isspace(*s++))
;
Is the same as:
while (isspace(*s)) { s++; }
They put the semicolon on the extra line to make it clearer that the loop is empty (otherwise you might think the next real statement is part of the loop). Other people might put a comment there as well, or even rewrite it to avoid the body being empty.
Code with some descriptive comments:
This loop picks up each character in turn, increments s to point to the next and continue doing that until the character we picked up is not a whitespace character. Note that because it increments before the test it will increment s one time too many, so that's why there's a decrement after the loop ends.
while (isspace(*s))
;
s--;
This would have been equivalent and doesn't need the separate decrement:
while (isspace(*s)) { s++; }
This loop copies each character from s so starting at the first non-whitespace character to d which points initially at the start of the string. If there was no leading whitespace it copies the character directly on top of itself. The loop ends after we copied a null character, i.e. the end of the string. As before there is one increment too many so we have to decrement d to endpointing at the null character:
while (*d++ = *s++)
;
d--;
This loop decrements d and then picks up whatever character it now points at. If it is a whitespace character then it replaces it with a null character. Note that there is no check for hitting the start of the string, so if the initial string was empty (i.e. a single null character) it will happily work backward through memory corrupting bytes outside the string as long as they are whitespace:
while (isspace(*--d))
*d = 0;
You can rewrite:
while (condition);
as follows:
while (condition) { /* empty block */ }
If the condition contains statements to be executed these will be executed and evaluated as long as the condition meets, this is the case in your example.
1.
In your case the first while loop:
while (isspace(*s++));
loops until it founds the first character being no space (which is the m of make in this case). As there is a postfix increment it will point to a of make:
" make trim \0"
^ ^
d| s|
2.
After that s is decremented (s--;) pointing at the start (m of make).
" make trim \0"
^ ^
d| s|
3.
The second while loop writes the string beginning with make to the beginning of the character buffer because d is pointing to the beginning due it's set at the beginning of the function (char *d = s;). This is done until the null terminator '\0' is reached:
while (*d++ = *s++)
could be rewritten as:
while ((*d++ = *s++) != '\0')
and will result in (note that null terminator '\0' is also written):
"make trim \0 \0"
^ ^
d| s|
4.
Now d will be decremented (d--;) pointing at the space before the null terminator '\0'.
"make trim \0 \0"
^ ^
d| s|
5.
The last while loop will search for the first character being no space (with d) but in reverse order:
while (isspace(*--d))
*d = 0;
It will write multiple null terminator '\0' until it find a character being no space.
"make trim\0\0\0\0 \0"
So the resulting string will be:
"make trim"
It isn't necessary to write multiple null terminator '\0' here but instead one null terminator '\0' would be enought after m of trim.
while (isspace(*s++))
;
is just equal to
while (isspace(*s++));
Don't let ; at a new line confuse you. All in all it is just a way to emphasize that this while loop does not have a body. And a while loop that has no body is performing until it's isspace(*s++) condition is false. Also isspace(*s++) it is an only calculation that should be done for this loop, so that is why there is no need to have a body for this loop.
When you read code like this it is easy to miss this ; and then you can make a wrong assumption that expression directly below the loop is a loop body, but just not surrounded by {}:
while (isspace(*s++));
s--;
while (isspace(*s++))
s--;
See the difference? In second example s-- is a while loop's body. To attract attention programmer can write:
while (isspace(*s++))
;
s--;
to clarify and emphasize his real intentions.

what is wrong with my understanding of strings ie character arrays ending with '\0' element in C programming

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.

Trying to understand a simple C copy function

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.

what is wrong with the while loop here ? C basics

I am trying to count the number of letters of a word before the space. For eg. "Hello how" is my input string and I am trying to count the number of letters in the first word.
#include<stdio.h>
#include<string.h>
int main()
{
char a[30];
int count = 0;
printf("Enter the string.\n"); // Enter hello how as string here.
gets(a);
for ( i = 0; a[i] != '\0'; i++ )
{
while( a[i+1] != ' ' )
count++;
}
printf("%d\n",count);
}
This is a small part of a bigger code, I am actually expecting the value of count to be 5 but it gets into some sort of infinite loop which I am unable to figure out. If I use if instead of while , I get the expected answer. I know gets is not very reliable and I will not use once I get better at programming so it will be kind of you to post your answer about the loop instead of gets. Thank You.
The NUL character is written with a backslash (\), not forward slash (/).
for (i = 0; a[i] != '\0'; i++)
Furthermore, the inner loop will not terminate because you're not incrementing i.
while (a[i] != ' ') {
i++;
count++;
}
Actually, you should not really have two loops. One loop is all you need.
for (i = 0; a[i] != '\0' && a[i] != ' '; i++) {
count++;
}
The expression within the while statement does not depend on count. So with every iteration of the while loop the count gets incremented, but that has no influence on the while conditional, hence it will loop ad infinitum or never, depending on the character at a[i+1].
In addition to that, the conditional statement for the for loop is not written correctly either. The string escape for a NUL character is \0 (backslash). Or you can just compare against a 0 literal, which has exactly the same outcome (though when it comes to the subtleties of C it does not mean exactly the same, but that's splitting hairs).
Use '\0' instead of '/0' in the for loop condition and also the while loop condition will never be false because i remains the same

Resources