Every time I run this it stops working when I enter the string.I use visual studio 2013.Here's my code:
#include<stdio.h>
#include<stdlib.h>
int main(void){
char x[10];
scanf("%s",x);
printf("%s",x);
system("pause");
return 0;
}
What probably happens is that the stdout output buffer is not flushed. By default stdout is line buffered meaning the output written to stdout will not actually be output until there is a newline.
So the solution is simply to write a newline:
printf("%s\n",x);
Also note that you can't write input more than nine characters, or you will write beyond the bounds of the array x and have undefined behavior. The number nine comes from your array being ten char big, and strings in C needs an extra character to terminate the string, so the largest string you can put in x is ten minus one.
Try this:
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
char *buffer = calloc(1024, sizeof(char)); // you could replace sizeof(char) with 1 if you wanted
scanf("%s", buffer);
unsigned lng = strlen(buffer);
buffer = realloc(buffer, (lng + 1)); // note sizeof(char) == 1, so no need to add it
printf("%s\n", buffer);
system("pause");
free(buffer);
return (0);
}
If you put more than 9 characters into x then your program will give undefined behavior. Suppose, you input abcdefghi, then actual content of x is follows:
x[0] = 'a'
x[1] = 'b'
x[2] = 'c'
x[3] = 'd'
x[4] = 'e'
x[5] = 'f'
x[6] = 'g'
x[7] = 'h'
x[8] = 'i'
x[9] = '\0'
scanf() of string will automatically put '\0' at the end. When you are printing using %s, your printf() method will print until it reaches '\0'. But if in the array there is no '\0' character, then it may crash or print garbage value form system dump, because the printf() will try to print beyond your array indexing.
Related
I have recently started learning C and I got into this problem where printf() prints an array I didn't ask for.
I was expecting an error since I used %s format in char array without the '\0', but below is what I got.
char testArray1[] = { 'a','b','c'};
char testArray2[] = { 'q','w','e','r','\0' };
printf("%c", testArray1[0]);
printf("%c", testArray1[1]);
printf("%c\n", testArray1[2]);
printf("%s\n", testArray1);
the result is
abc
abcqwer
thanks
The format "%s" expects that the corresponding argument points to a string: sequence of characters terminated by the zero character '\0'.
printf("%s\n", testArray1);
As the array testArray1 does not contain a string then the call above has undefined behavior.
Instead you could write
printf("%.*s\n", 3,testArray1);
or
printf("%.3s\n", testArray1);
specifying exactly how many elements of the array you are going to output.
Pay attention to that in C instead of these declarations
char testArray1[] = { 'a','b','c'};
char testArray2[] = { 'q','w','e','r','\0' };
you may write
char testArray1[3] = { "abc" };
char testArray2[] = { "qwer" };
or that is the same
char testArray1[3] = "abc";
char testArray2[] = "qwer";
In C++ the first declaration will be invalid.
%s indeed stop when encountered \0, but testArray1 didn't have that \0, so it keeps printing the following bytes in the memory.
And the compiler magically(actually intentionally) places the testArray2 next to testArray1, the memory is like:
a b c q w e r \0
^ testArray1 starts here
^ testArray2 starts here
And the %s will print all of those chars above until it meets a \0.
You can validate that by:
printf("%d\n", testArray2 == testArray1 + 3);
// prints `1`(true)
As your question, there was no error because the a ... r \0 sequece in memory is owned by your process. Only the program is trying to access an address not owned by it, the OS will throw an error.
Add zero at the end of first array:
char testArray1[] = { 'a','b','c', 0 };
Otherwise printf continues with memory after 'c' until zero byte and there is the second array.
PS: zero 0 is 100% identical to longer ASCII '\0'.
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.
I'm trying to print out a memory address backwards like in a little endian machine, but for some reason my program is outputting both char arrays in my program.
char address[8];
char result[16];
scanf("%s", address);
int x = 1;
for(x; x<5; x++)
{
int y = 4*x;
int z = 8 - 2*x;
result[y-4] = '\\';
result[y-3] = 'x';
result[y-2] = address[z];
result[y-1] = address[z+1];
}
printf("%s", result);
for example, if I input "12345678" it outputs "\x78\x56\x34\x1212345678"
I want the "\x78\x56\x34\x12", but I don't understand why the "12345678" is also printed.
You forget to terminate the string. In fact, your array is to small for the terminator, you need it to be 17 characters, then do result[16] = '\0';.
Oh, and you have an out-of-bound error in your code as well, as if you enter 8 characters for the input then scanf will write 9 characters to the 8-character array.
%s //
in C %s expects a pointer to a string, unlike %d or %c(these expect variables with integers or characters), so your pointer must be null terminated, so the program knows where in memory it must stop printing, or else your are printing random stuff in memory
main()
{
char *x="girl";
int n,i;
n=strlen(x);
*x=x[n];
for(i=0;i<n;i++)
{
printf("%s \n",x);
x++;
}
}
What is the output?
Please explain the output.......................
o/p is :
irl
rl
l
The output is undefined behaviour. You modified a string literal.
As others have pointed out, the program as written has undefined behaviour.
If you make a small alteration:
char x[] = "girl";
then I believe it is legal, and possible to explain. (EDIT: Actually there are still problems with it. It's int main(), and you should return 0; at the end. You also need to #include <string.h> because you are using strlen, and #include <stdio.h> because you are using printf.)
The line
*x = x[n];
sets x[0] (i.e. *x) to x[4] (which happens to be the string terminator '\0'). Thus the first string to be printed is the empty string, because the very first character is the string terminator.
We then loop through the string, one character at a time, printing the substrings:
irl
rl
l
While the result is undefined behavior, as DeadMG said, let's assume you declared x as char x[] = "girl".
You assign 4 to n (since the length of the word "girl" is 4), and you assign the value in x[4] to *x (which is x[0]), but this value is '\0' (null terminator)
Now you loop and print the word from x to the next null terminator, but the first time, the first char is the null terminator, so you get nothing. after that you print the word from incrementing index.
g i r l \0
*x = x[4]:
\0 i r l \0
^ ^ ^ ^
it1 it2 it3 it4 // << Where does x points to in each iteration of the for loop
The code is distictly suspect. *x=x[n] attempts to overwrite the literal "girl", and the effect will vary between platforms and compilers. More correctly it should be declared as:
const char *x = "girl";
and then it will not (should not) compile.
How can I access s[7] in s?
I didn't observe any difference between strncpy and memcpy. If I want to print the output s, along with s[7] (like qwertyA), what are the changes I have to made in the following code:
#include <stdio.h>
#include <stdlib.h>
int main() {
char s[10] = "qwerty", str[10], str1[10];
s[7] = 'A';
printf("%s\n", s);
strncpy(str, s, 8);
printf("%s\n", str);
memcpy(str1, s, 8);
printf("%s\n", str1);
return 0;
}
Output:
qwerty
qwerty
qwerty
Others have pointed out your null-termination problems. You need to understand null-termination before you understand the difference between memcpy and strncpy.
The main difference is that memcpy will copy all N characters you ask for, while strncpy will copy up to the first null terminator inclusive, or N characters, whichever is fewer.
In the event that it copies less than N characters, it will pad the rest out with null characters.
You are getting the output querty because the index 7 is incorrect (arrays are indexed from 0, not 1). There is a null-terminator at index 6 to signal the end of the string, and whatever comes after it will have no effect.
Two things you need to fix:
Change the 7 in s[7] to 6
Add a null-terminator at s[7]
The result will be:
char s[10] = "qwerty";
s[6] = 'A';
s[7] = 0;
Original not working and fixed working.
As for the question of strncpy versus memcpy, the difference is that strncpy adds a null-terminator for you. BUT, only if the source string has one before n. So strncpy is what you want to use here, but be very careful of the big BUT.
Strncpy will copy up to NULL even you specified the number of bytes to copy , but memcpy will copy up to specified number of bytes .
printf statement will print up to NULL , so you will try to print a single charater , it will show ,
printf("\t%c %c %c\t",s[7],str[7],str1[7]);
OUTPUT
7 7
To make "qwertyA" you need to set s[6] = 'A' and s[7]='\0'
Strings are indexed from 0, so s[0] == 'q', and they need to be null terminated.
When you have:
char s[10] = "qwerty";
this is what that array contains:
s[0] 'q'
s[1] 'w'
s[2] 'e'
s[3] 'r'
s[4] 't'
s[5] 'y'
s[6] 0
s[7] 0
s[8] 0
s[9] 0
If you want to add an 'A' to the end of your string, that's at index 6, since array indexes start at 0
s[6] = 'A';
Note that when you initialize an array this way, the remaining space is set to 0 (a nul terminator), While not needed in this case, generally be aware that you need to make your strings nul terminated.
e.g.
char s[10];
strcpy(s,"qwerty");
s[6] = 'A';
s[7] = 0;
In the above example "qwerty" , including its nul terminator is copied to s. s[6] overwrites that nul terminator. Since the rest of s is not initialized we need to add a nul terminator ourselves with s[7] = 0;
As explained by Philip Potter, the main difference is that memcpy will copy all N characters you ask for, while strncpy will copy up to the first null terminator inclusive, or N characters, whichever is fewer. In the event that it copies less than N characters, it will pad the rest out with null characters.
Execute the below code and check the difference, you might find it useful.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char s[10] = "qwer\0ty", str[10], str1[10];
s[7] = 'A';
printf("%s\n",s);
strncpy(str,s,8);
printf("%s\n",str);
memcpy(str1,s,8);
printf("%s\n",str1);
for(int i = 0; i<8; i++)
{
printf("%d=%c,",i,str[i]);
}
printf("\n");
for(int i = 0; i<8; i++)
{
printf("%d=%c,",i,str1[i]);
}
return 0;
}
Output:
qwer
qwer
qwer
0=q,1=w,2=e,3=r,4=,5=,6=,7=,
0=q,1=w,2=e,3=r,4=,5=t,6=y,7=A,