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

This is the source code
char target[80]="hello", *tar;
tar=⌖
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.

Related

Issue with saving characters in multidimensional array

i have a given Input of four scanf-strings which i want to save in a multidimensional array. I Don't know if i save the string right, but i can't just simply print the whole array or certain characters of it.
char getr[4][4];
for (z=0; z<4; z++){
scanf(" %99s", &getr[z]);
}
for (s=0; s<4; s++) {
printf("%s\n",getr[s]);
}
Input:
abcd
efgh
ijkl
mnop
Output:
abcdefghijklmnop
efghijklmnop
ijklmnop
mnop
what if i just want to print the second line or the fourth character of the first line? Does anybody know?
First, change as following:
scanf(" %99s", getr[z]); //getr[z] is the address to take the 4 characters string
To print out the second line:
printf("%s\n", getr[1]);
To print out the fourth character of the first line:
printf("%c\n", getr[0][3]); // %c is used here because just print one character.
To store 4-char strings, like your example input, you need 5-char arrays to leave room for the terminating null character:
char getr[4][5];
Your scanf() format string should also reflect the amount of space you have; %99s could read up to 100 bytes (99 chars plus the null), and you only have 5 (including the null, after the above change). Also, &getr[z] and getr[z] happen to give the same address, but the types of the pointers are different -- but getr[z] gives a char * which is appropriate in this case. So...
scanf(" %4s", getr[z]);
Those changes will already keep the strings from running together, so individual strings can be accessed as getr[0] through getr[3]. To print individual characters within a string, add an additional set of indexing brackets and use a function that prints a character rather than a string:
fputc(getr[0][2],stdout); /* print 3rd char in 1st string */
printf("%c",getr[1][3]); /* print 4th char of 2nd string */
The reason you were getting all your strings concatenated was because the null char from the earlier strings overflowed into the next char array, and was overwritten by the first char of the next string you read. The last string's null would have overflowed past your whole 2D array into whatever was next in memory (which is bad).

Storing a format specifier in a pointer

What actually happens when I do this?
{
char * str = "%d\n";
str++;
str++;
printf(str-2,300);
return 0;
}
Intuitively, it appears that the number on the screen will be 300, but I want to know, what gets stored in str.
Edit: It will be great if someone can tell me, when do we actually do this?
Thanks!
str is a memory address, initially the address of the % sign of the string literal %d\n. This literal is created because it is in your code.
Two increments make str point to the character \n and when this is the case, str - 2 is the address of the % sign. So printf sees the format string %d\n, and as usual it prints the first argument after the format string as an integer. The fact is, printf does not care about the origins of the format string. It doesn't matter if you can create it on-the-fly, or hard code it.
We don't do this generally. Sometimes you need to fiddle with a character pointer to scan a string, extract something out of a string, or to skip some prefix of a string.
str is a pointer on the stack. It initially points to (ie, holds the address of) the start of the string literal "%d\n" (this is probably stored in a read-only section of your program by the compiler).
Let's say for example the string literal (the "$d\n") is stored at 0x5000. So (assuming UTF-8 or ASCII) the byte at 0x5000 is %, the byte at 0x5001 is d, 0x5002 is \n (the newline) and at 0x5003 it is \0 (the terminating null character)
str is initially holding the address 0x5000. str++ would increase it to 0x5001, meaning it now points to the string "d\n", ie one character into the string literal "%d\n". Likewise, str++ again moves it to 0x5002, ie the string "\n", two characters into the string literal "%d\n". Note that all of these are still terminated by the null character at 0x5003 (how C knows when the string ends).
The printf call has the format string as the first argument. str at this point holds 0x5002, so the call is saying 'Use the format string starting at 0x5002 - 2 = 0x5000', which turns out to be the same string that we started with.
Thus it will be the same as calling
printf("%d\n",300)
and will print out 300.
Well you are declaring a char pointer. This pointer will hold a RAM address from where you will write the following bytes: % (1 byte) d (1 byte) \n (1byte on UNIX, 2 bytes on windows) and \0 the null terminating byte that ends your string.
Then you increment by two your pointer value (which is the address of the first byte) then decrement by two. So basically you do nothing. Thus when calling printf() src-2 will point to %d\n and the null terminating byte will make it exactly pass %d\n.
So at the end of the day what you are doing is:
printf("%d\n", 300); Hence the 300 output.

sscanf reading multiple characters

I am trying to read a list of interfaces given in a config file.
char readList[3];
memset(readList,'\0',sizeof(readList));
fgets(linebuf, sizeof(linebuf),fp); //I get the file pointer(fp) without any error
sscanf(linebuf, "List %s, %s, %s \n",
&readList[0],
&readList[1],
&readList[2]);
Suppose the line the config file is something like this
list value1 value2 value3
I am not able to read this. Can someone please tell me the correct syntax for doing this. What am I doing wrong here.
The %s conversion specifier in the format string reads a sequence of non-whitespace characters and stores in buffer pointed to by the corresponding argument passed to sscanf. The buffer must be large enough to store the input string plus the terminating null byte which is added automatically by sscanf else it is undefined behaviour.
char readList[3];
The above statement defines readList to be an array of 3 characters. What you need is an array of characters arrays large enough to store the strings written by sscanf. Also the format string "List %s, %s, %s \n" in your sscanf call means that it must exactly match "List" and two commas ' in that order in the string linebuf else sscanf will fail due to matching failure. Make sure that you string linebuf is formatted accordingly else here is what I suggest. Also, you must guard against sscanf overrunning the buffer it writes into by specifying the maximum field width else it will cause undefined behaviour. The maximum field width should be one less than the buffer size to accommodate the terminating null byte.
// assuming the max length of a string in linebuf is 40
// +1 for the terminating null byte which is added by sscanf
char readList[3][40+1];
fgets(linebuf, sizeof linebuf, fp);
// "%40s" means that sscanf will write at most 40 chars
// in the buffer and then append the null byte at the end.
sscanf(linebuf,
"%40s%40s%40s",
readList[0],
readList[1],
readList[2]);
Your char readlist[3] is an array of three chars. What you need however is an array of three strings, like char readlist[3][MUCH]. Then, reading them like
sscanf(linebuf, "list %s %s %s",
readList[0],
readList[1],
readList[2]);
will perhaps succeed. Note that the alphabetic strings in scanf need to match character-by-character (hence list, not List), and any whitespace in the format string is a signal to skip all whitespace in the string up to the next non-whitespace character. Also note the absence of & in readList arguments since they are already pointers.

How '\0' is treated in printf?

#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 .

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