Trying to understand a simple C copy function - c

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.

Related

while loop with only parentheses syntax, in c

i just saw this "while(something);" syntax. i googled this but did not found anything. how does this work? especially second while in the example code confuses me.
this code is a program to concatenate two strings using pointer.
#include <stdio.h>
#define MAX_SIZE 100 // Maximum string size
int main()
{
char str1[MAX_SIZE], str2[MAX_SIZE];
char * s1 = str1;
char * s2 = str2;
/* Input two strings from user */
printf("Enter first string: ");
gets(str1);
printf("Enter second string: ");
gets(str2);
/* !!!!!!!!!!!!!!!!! this is it!!!!!!!!!!!!!!!!!!!! Move till the end of str1 */
while(*(++s1));
/* !!!!!!!!!!!!!!!!! this is it!!!!!!!!!!!!!!!!!!!! Copy str2 to str1 */
while(*(s1++) = *(s2++));
printf("Concatenated string = %s", str1);
return 0;
}
The while loop is defined in C the following way
while ( expression ) statement
In this while loop
while(*(++s1));
the statement is a null statement. (The C Standard, 6.8.3 Expression and null statements)
3 A null statement (consisting of just a semicolon) performs no
operations.
So in the above while loop the expression is evaluated cyclically until it logically becomes false.
Pay attention to that this while loop has a bug.;)
Let's assume that the pointed string is empty "". In memory it is represented the following way
{ '\0' }
So initially s1 points to the terminating zero.
But before dereferencing it is incremented in the expression of the while loop
while(*(++s1));
^^^^
and after that points in the uninitialized part of the character array after the terminating zero '\0'. So the loop can invoke undefined behavior.
It would be more correctly to rewrite it like
while( *s1 != '\0' ) ++s1;
In this case after the loop the pointer s1 will point to the terminating zero '\0' of the source string.
This while loop where the statement is again a null statement
while(*(s1++) = *(s2++));
can be rewritten the following way
while( ( *s1++ = *s2++ ) != '\0' );
that is in essence the same as
while( ( *s1 = *s2 ) != '\0' )
{
++s1;
++s2;
}
(except that if the terminating zero was encountered and copied the pointers are not incremented)
That is the result of the assignment ( *s1 = *s2 ) is the assigned character that is checked whether it is equal already to the terminating zero character '\0'. And if so the loop stops and it means that the string pointed to by the pointer s2 is appended to the string pointed to by the pointer s1.
Pay attention to that the function gets is unsafe and is not supported by the C Standard. Instead you should use the function fgets as for example
#include <string.h>
#include <stdio.h>
//...
printf("Enter first string: ");
fgets(str1, sizeof( str1 ), stdin );
str1[ strcspn( str1, "\n" ) ] = '\0';
The last statement is used to remove the new line character '\n' that can be appended to the entered string by the function call.
Also you need to check in the program whether there is enough space in the array str1 and the string stored in the array str2 can be indeed appended to the string stored in the array str1.
while(*(++s1)); is an obfuscated and bugged way of writing while(*s1 != '\0') { s1++; }.
(It should have been while(*(s1++)); to behave as expected, but that too is wrong since it increments the pointer upon failure and won't work with an empty string.)
while(*(s1++) = *(s2++)); is an obfuscated (and likely inefficient) way of writing strcpy(s1,s2);.
The whole program is an obfuscated way of writing strcat(s1, s2);. You can replace both of these buggy while loops with that single function call.
Generally while(something); is bad practice, to the point where compilers might even warn for it, since it isn't clear if the semicolon ended up there on purpose or by a slip of the finger. Preferred style is either:
while(something)
; // aha this was surely not placed there by accident
or
while(something){}
or
while(something)
{}
++s1 advances (or increments) the pointer, before the while checks it value
The while loop will iterate through the string until it will reach the null terminator, since while(NULL) is equal to while(false) or while(0)
The loop
while(*(++s1));
doesn't need a body because everything is done inside the loop condition.
Therefore the loop body is an empty statement ;.
The loop consists the following steps:
++s1 increment pointer
*(...) dereference pointer, i.e. get the data where the pointer points to.
use the value as the condition (0 is false, everything else is true)
The loop can be rewritten as
do
{
++s1;
}
while(*s1); // or while(*s1 != '\0');
Similarly, the other loop
while(*(s1++) = *(s2++));
can be written as
do
{
char c;
*s1 = *s2;
c = *s1;
s1++;
s2++;
}
while(c != '\0')
Note that the original loop condition contains an assignment (=), not a comparison (==). The assigned value is used as the loop condition.

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

Reverse of a string in C program?

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.

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.

understanding strlen function in C

I am learning C. And, I see this function find length of a string.
size_t strlen(const char *str)
{
size_t len = 0U;
while(*(str++)) ++len; return len;
}
Now, when does the loop exit? I am confused, since str++, always increases the pointer.
while(*(str++)) ++len;
is same as:
while(*str) {
++len;
++str;
}
is same as:
while(*str != '\0') {
++len;
++str;
}
So now you see when str points to the null char at the end of the string, the test condition fails and you stop looping.
C strings are terminated by the NUL character which has the value of 0
0 is false in C and anything else is true.
So we keep incrementing the pointer into the string and the length until we find a NUL and then return.
You need to understand two notions to grab the idea of the function :
1°) A C string is an array of characters.
2°) In C, an array variable is actually a pointer to the first case of the table.
So what strlen does ? It uses pointer arithmetics to parse the table (++ on a pointer means : next case), till it gets to the end signal ("\0").
Once *(str++) returns 0, the loop exits. This will happen when str points to the last character of the string (because strings in C are 0 terminated).
Correct, str++ increases the counter and returns the previous value. The asterisk (*) dereferences the pointer, i.e. it gives you the character value.
C strings end with a zero byte. The while loop exits when the conditional is no longer true, which means when it is zero.
So the while loop runs until it encounters a zero byte in the string.

Resources