How '\0' is treated in printf? - c

#include<stdio.h>
#include<conio.h>
int main()
{
char arr[]="\0";
if(printf("%s",arr))
printf("not empty");
else
printf("empty");
return 0;
}
Here I thought that \0 will be taken as 1 byte in the array and printf will return 1 byte, so not empty should be printed. But output was empty that means printf returned 0. So how printf takes \0?

char arr[]="\0";
Here, the char array arr has two elements, both of them are \0. When you use:
printf("%s",arr)
%s in format specifier tells printf to look for a string. And printf found it, but it stops printing after seeing the first \0, which is the first character. That's why printf prints nothing, because arr is an empty string.
The return value of printf, is the number of characters it prints, (not the number of bytes of the string)in this example, 0 because it prints nothing, that's why the if statement leads the program to print empty.

Not so much printf, but how strings are treated. Strings are terminated by \0 and they don't "include" the \0. You are asking printf to print a string via the %s. so it prints the contents of the string NOT including the \0, and so it is empty.

printf() function with %s read value until it find '\0', It does not read '\0' that why it returns 0 and result is empty.

arr is an array of 2 chars containing two 0 bytes. One 0 is explicitly specified and other is implicitly inserted into the string literal.
When you print a string with format specifier %s, printf() prints until it encounters a 0 terminator. Since the very first character is 0 (Note that string is terminated by the first 0 itself), printf() doesn't print anything.
printf() returns the number of characters successfully printed which is 0 in this case. Hence the if clause fails and the else clause is executed. So empty is printed as output.

The main concept here is the return type of printf statement . printf returns the no. of characters it is printing except any null character in the statement if any . Here your string contains only the null value, so compiler ignores it and thus the return value of the printf statement inside if block is 0 . And hence the else part gets executed .

Related

Why is the last character of a string not captured?

What happens to the last (nth) character of a n-character string when I try to output the string?
I've included my code, sample input and output below that highlights that the last character I input is lost.
Code:
char buffer[10];
fgets(buffer, sizeof(buffer), stdin);
printf("%s", buffer);
return 0;
Input:
aaaaaaaaab (that's 9 a's followed by 1 b)
Output:
aaaaaaaaa (9 a's)
For an array of characters to be treated as a propper string, its last character must be a null terminator (or null byte) '\0'.
The fgets function, in particular always makes sure that this character is added to the char array, so for a size argument of 10 it stores the first 9 caracters in the array and a null byte in the last available space, if the input is larger than or equal to 9.
Be aware that the unread characters, like b in your sample case, will remain in the input buffer stdin, and can disrupt future input reads.
This null byte acts as a sentinel, and is used by functions like printf to know where the string ends, needless to say that this character is not printable.
If you pass a non null terminated array of characters to printf this will amount to undefined behavior.
Many other functions in the standard library (and others) rely on this to work properly so it's imperative that you make sure that all your strings are properly null terminated.

What will be the output of the following C program

#include<stdio.h>
int main()
{
char *p;
p="%d\n";
p++;
p++;
printf(p-2, 400);
return 0;
}
When I am running above code, I am getting output 400. But why 400?
The p is assigned the formatting string first. Then it's decrement by 1 two times. Finally its value minus two is passed to the printf with additional parameter 400.
Subtracting 2 from latest value of p moves it back to the original formatting string. And therefore printf prints value 400.
printf()'s first parameter is a format string. The variable p is a pointer to a character array which is also how strings are represented.
When p is assigned a string "%d\n" it says format an integer to print its value and then print the carriage return character.
Since p is a char pointer p++ means move the pointer forward 1 character. This is done twice to move p forward 2 characters so it points to the beginning of the carriage return character. p-2 says do pointer math to give a char* 2 characters in front of where p points.
This is the beginning of the %d carriage return string. This becomes the format string and the second parameter 400 replaces the %d and prints itself followed by the carriage return.
You declared a pointer to a string and assigned it the value "%d\n". This pointer holds an address in memory.
For example, lets say it points to address 6 when you add two to it (which you shouldn't do you you always have to know where your pointers are pointing) you change the address to 8.
Now when you do printf you're replacing it with the current value of the address p points to (8) minus 2 which is 6.

Strncpy (String C programming) doesn't perform well the second time

Why does the second strncpy give incorrect weird symbols when printing?
Do I need something like fflush(stdin) ?
Note that I used scanf("%s",aString); to read an entire string, the input that is entered starts first off with a space so that it works correctly.
void stringMagic(char str[], int index1, int index2)
{
char part1[40],part2[40];
strncpy(part1,&str[0],index1);
part1[sizeof(part1)-1] = '\0';//strncpy doesn't always put '\0' where it should
printf("\n%s\n",part1);
strncpy(part2,&str[index1+1],(index2-index1));
part2[sizeof(part2)-1] = '\0';
printf("\n%s\n",part2);
}
EDIT
The problem seems to lie in
scanf("%s",aString);
because when I use printf("\n%s",aString); and I have entered something like "Enough with the hello world" I only get as output "Enough" because of the '\0'.
How can I correctly input the entire sentence with whitespace stored? Reading characters?
Now I use: fgets (aString, 100, stdin);
(Reading string from input with space character?)
In order to print a char sequence correctly using %s it needs to be null-terminated. In addition the terminating symbol should be immediately after the last symbol to be printed. However this section in your code: part2[sizeof(part2)-1] = '\0'; always sets the 39th cell of part2 to be the 0 character. Note that sizeof(part2) will always return the memory size allocated for part2 which in this case is 40. The value of this function does not depend on the contents of part2.
What you should do instead is to set the (index2-index1) character in part2 to 0. You know you've copied that many characters to part2, so you know what is the expected length of the resulting string.

Why the complete character array is getting printed not the first character?

This is the source code
char target[80]="hello", *tar;
tar=&target;
printf("%s",tar); //printing hello
tar is getting the address of target[0] then why it is printing the whole character array.
when u say %s and specify a starting memory(or any intermediate) of the string it gets printed till it encounters '\0' character.
consider
char *name = "Hello";
will be stored internally as
Hello\0
so if u need a single character go for %c.
Use %c to print a single character and %s is used to print a string.
C strings are null terminated. When you pass the address of the first character in an array of characters representing a string to printf and tell it to format the output as a string using %s, it will print all of the characters beginning at the address of the first character until a null (NUL) character, '\0', is reached.
%s indicates printing characters between the character 'tar' points to and next '\0' .
printf("%c",*tar);
will print what you need.

Doesn't %[] or %[^] specifier in scanf(),sscanf() or fscanf() store the input in null-terminated character array?

Here's what the Beez C guide (LINK) tells about the %[] format specifier:
It allows you to specify a set of characters to be stored away (likely in an array of chars). Conversion stops when a character that is not in the set is matched.
I would appreciate if you can clarify some basic questions that arise from this premise:
1) Are the input fetched by those two format specifiers stored in the arguments(of type char*) as a character array or a character array with a \0 terminating character (string)? If not a string, how to make it store as a string , in cases like the program below where we want to fetch a sequence of characters as a string and stop when a particular character (in the negated character set) is encountered?
2) My program seems to suggest that processing stops for the %[^|] specifier when the negated character | is encountered.But when it starts again for the next format specifier,does it start from the negated character where it had stopped earlier?In my program I intend to ignore the | hence I used %*c.But I tested and found that if I use %c and an additional argument of type char,then the character | is indeed stored in that argument.
3) And lastly but crucially for me,what is the difference between passing a character array for a %s format specifier in printf() and a string(NULL terminated character array)?In my other program titled character array vs string,I've passed a character array(not NULL terminated) for a %s format specifier in printf() and it gets printed just as a string would.What is the difference?
//Program to illustrate %[^] specifier
#include<stdio.h>
int main()
{
char *ptr="fruit|apple|lemon",type[10],fruit1[10],fruit2[10];
sscanf(ptr, "%[^|]%*c%[^|]%*c%s", type,fruit1, fruit2);
printf("%s,%s,%s",type,fruit1,fruit2);
}
//character array vs string
#include<stdio.h>
int main()
{
char test[10]={'J','O','N'};
printf("%s",test);
}
Output JON
//Using %c instead of %*c
#include<stdio.h>
int main()
{
char *ptr="fruit|apple|lemon",type[10],fruit1[10],fruit2[10],char_var;
sscanf(ptr, "%[^|]%c%[^|]%*c%s", type,&char_var,fruit1, fruit2);
printf("%s,%s,%s,and the character is %c",type,fruit1,fruit2,char_var);
}
Output fruit,apple,lemon,and the character is |
It is null terminated. From sscanf():
The conversion specifiers s and [ always store the null terminator in addition to the matched characters. The size of the destination array must be at least one greater than the specified field width.
The excluded characters are unconsumed by the scan set and remain to be processed. An alternative format specifier:
if (sscanf(ptr, "%9[^|]|%9[^|]|%9s", type,fruit1, fruit2) == 3)
The array is actually null terminated as remaining elements will be zero initialized:
char test[10]={'J','O','N' /*,0,0,0,0,0,0,0*/ };
If it was not null terminated then it would keep printing until a null character was found somewhere in memory, possibly overruning the end of the array causing undefined behaviour. It is possible to print a non-null terminated array:
char buf[] = { 'a', 'b', 'c' };
printf("%.*s", 3, buf);
1) Are the input fetched by those two format specifiers stored in the
arguments(of type char*) as a character array or a character array
with a \0 terminating character (string)? If not a string, how to make
it store as a string , in cases like the program below where we want
to fetch a sequence of characters as a string and stop when a
particular character (in the negated character set) is encountered?
They're stored in ASCIIZ format - with a NUL/'\0' terminator.
2) My program seems to suggest that processing stops for the %[^|]
specifier when the negated character | is encountered.But when it
starts again for the next format specifier,does it start from the
negated character where it had stopped earlier?In my program I intend
to ignore the | hence I used %*c.But I tested and found that if I use
%c and an additional argument of type char,then the character | is
indeed stored in that argument.
It shouldn't consume the next character. Show us your code or it didn't happen ;-P.
3) And lastly but crucially for me,what is the difference between
passing a character array for a %s format specifier in printf() and a
string(NULL terminated character array)?In my other program titled
character array vs string,I've passed a character array(not NULL
terminated) for a %s format specifier in printf() and it gets printed
just as a string would.What is the difference?
(edit: the following addresses the question above, which talks about array behaviours generally and is broader than the code snippet in the question that specifically posed the case char[10] = "abcd"; and is safe)
%s must be passed a pointer to a ASCIIZ text... even if that text is explicitly in a char array, it's the mandatory presence of the NUL terminator that defines the textual content and not the array length. You must NUL terminate your character array or you have undefined behaviour. You might get away with it sometimes - e.g. strncpy into the array will NUL terminate it if-and-only-if there's room to do so, and static arrays start with all-0 content so if you only overwrite before the final character you'll have a NUL, your char[10] example happens to have elements for which values aren't specified populated with NULs, but you should generally take responsibility for ensuring that something is ensuring NUL termination.

Resources