I have read this post.
But when I tried:
printf("before null %c after null\n", 0); // (ASCII=0) != '\0' ??
instead of getting:
before null
I got:
before null after null
So my question is:
Is ASCII value 0 actually equal to '\0'?
Is ASCII value 0 actually equal to \0?
Yes
The differences in how the strings are stored in memory and handled by functions like printf() are important.
"before null %c after null\n"
"before null \0 after null\n"
Both are stored in memory with an implicit \0 terminator at the end. The fact that the second has an explicit \0 character in the middle changes things.
printf() will scan the string until "the end", printing components as it goes... in C "the end" typically means until the first \0 / nul character.
With the first variant, printf() copies characters to the output until it reaches the %c directive, at which point it looks at the arguments that were given to the function... it might find that you gave '\0', or it might find that you gave '+' - either way, it copies this to the output. It'll then continue copying characters to the output, seeking "the end" of the string.
With the second variant, printf() will start copying characters to the output, will find "the end" (denoted by the \0), and stop.
If you were to use snprintf(), then the results / outputs would contain the following: (again, with implicit \0 termination)
"before null \0 after null\n"
"before null "
If you were to subsequently print both of these, they would look the same, but the memory content would be different.
However, the output of printf() is the terminal (or a file)... what happens for \0 depends on your terminal emulator... it might simply not be shown, it might be displayed as a space, or it may have a funny box symbol...
The important thing to note, is that this occurs at run time - not compile time.
That's because printf is NOT actually replacing "Hello %s", "World" with "Hello World" then print. No. It does not concatenate.
Rather, it actually prints each character alone in order, and when it encounters an argument, it starting printing each character from it directly too without concatenating.
If you ever tried to print a single null character using putchar(), You'd notice that it prints a space instead, that's why printf prints a space too based on it. (Note that It'll print nothing on other systems like Linux).
Sample code of how printf actually work.
const char * x;
// while the current char != '\0'
while (*format)
{
// if the current char == '%'
if (*format == '%')
{
// increment the pointer so we can point to the next char and skip printing '%'
switch (*(++format)) // then switch that next char (specifier).
{
case 'c':
putchar(va_arg(args, char)); // if the argument is null, then it's putchar(0);
break;
case 's':
// regular operation of printing a string argument.
x = va_arg(args, const char*);
while (*x) putchar(*x++);
break;
}
// skips the format specifier so we don't print it (e.g 's', 'c'..)
*format++;
}
// else: isn't a format specfier.
else
// print the current char (pointer) of the original string
putchar(*format++); // increments it for the next operation.
}
va_end(args);
So returning to your question, It will print each character and when it comes to the argument 0 which is null, putchar() will either put a space or nothing based on your system.
You can say that printf arguments don't really have any relationship with the original string to terminate it, they don't know each other. Like when you printf("Hello %s, from SO!", "World");, "World" is actually terminated at the end with \0, but it will terminate just itself, not the other , from SO!.
And Yes, 0 is '\0'. they're the same character.
printf will not terminate the printf format-string at that character position for the %c format-specifier when given values 0 or '\0'. Instead, the terminal output for the nul will generally be a placeholder (e.g. a space or the like)
However you can insert a nul into the string and then output the string using the %s format-specifier and see that in fact decimal 0 is actually the ASCII value for the equivalent ASCII character '\0' and will terminate the string at the point of the nul-character (see: www.ASCIItable.com), e.g.
#include <stdio.h>
#define FMT "before null %c after null\n"
int main (void) {
char buf[sizeof FMT * 2];
puts (FMT);
sprintf (buf, FMT, 0);
printf ("using 0 : '%s'", buf);
putchar ('\n');
sprintf (buf, FMT, '\0');
printf ("using \\0: '%s'", buf);
putchar ('\n');
return 0;
}
Example Use/Output
$ ./bin/str_printf_null
before null %c after null
using 0 : 'before null '
using \0: 'before null '
Related
Why both inner printf() functions are working different even the printing value is same for both functions ?
Here is the code -:
#include<stdio.h>
int main()
{
char ch = '\0';
printf("%d",printf("%c", ch)) ;
// This line will print 1.
printf("%d",printf("\0")) ;
// This line will print 0.
return 0;
}
printf("%d", printf("%c", '\0'));
Why this line prints 1?
The value '\0' is one single character, which "%c" sends th stdout (though you can't see it).
printf("%d", printf("%s", "\0"));
Why this line prints 0?
The string "\0" has two characters in it: the literal '\0' and the implied '\0'. None of them are printed with "%s", the first zero terminates the string. The string "foo" has 4 characters: the 3 literal ones and the implied '\0'
Referring to man page of printf
man 3 printf
printf returns the following
RETURN VALUE
Upon successful return, these functions return the number of characters printed (excluding the null byte used to end output to strings).
So it does not return the count of null bytes.
In the first printf you are explicitly telling to print 1 character, so the output is 1. In the second printf there is nothing to print or NULL. So the output is 0
#include<stdio.h>
int main()
{
char ch = '\0';
printf("%d",printf("%c", ch)) ;
The inner call to printf() prints a null character (you don't see it) and returns 1 as the number of characters printed, which is then printed as the string 1 (you get a null plus a digit 1).
// This line will print 1.
printf("%d",printf("\0")) ;
In this case, you supply a string literal ended in two consecutive null chars, which results on printing an empty string (literally "") and that results in passing to the second printf a 0 and the second printf prints it as the string 0.
// This line will print 0.
return 0;
}
So, you are wrong, in the first case you got a null character printed (a true \0 befpre tje 1. But a null is ignored by the terminal you are using and it doesn't show in your screen, while the second doesn't print anything·)
NOTE
Every C language string related function, explores the string to know how long it is, or when to stop the task it is doing. Putting more than the default string literal's last null char \0 does nothing but shorten the useful part of the string literal. If you try to print "Se está quemando la serrería\0... Duduap!!" or operate on it with any of the string related functions, you'll get the same result as if you had stopped before the first \0 character. So the string literal above is basically equivalent to just "Se está quemando la serrería"
They are working different because first inner printf is printing a character and that character is a null character which has length of 1. While in your second inner printf you are trying to print a string which only contains null character, but due to null character the string became empty with length 0. This is the reason why your first outer printf printed 1 and second outer printf printed 0.
Here afaik, %s will keep on printing until it gets the termination character i.e. \0.
How does %c knows about termination and end up printing only one character?
String formatting is not a feature of C or the language. Is is a facility provided by the C runtime library.
"%c" doesn't need a terminator because it only processes one character.
"%s" continues to process characters until it encounters an ASCII NUL character which is expressed in C as '\000' (or '\0'). A forward slash in a string or character constant is a printable character without any special meaning.
Additionally, almost every C runtime library provides considerably more control over the %s length:
%.123s processes up to 123 characters if a NUL is not encountered
%.*s needs two matching parameters: the first is an integer which specifies the maximum field width and the second is the char pointer. Example: printf ("x = %.*s\n", 15, ptr);
%c always prints a single character.
char x = 'a';
Here we have a single character a which needs to be printed.
char x[2] = "a";
In the above example we have 2 characters one is 'a' and another is '\0'.
So while printing we need to use %s so that it encounters end of string thorough '\0' and prints the string.
%c means character, range is 0x00 to 0xff (Unsigned) that is 1 byte, a memory location can hold 1 byte of data, %c will print data from one memory location only, so termination character is not required.
%s means stream of characters means it has to get data from stream of memory locations so it requires a termination character, Hence '\0' is required for %s.
%c and %s are part of the printf() functions in the standard library, not part of the language itself.
That being said, printf() uses the character(s) following %, along with the stdarg functions, to determine what type of variable it will read from its arguments and what it will do with it. A highly simplified implementation of printf() might look like the following.
Note in particular that %c and %s do not deal with the same type of arguments! %c deals with a char (that is, a single character), whereas %s deals with a char * (that is, a pointer to an array of characters, hopefully null-terminated).
int printf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt); // Initialize stdargs
const char *p = fmt; // Pointer into the format string
while (*p != '\0') {
char ch = *p++; // Get the next character of the format string
if (ch != '%') { // Not a format character? Just print it
putchar(ch);
continue;
}
char fmt = *p++; // Get the character following the %
if (fmt == 'd') {
int n = va_arg(ap, int);
print_number(n);
if (fmt == 'c') {
char c = va_arg(ap, char);
putchar(c);
} else if (fmt == 's') {
char *str = va_arg(ap, char *);
print_string(str);
} else {
// Unrecognized format character
}
}
va_end(ap);
return n;
}
How can I make my input string S1 of the fgets (or similar statement) to be equal to my declared static string S2?
#include <stdio.h>
#include <string.h>
main() {
char s1[80];
char s2[] = "This is a test.";
int l1, l2;
system("clear");
printf("%s\n\n", s2);
printf("Please type exactly the above sentence: ");
fgets(s1,80,stdin);
l1=strlen(s1);
l2=strlen(s2);
printf("\n String entered for S1, have a length of %d:\n %s", l1, s1);
printf("\n String static for S2, have a legnth of %d:\n %s", l2, s2);
if(s1==s2)
printf("\n\nOk! they're with the same length!\n");
else
printf("\n\nNop! They are NOT the same.\n");
return(0);
}
You're doing a pointer comparison, not a string comparison. To compare the content of the strings, use strcmp (docs):
if (strcmp(s1, s2) == 0)
...
fgets reads a line of input (up to a specified length, in your case 80). It stores that line in the array pointed to by its first argument (s1) -- including the terminating '\n' newline character.
Which means that after your fgets call, assuming you typed exactly "This is a test." and then typed Enter, s1 will contain "This is a test.\n", not just "This is a test.".
You can remove that newline character before the comparison -- or rather you can replace it with a null character '\0', which marks the end of the string:
size_t len = strlen(s1);
if (s1[len-1] == '\n') {
s1[len-1] = '\0';
}
(You might need to move the declaration of len to the top of main if your compiler doesn't support mixed declarations and statements -- but the strlen call still has to be done after fgets.)
To test whether the s1 and s2 contain the same string value, use the strcmp function; your s1 == s2 does a pointer comparison. strcmp returns 0 if the strings are equal. (If they're not, it returns a negative or positive value to indicate whether the left string is lexicographically less than or greater than the right string.)
Some minor comments on your code:
main() should be int main(void). (Long story; for now, just take my word for it.)
There's probably no need to invoke system("clear"). Why do you want to clear the screen? There might be useful information on it. And it won't work on all systems. If I want to clear my screen before running your program, I can do it myself, thank you very much.
Your message "they're with the same length" isn't quite right. If you correct the test by using strcmp rather than ==, you're testing whether the strings have the same value, whether their lengths happen to be the same or not.
Usually when you print a message, it's best to put the newline \n at the end of the output. It's usually best to have just a single \n at the end of the message (unless you want to print multiple lines with one printf, or build up one line with multiple printfs, which you can do but it's not necessary here.)
Your question originally had gets and scanf tags. Never use the gets function; it's inherently unsafe and has been removed from the language. scanf is tricky, and not needed in this case.
I was just printing some characters in C.
I have declared char c and assigned its characters.
then using a for loop i try to print the characters one by one.
I have used pointers, of course.
#include <stdio.h>
#include <string.h>
int main()
{
char c[4] = {"hia"};
int i;
for(i=0;i<4;i++)
{
printf(&c[i]);
}
return 0;
}
However when I compile my code using turbo, i get output "hiaiaa" instead of "hia"! What am i doing wrong here?
Your printf() call is broken. You are using the string (from the point you specify) as the formatting string. This will not print single characters. Instead each call will print from where its formatting string starts, to end of the string.
This means the first call will print all of c, the next will print from c[1] and onwards, and so on. Not at all what you wanted.
If you want to print single characters, use the %c format specifier:
printf("%c", c[i]);
No pointer necessary, since the character is passed by value to printf().
This is what happened in your loop:
0. hia
1. ia
2. a
3. \0
However, you want to print exactly one char at a time, not a null terminated string, so you should pass it as char not a char*:
printf( "%c", c[i] )
Also, you are looping four times, but string length is just three. You should use:
for( i = 0; i < strlen( c ); i++ )
...
The printf function have an char* as first argument, that's correct. However, it prints a string (that is, a zero-terminated sequence of char) so it will always do that.
If you want to print one character at a time, then you have to use that format, like in:
printf("%c\n", c[i]);
You also have another problem, and that is that you try to print the zero terminator as well. This character is not printable so will not show. Use e.g. i < strlen(c) as the loop condition to overcome this.
Also, instead of printing character-by-character, print it all as one string:
printf("%s\n", c);
1) For loop size should i<3 , not i<4 (i=3 refers to the null character at the end of the string)
2) use printf("%c",c[i]);
Explanation of what you're seeing: In each loop, printf is printing a null-terminated string. This string starts in every loop one char later inside your array.
How it should be done, depends on what you're intending. If you want to print the string char by char via pointer you may use:
char *p=&c[0];
while (*p) {
printf("%c", *p);
p++;
}
Your question is to print string using pointer. You could use
printf("%s", c);
or character by character as (include library string.h for this)
for(i=0;i<strlen(c);i++)
{
printf("%c", c[i]);
}
in C strings are stored as character arrays and are terminated by a zero-value, so called zero-terminated strings. Btw, this is why you have to make the array size of 4 for thee real chars.
In your example, you are passing pointers th each char to the printf function and printf prints the strings from your pointer to the next null-value . The 1st pass prints "hia", the 2nd ia and the 3rd a.
To print a single char in each pass, you have to use
printf ("%c", c[i]);
Your loop will call printf with the following parameter:
printf("hia"); // first loop iteration
printf("ia"); // second loop iteration
printf("a"); // third loop iteration
printf(""); // fourth loop iteration
You probably meant to print one character at a time:
for(i=0;i<3;i++) // No need to print the string termination character.
{
printf("%c", c[i]); // "%c" is the printf format code to print a single character
}
I have a string I composed using memcpy() that (when expanded) looks like this:
char* str = "AAAA\x00\x00\x00...\x11\x11\x11\x11\x00\x00...";
I would like to print every character in the string, and if the character is null, print out "(null)" as a substitute for '\0'.
If I use a function like puts() or printf() it will just end at the first null and print out
AAAA
So how can I get it to print out the actual word "(null)" without it interpreting it as the end of the string?
You have to do that mapping yourself. If you want to, that is. In C, strings are null-terminated. So, if you use a formatted output function such as printf or puts and ask it to print a string (via the format specifier %s) it'd stop printing str as soon as it hits the first null. There is no null word in C. If you know exactly how many characters you have in str you might as well loop over them and print the characters out individually, substituting the 0 by your chosen mnemonic.
The draft says 7.21.6.1/8:
p The argument shall be a pointer to void. The value of the pointer is
converted to a sequence of printing characters, in an
implementation-defined manner.
However, the following:
$ cat null.c
#include <stdio.h>
int main() {
printf("%p\n", (void *)0);
}
produces:
00000000
on both gcc 4.6 and clang 3.2.
However, on digging deeper:
$ cat null.c
#include <stdio.h>
int main() {
printf("%s\n", (void *)0);
}
does indeed produce the desired output:
(null)
on both gcc and clang.
Note that the standard does not mandate this:
s If no l length modifier is present, the argument shall be a pointer
to the initial element of an array of character type.280) Characters
from the array are written up to (but not including) the terminating
null character. If the precision is specified, no more than that many
bytes are written. If the precision is not specified or is greater
than the size of the array, the array shall contain a null character.
Relying on this behavior may lead to surprises!
Instead of printing the string with %s , you will have to come up with a for loop that checks a condition whther a given char in your char array is a \0 and then print the NULL
From C++ Reference on puts() (emphasis mine):
Writes the C string pointed by str to stdout and appends a newline
character ('\n'). The function begins copying from the address
specified (str) until it reaches the terminating null character
('\0'). This final null-character is not copied to stdout.
To process data such as you have, you'll need to know the length. From there, you can simply loop across the characters:
/* ugly example */
char* str = "AAAA\x00\x00\x00...\x11\x11\x11\x11\x00\x00...";
int len = ...; /* get the len somehow or know ahead of time */
for(int i = 0; i < len; ++i) {
if('\0' == str[i]) {
printf(" (null) ");
} else {
printf(" %c ", str[i]);
}
}
One of the key cornerstones of C is strings are terminated by '\0'. Everyone lives by that rule. so I suggest you not think of your string as a string but as an array of characters.
If you traverse the array and test for '\0', you can print "(null)" out in place of the character. Here is an example. Please note, your char * str was created either as a char array or on the stack using malloc. This code needs to know the actual buffer size.
char* str = "AAAA\x00\x00\x00...\x11\x11\x11\x11\x00\x00...";
int iStrSz = <str's actual buffer size>
int idx;
for(idx=0; idx<iStrSz; idx++)
{
if('\0' == *(str + idx)
{
sprintf("%s", "(null)");
}
else
{
putchar(*(str + idx));
}
}
printf("%s", "\n");