How printf works without modifiers? - c

#include <stdio.h>
int main()
{
char string[]="Programming Language";
printf(string);
printf("\n%s",string);
return 0;
}
Output
Programming Language
Programming Language
Why is the output same?

When printf parses the format string it prints the characters that are not format specifiers as they are.
So when it parses "Programming Language" it just echoes each character.

The first printf statement is the same as:
printf("Programming Language");
and your second printf statement is just the same:
(Because the 'placeholder' gets replaced with the variable, + a new line at the start)
printf("\nProgramming Language");
So that's why it is the same output

They are not the same. The second one includes a new line that is not included in the first one.
If you remove the newline, they will be the same because:
The first version simply prints the contents of string.
The second version uses %s, which is replaced with the contents of string.
Either way, the result would be the same.

First argument of printf could contains plain text besides modifiers. So basically it equals. %s is useful when you want to include some string inside of other e.g.:
printf ("One Two %s Four Five (%d, %d, %d, %d, %d)", "Three", 1, 2, 3, 4, 5);
Using %s modifier standalone quite meaningless. Just one thing you should remember - in the case you are not using %s modifier and pass string as a first parameter you should quote % symbol. E.g.:
printf ("I am 100%% sure that it would works!");
So basically instead just single % sign you need to use double % ( %% ). Even in the case you pass it as a variable:
char s [] = "50%% complete";
printf (s);
Hope it makes sence!

Related

accessing pointed value with pointer without *

I am reading Head First C book and in pointers chapter(and pointer arithmetic) i couldnt understand something.
I have to write arrays like this to print its 3rd element:
main(){
int drinks[] = {4, 2, 3};
printf("3rd order: %i drinks\n", *(drinks + 2));
}
But when using pointer i need to write like this
void skip(char*);
int main() {
char *msg_from_amy="dont call me";
skip(msg_from_amy);
}
void skip(char *msg){
puts(msg+6);
}
Shouldnt i need to write *(msg+6) to access 7th element? msg holds an address and msg+6 means ahead of 6 bytes from begining. so it is still an address, i need to write *(msg+6) to access stored value in that address from my perspective but it doesnt work. But why quoted one right answer, why i cant figure out.
Edit: Actually i asked wrongly my question. And edited code snippets. Here is output of:
puts(msg+6);
printf("%c\n", *(msg+6));
printf("%s\n", *(msg+6));
all me
a
I expected get "all me" output from 2nd printf like 1st one. But i think i understand the reason. its difference of puts and printf argument list. Thx for answers.
Btw why 3rd printf prints just a blank character?
I have to write arrays like this to print its 3rd element:
main(){
int drinks[] = {4, 2, 3};
printf("3rd order: %i drinks\n", *(drinks + 2));
}
No, you don't have to do that, and it is very non-idiomatic. Most people would use
printf("3rd order: %i drinks\n", drinks[2]);
Moving on ...
void skip(char *msg){
puts(msg+6);
}
Shouldnt i need to write *(msg+6) to access 7th element?
Yes, *(msg+6) to access 7th element or, better, msg[6]. But you're not trying to access the 7th element. You are providing to puts the substring that starts at the 7th element. msg+6 is just fine for that.
Here is output of:
puts(msg+6);
printf("%c\n", *(msg+6));
printf("%s\n", *(msg+6));
all me
a
I expected get "all me" output from 2nd printf like 1st one
I don't see why. The %c formatting directive converts and prints one character, which is good because that's what you pass as the corresponding argument. It's not about a difference between puts and printf. Rather, it's mostly about the deep difference between msg+6 and *(msg+6).
Btw why 3rd printf prints just a blank character?
No one can say. The behavior of your third printf call is undefined because the formatting directive %s, which expects a char * argument, is not correctly type matched with the corresponding argument *(msg+6), which is a char. Anything could happen. And this underscores my previous point: there is no deep difference in this regard between puts and printf. You appear to want:
printf("%s\n", msg+6);
I expected get "all me" output from 2nd printf like 1st one.
The %c specifier is intended to print exactly one character. Furthermore, it's impossible to go to msg+7 from *(msg+6).
Btw why 3rd printf prints just a blank character?
Because %s expects a pointer. *(msg+6) is not a pointer.
You should compile with -Wall -Wextra. That will make the compiler warn you about a lot of stuff.
If you need the value that msg points to, you need to deference it using the * operator. So, if you want to get the sixth element pointed by msg, you need to advance by 6 and then deference it. The problem with printf("%s\n", *(msg+6)); is that %s expects a string, but *(msg+6) is a character. You can try to change %s with %c.
Remember that a string in c is a collection of characters ended by the null character '\0'.

Too many arguments for format (printf function)

Keep getting the following warning: “too many arguments for format” for the printf function below. Do not know what is causing this warning. I provided the type values of pos and str_pos along with the printf function. I excluded all other code as I did not think it was necessary for this question.
int pos;
char str_pos;
printf("The character at index %d is %c",pos,str_pos, "\n");
The corect way of writing that printf() statement would be
printf("The character at index %d is %c\n", pos, str_pos);
You need to change
“ to "s.
Use the format string correctly, including the newline.
use pos and string_pos as the argument (not part of the format string itself), in the variadic list.
Also, I presume that variables are initialized before you're printing them.

why i have exc_bad_access doing cast?

i am programming in C and i have a problem while casting an int into a char.
I am using my mac with Xcode to program c.
The code is:
int main(){
int t = 2;
printf("test %s\n", (char)t); //EXC_BAD_ACCESS
return 0;
}
I tried all I found in many post, I really don't know what is going on... any suggestion?
Please include the goal of your code in your question not in a comment below.
If you want the output
test 2
your have to change %s to %d
printf("test %d\n", t);
I guess you got the wrong idea about the %s. It does not tell the printf that you want to have the int as string, it does tell printf that the parameter is a string! It is obviously not, so you got the exception.
if you use %c you tell the printf function that you want to output your number as character from your current ASCII table. For example 65 is 'A'.
If you have a concatenation situation like
strcpy(str_buscar, "controlID='");
strcat(str_buscar, (char) t);
strcat(str_buscar, "'");
you need itoa instead of the cast:
strcat(str_buscar, (char) t);
you need the follow:
char buffer[32]; // enough space for a "number as string"
itoa(t,buffer,10);
strcat(str_buscar, buffer);
a (IMHO) shortcut is to "print" to a buffer with sprintf
sprintf(str_buscar,"controlID='%d'",t);
instead of printing to a console sprintf prints into the given buffer. Make shure that your buffer str_buscar is big enough.
The %s format specifier represents a string, not an individual character. Printf thinks that the number 2 you're passing it is a string's address. It tries to access the memory address 2 and fails, because that address doesn't exist.
If you want to print a character, you'll want the %c specifier. This tells printf to print the character whose ASCII code is 2. The ASCII character number 2 is, according to the ASCII table, a control character that cannot be printed, which is why you're getting strange output.
If you actually want to print the character '2' (which has a different code, 50), you will want to use something like:
printf("test: %c", (char)('0' + c));
This example leverages the fact that all ASCII characters have consecutive codes, starting with 48 ('0'). This way, if you wanted to print the digit 0, you'd end up printing the '0' character (ASCII code 48 = 48 + 0). If you want to print the digit 2, you'll end up printing the '2' character (50 = 48 + 2).
This way, however, is a bit clunky and fails when encountering numbers larger than 9 (i.e. it only works with digits). The easier way consists of no longer working with characters at all and, instead, using the '%d' specifier (used for printing whole number):
int t = 0;
printf("test: %d", t);

how can I printf in c

How can I make this print properly without using two printf calls?
char* second = "Second%d";
printf("First%d"second,1,2);
The code you showed us is syntactically invalid, but I presume you want to do something that has the same effect as:
printf("First%dSecond%d", 1, 2);
As you know, the first argument to printf is the format string. It doesn't have to be a literal; you can build it any way you like.
Here's an example:
#include <stdio.h>
#include <string.h>
int main(void)
{
char *second = "Second%d";
char format[100];
strcpy(format, "First%d");
strcat(format, second);
printf(format, 1, 2);
putchar('\n');
return 0;
}
Some notes:
I've added a newline after the output. Output text should (almost) always be terminated by a newline.
I've set an arbitrary size of 100 bytes for the format string. More generally, you could declare
char *format;
and initialize it with a call to malloc(), allocating the size you actually need (and checking that malloc() didn't signal failure by returning a null pointer); you'd then want to call free(format); after you're done with it.
As templatetypedef says in a comment, this kind of thing can be potentially dangerous if the format string comes from an uncontrolled source.
(Or you could just call printf twice; it's not that much more expensive than calling it once.)
Use the preprocessor to concatenate the two strings.
#define second "Second%d"
printf("First%d"second,1,2);
Do not do this in a real program.
char *second = "Second %d";
char *first = "First %d";
char largebuffer[256];
strcpy (largebuffer, first);
strcat (largebuffer, second);
printf (largebuffer, 1, 2);
The problem with using generated formats such as the method above is that the printf() function, since it is a variable length argument list, has no way of knowing the number of arguments provided. What it does is to use the format string provided and using the types as described in the format string it will then pick that number and types of arguments from the argument list.
If you provide the correct number of arguments like in the example above in which there are two %d formats and there are two integers provided to be printed in those places, everything is fine. However what if you do something like the following:
char *second = "Second %s";
char *first = "First %d";
char largebuffer[256];
strcpy (largebuffer, first);
strcat (largebuffer, second);
printf (largebuffer, 1);
In this example the printf() function is expecting the format string as well as a variable number of arguments. The format string says that there will be two additional arguments, an integer and a zero terminated character string. However only one additional argument is provided so the printf() function will just use what ever is next on the stack as being a pointer to a zero terminated character string.
If you are lucky, the data that the printf() function interprets as a pointer will a valid memory address for your application and the memory area pointed to will be a couple of characters terminated by a zero. If you are less lucky the pointer will be zero or garbage and you will get an access violation right then and it will be easy to find the cause of the application crash. If you have no luck at all, the pointer will be good enough that it will point to a valid address that is about 2K of characters and the result is that printf() will totally mess up your stack and go into the weeds and the resulting crash data will be pretty useless.
char *second = "Second%d";
char tmp[256];
memset(tmp, 0, 256);
sprintf(tmp, second, 2);
printf("First%d%s", 1,tmp);
Or something like that
I'm assuming you want the output:
First 1 Second 2
To do this we need to understand printf's functionality a little better. The real reason that printf is so useful is that it not only prints strings, but also formats variables for you. Depending on how you want your variable formatted you need to use different formatting characters. %d tells printf to format the variable as a signed integer, which you already know. However, there are other formats, such as %f for floats and doubles, %l% for long integers, and %s for strings, or char*.
Using the %s formatting character to print your char* variable, second, our code looks like this:
char* second = "Second";
printf ( " First %d %s %d ", 1, second, 2 );
This tells printf that you want the first variable formatted as an integer, the second as a string, and the third as another integer.

Format specifiers in C - %s inside %s

I have something like this
char string[]="My name is %s";
printf("%s",string,"Tom");
I expect the output to be My name is Tom but I am getting My name is %s
I tried escaping the % character, but it dint work.
What's going wrong here? How shall I have a %s inside a %s?
Try something like this
printf(string,"Tom");
The problem with your method is this -
As soon as printf sees %s format specifier in your format string, it assumes that the next argument in list is a string pointed to by a character pointer, retrieves it and prints it in place of %s. Now, printf doesn't do a recursive replacement and hence
%s inside your string remains as it is and "Tom" is now an extra argument which is just discarded.
There is only one expansion during printf; that means any strings passed to printf except the format strings will be printed verbatim (if at all). That is actually a good thing, because otherwise, it leaves a huge security hole.
The security risk relates to the fact that the format string and the parameter list have to correspond. That means, if an unwanted % makes it to the format string, you will get in trouble:
char ch[50];
fgets(ch, 50, stdin);
printf(ch);
If the user supplies eg. %p %p %p %p, he will be reading data stored on the stack (like the return address and so on), if he supplies %s %s %s, he'll likely crash the program. If he supplies %n, he'll overwrite some data on the stack.
That said, you can just compute the format string if you want:
char ch[50];
char format_prototype[]="My name is %s";
snprintf(ch, 49, "%s", format_prototype);
ch[49]=0;
printf(ch, "Tom");
printf(string, "Tom") maybe?
The problem is with printf("%s",string,"Tom");
line
You should use
char string[]="My name is %s";
printf(string,"Tom");
here you will get the output as
My name is Tom
The first parameter to printf is the format string. The rest are all parameters which will be formatted according to the format string. The format strings do not nest in any way. In other words, even if a string to be formatted happens to contain formatting instruction, it is simply printed and not interpreted as another format string.
If you want to have that kind of formatting indirection, you would have to first generate a new format string (sprintf is useful for that):
char string[] = "My name is %s";
char format[100];
sprintf(format, "%s", string);
and then use the newly generated format string:
printf(format, "Tom");

Resources