I have this code, which doubles every letter in nabucco
:
#include<stdio.h>
#include<string.h>
int main(){
char string1[20] = "nabucco";
char string2[40];
int j=-1;
for(int i=0; i<strlen(string1);i ){
j ;
string2[j] = string1[i];
j ;
string2[j] = string1[i];
}
printf("string1=\t%s\n",string1);
printf("string2=\t%s\n",string2);
}
string2
is set to and prints nnaabbuuccccoo
.
However, when I try to set j=0;
string2
prints (and is presumably set to) nothing.
If j=0
before going into the loop, then j is incremented to 1 in the for
loop, which starts off setting the second element of the empty string2
. Is there something behind the scenes preventing any element other than the first from being set? I do not understand what is causing this behavior.
CodePudding user response:
The program as posted has undefined behavior since you don't put a null terminator in string2
.
If you start with j=0
, you never set the value of string2[0]
since you increase j
before using it, so that position remains indeterminable.
Possible fix:
#include<stdio.h>
#include<string.h>
int main(){
char string1[20] = "nabucco";
char string2[40];
size_t j=0;
for(size_t i=0, len = strlen(string1); i<len; i ) {
string2[j ] = string1[i]; // increase j "after" using the current value
string2[j ] = string1[i];
}
string2[j] = '\0'; // add null terminator
printf("string1=\t%s\n",string1);
printf("string2=\t%s\n",string2);
}
An alternative could be to initialize string2
when you create it:
#include<stdio.h>
#include<string.h>
int main(){
char string1[20] = "nabucco";
char string2[40] = {0}; // zero initialized
for(size_t i=0, j=0, len = strlen(string1); i<len; i ) {
string2[j ] = string1[i];
string2[j ] = string1[i];
}
printf("string1=\t%s\n",string1);
printf("string2=\t%s\n",string2);
}
CodePudding user response:
You increment the counter before using it the first time, so if you set j=0
you do j
before using it first, which means you start with string2[1]
.
You can change it like so:
int j=0;
for(int i=0; i<strlen(string1);i ){
string2[j] = string1[i];
j ;
string2[j] = string1[i];
j ;
}
CodePudding user response:
When you do this
printf("string2=\t%s\n",string2);
and string2
was set from the second character, this is a sort of undefined behaviour (see also this answer). string2[0]
was not initialised, and could contain anything (from sensitive data to something that can't be parsed successfully by other functions - okay, here it is a single character; in other circumstances it could be more than that, if you started with j=20
for example). Which is why undefined behaviour is to be avoided at all costs.
In this case, the quirks of platform, compiler and process made it so the first character is a zero. Since C strings are zero-terminated, and string2
begins with a zero, printf
prints nothing. If you printed something like this, where "." is a 0 character (ASCII 0),
"nnaa.bbuuccoo."
you would get only "nnaa". By the same token, printf'ing ".nnaabbuuccoo" gets you nothing.
If you were to print string2
starting at the second character, you'd get different results:
printf("string2=\t%s\n",string2 1);
CodePudding user response:
After the for loop the character array string2
does not contain a string because you forgot to append it with the terminating zero character '\0'
. So this call of printf
printf("string2=\t%s\n",string2);
invokes undefined behavior.
A simplest approach to resolve the problem is to initialize the array in its declaration. For example
char string2[40] = "";
As for this statement
However, when I try to set j=0; string2 prints (and is presumably set to) nothing.
then within the for loop the variable j
is at once incremented.
int j = 0;
for(int i=0; i<strlen(string1);i ){
j ;
string2[j] = string1[i];
//...
So the first character of the array string2
is not set.
In this case it is better to write the for loop the following way
size_t j = 0;
for ( size_t i = 0, n = strlen( string1 ); i < n; i ){
string2[j ] = string1[i];
string2[j ] = string1[i];
}
string2[j] = '\0';
CodePudding user response:
It is because strings in C are null terminated. So when you set j=0 outside of loop, you skip setting first character which remains null.