C: String erroneously printing twice - c

I'm playing around with C strings as in the following programme:
#include <stdio.h>
int main(void){
char *player1 = "Harry";
char player2[] = "Rosie";
char player3[6] = "Ronald";
printf("%s %s %s\n", player1, player2, player3);
return 0;
}
Which prints the following:
Harry Rosie RonaldRosie
Why is "Rosie" printing out twice?

Ronald has 6 letters, so char player3[6] leaves no space for the null-terminator character '\0'.
In your case, it printed whatever comes after Ronald in memory until a '\0' was encountered. That happened to be Rosie. You might not always be so lucky and run into an error (e.g. memory protection) before finding a '\0'.
One solution (apart from how you initialized Harry and Rosie) is to increase the number of elements by one to provide space for a trailing '\0':
char player3[7] = "Ronald";

Related

Spurious newlines+whitespace when printing substrings in C

I have a simple program that reads a pair of characters from a char[] array and prints each pair to the console, all on the same line - for some reason, some spurious newlines (and whitespace) are added to the output.
I've removed usage of str libs (apart from strlen) that may add newlines at the end of strings - but I am still lost as to what's happening.
The program:
#include <stdio.h>
#include <string.h>
char input[] = "aabbaabbaabbaabbaabb";
int main() {
int i;
char c[2];
size_t input_length = strlen(input);
for (i=0; i<input_length; i+=2) {
c[0] = input[i];
c[1] = input[i+1];
printf("%s", c);
}
printf("\n");
return 0;
}
Expected output:
aabbaabbabbaabbaabb
Output:
aabbaabbabb
aa
bbaabb
Why are there newlines and whitespace in the output? (Note that the 1st line has a single a towards the end - could not deduce why)
Using Apple clang version 11.0.0 (clang-1100.0.33.16), though I would doubt if that matters.
%s works properly if your string contains null character ('\0'). If it does not (just like your case), then printf function continues to print characters until it finds '\0' somewhere in memory. Remember that string in C is a character sequence terminated with '\0'. This is the reason why your code does not behave as you expected.
On the other hand, %c prints only one character so you can use:
printf("%c%c", c[0],c[1]);
If you persist in using %s, in this case you have to use %.2s. You probably already know that . shows precision in C. Precision in string means maximum number of characters that you want to print. So usage of .2 results in printing the first two characters in your string. No need to wait for '\0'!
printf("%.2s", c);
I also give #Tom Karzes's solution. You should change and add these lines:
char c[3];
c[2] = '\0';

Unexplainable behaviour when printing out strings in C

The following code works as expected and outputs ABC:
#include <stdio.h>
void printString (char toPrint [100]);
int main()
{
char hello [100];
hello[0] = 'A';
hello[1] = 'B';
hello[2] = 'C';
hello[3] = '\0';
printString(hello);
}
void printString (char toPrint [100])
{
int i = 0;
while (toPrint[i] != '\0')
{
printf("%c", toPrint[i]);
++i;
}
}
But if I remove the line that adds the null-character
hallo[3] = '\0';
I get random output like wBCÇL, ╗BCÄL, ┬BCNL etc.
Why is that so? What I expected is the loop in printString() to run forever because it doesn't run into a '\0', but what happend to 'A', 'B' and 'C'? Why do B and C still show up in the output but A is replaced by some random character?
You declaration of hello leaves it uninitialized and filled with random bytes
int main()
{
char hello [100];
...
}
If you want zero initialized array use
int main()
{
char hello [100] = {0};
...
}
There must have been, by pure chance, the value for \r somewhere in the memory cells following those of my array hello. That's why my character 'A' was overwritten.
On other machines, "ABC" was ouput as expected, followed by random characters.
Initializing the array with 0s, purposely omitted here, of course solves the problem.
edit:
I let the code print out each character in binary and toPrint[5] was indeed 00001101 which is ASCII for \r (carriage return).
When you declare an automatic like char hello [100];, the first thing to understand is that the 100 bytes can contain just about anything. You must assign values to each byte explicitly to do / have something meaningful.
You are terminating you loop when you find the \0 a.k.a the NUL character. Now, if you comment out the instruction which puts the \0 after the character c, your loop runs until you actually find \0.
Your array might contain \0 at some point or it might not. There are chances you might go beyond the 100 bytes still looking for a \0 and invoke undefined behaviour. You also invoke UB when you try to work with an unassigned piece of memory.

iteration collect char in C

Here's my code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int i,j,n;
scanf("%d",&n);
n*=n;
char str[n];
for(i=0;i<n;i++){
str[i]='*';
}
printf("%s",str);
printf("\n%d",strlen(str));
return 0;
}
I input 2 and this is the output I got:
2
****ú#
7
In line 2 it has some weird characters that show in console (U+0013 or control-S between ú and #), but it didn't show here.
Could you explain this to me?
printf("%s", str) assumes that str points to a NUL-terminated char array (aka "C string"). str is not NUL terminated in your case, so printf is running off the end of the buffer, resulting in undefined behavior.
To fix this you need to do two things:
Allocate an additional byte for the NUL terminator
NUL-terminate the array when you're finished writing to it
char str[n+1]
for(i=0;i<n;i++){
str[i]='*';
}
str[n] = '\0';
You are printing with %s format specifier which expects a C string(char array with NUL character at the end). You need to make the last character \0 to make printf recognize the end of the string and stop printing. So allocate one more character in the array and set the last character to \0.
char str[n+1];
str[n] = '\0`;
You need to NUL-terminate your string, like so:
char str[n+1]; /// <<<
for(i=0;i<n;i++){
str[i]='*';
}
str[n]='\0'; /// <<<

While entering a string in an single element of array in c why does the following code gives the shown output?

#include <stdio.h>
int main(int argc, char *argv[])
{
int i, n, m;
scanf("%d %d", &n, &m);
char s[m][n];
for (i = 0; i < m; i++) {
printf("the string --\n");
scanf("%s", s[i]);
}
for (i = 0; i < m; i++) {
printf("the strings are %s \n",s[i]);
printf("\n");
}
return 0;
}
The output is:
2 2
the string --
10
the string --
11
the strings are 1011
the strings are 11
Why is the first string 1011 instead of 10?
In C, strings are represented as a sequence of char values, terminated by a null character (0 or '\0'). This means that to store a two-character string, you need space for three characters: the two characters of string content, plus the null terminator character.
Here, you've only allocated enough space for two characters in each string, but you need space for three.
So, it reads the first string into the array s[0], but the null terminator doesn't fit, and so it overflows into the second array s[1]. Now your array of arrays s looks like this: {{'1', '0'}, {'\0', ... }}.
Then, when it reads the second string into the array s[1], it overwrites the overflowed null terminator from before. And the null terminator for the second string doesn't fit into its own array, so it overflows again into the rest of the stack. The program might crash here, or corrupt other data, because you're overflowing past the end of the array.
So now your array of arrays s ends up looking like this: {{'1', '0'}, {'1', '1'}}, followed by a '\0' somewhere after the end of the array.
When printf goes to read your first string, it prints characters until it finds a null terminator. But it doesn't find one in the first string, so it keeps going, and hits the second string. It doesn't find one there either, and continues past the end of the array. In your case, luckily a null terminator was right there, but for all we know there could be something else.
To fix this, you need to allocate an extra character per string on line 9, for the null terminator:
char s[m][n+1];
There's another problem here, however. What if your input gives you the wrong length? For example, what if your input says 2 3, i.e. that the following strings will have a length of 3, but gives you the string foobar, which is 6 characters? Your code right now would overflow the buffer when it read that string, because it doesn't ensure it's the right length.
One way to avoid this would be to use gets_s instead of sscanf() for reading the strings on line 13:
gets_s(s[i], n+1);
This will read at most n characters, so avoid crashing your program or creating a security issue. However, gets_s is a C11 function, so you may not be able to use it.
You must set column size to 3 if you insert 2 characters per string, 4 for 3 characters per string and so on.
This because string in C have a termination character ('\0') in the last position.
#include <stdio.h>
int main(int argc, char *argv[])
{
int i, n, m;
scanf("%d %d", &n, &m);
char s[m][n+1];
for (i = 0; i < m; i++) {
printf("the string --\n");
scanf("%s", s[i]);
}
for (i = 0; i < m; i++) {
printf("the strings are %s \n",s[i]);
printf("\n");
}
return 0;
}
%s expects null terminated strings as an argument. When first string is read by scanf, there is not enough space for the null terminator within the allocated memory of first string. It will goes to the space next to the allocated space. Writing to unallocated space invokes undefined behavior.
While printing the strings with %s specifier, printf write the string character by character till it finds a null terminator '\0'. Here it may be the case that both the strings 10 and 11 are stored one after another in memory, so printf writes the first string till it read the null character of second string.
Input n as 3 and you will get the desire results.
In my opninion using scanf to read strings is just pure evil.
That said the array s[m][n] is just s[m*n] of course.
That said that evil thing scanf is going to load on *s[0] 10\n\0 and on *s[1*n] or *s[2] 11 and *s will be 1011\n\0
And this is a monument to bad C coding. I guess it's just an example but if I was asked this question i would say: "Come on, get me real things"

Need help finding bug, if string input is composed all of same character one output character is corrupt

reverser() reverses a cstring (not in place). 99% of the time it works but some input corrupts it for example it appears if aStr2[] is assigned a string made up of the same character it will have an error.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* reverser(const char *str);
int main()
{
char aStr[] = "aaa";
char aStr2[] = "cccccc";
printf("%s %s", aStr, aStr2);
char* tmp = reverser(aStr2);//tmp now has garbage
printf("\n%s", tmp);
printf(" %s", aStr2);
return 0;
}
char* reverser(const char *str)
{
char* revStr = (char*)malloc(strlen(str));
int i;
for(i = strlen(str)-1; i >= 0; i--)
{
revStr[strlen(str)-1-i] = str[i];
}
return revStr;
}
Gives
aaa cccccc
cccccc9 cccccc
Process returned 0 (0x0) execution time : 0.068 s
Press any key to continue
Notice the 9 that shouldn't be there.
Change this malloc to strlen(str) + 1 , plus 1 for '\0'
char* revStr = (char*)malloc(strlen(str) + 1);
and after the for loop
revStr[strlen(str)+1] = '\0';
Your problem is that you don't put the string terminator in your reversed string. All strings in C are actually one extra character that isn't reported by strlen, and that is the character '\0' (or plain and simple, a zero). This tells all C functions when the string ends.
Therefore you need to allocate space for this extra terminator character in your malloc call, and add it after the last character in the string.
There are also a couple of other problems with your code, the first is that you should not cast the return of malloc (or any other function returning void *). Another that you have a memory leak in that you do not free the memory you allocate. This last point doesn't matter in a small program like the one you have here, but will be an issue in larger and longer running programs.
You haven't null-terminated your reversed string. You need to set the final index of revStr[] to 0.

Resources