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");
Related
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.
I'm trying to read the characters of a character array by number in c. I've stripped the program down to isolate the problem. I know this is about my misunderstanding of how arrays and memory works and I am ready to be called clueless but I would like to know what I am misunderstanding here. Here is what I have:
#include <stdio.h>
int main(int argc, char **argv) {
char buffer[] = "stuff";
printf("buffer is %s\n", buffer);
printf("first character of buffer is %s", (char)buffer[0]);
return 0;
}
You have to write the correct format specifier. Now you used %s ...what happens?
It looks for an string which is null terminated. But it doesn't find one. So it simply cant put anything in the output . That's it.
Use %c instead.
In C there is a very big difference between a character and a string.
A character is simply a number in a range of 256 different options.
A string is not really a type of its own, it is merely an array of chars (which, in C, is simply evaluated as a pointer to the first character of the string).
Now, when you type buffer[0], this is evaluated to the value at the beginning of the string (first value in the array). Indeed, this is of char type (and therefore you do not need the (char) casting, because this will not do anything in the case of your code).
What you need is to tell printf() how to evaluate the input that you give it. %s is for a string (an array of chars). But note and remember that buffer[0] is not an array of chars, but rather a char.
So you actually want to use %c, instead of %s. This tells printf() to evaluate the parameter as a char type.
What your code currently does is take the value buffer[0] (which is just a number) and consider it as a pointer to a location in memory where a string is kept, and printf() tries to print this string. But this memory location is simply invalid. It is not a location you've accessed before.
In conclusion you want:
printf("first character of buffer is %c", (char)buffer[0]);
or even simpler:
printf("first character of buffer is %c", buffer[0]);
For other specifiers of the printf() function, look here:
http://www.tutorialspoint.com/c_standard_library/c_function_printf.htm
If you want to print only a single char use %c format.
printf("first character of buffer is %c\n", (char)buffer[0]);
Whenever I need to assign to a string and I have some word (called variedinput) that is assigned via standard input, socket, etc, I do something like
char buffer[50];
strcpy(buffer, "The ");
strcat(buffer, variedinput);
strcat(buffer, " jumped over the fence.");
Is there some other function that allows me to do something like the following?
function(buffer, "The %s jumped over the fence.", variedinput)
Yes, it is called spnrintf. I your code:
snprintf(buffer, sizeof buffer, "The %s jumped over the fence", variedinput);
The rules for the format string and later arguments are the same as for printf. Of course, you must make sure variedinput actually points to a string in this example.
sprintf(buffer,"",...)?
Write formatted data to string.
http://www.cplusplus.com/reference/cstdio/sprintf/?kw=sprintf
My question is how do I create a format string that will include an entire line of text including embedded spaces?
I have a buffer defined
char buf[380];
When I read in a line of text, I make sure that buf[378] = '\n'; and `buf[379] = '\0';'
I am editing that buffer and then writing it to an already-opened file using fprintf:
fprintf(outfile, buf);
I am getting this warning when compiling:
ex_split.c: In function ‘main’:
ex_split.c:65:3: warning: format not a string literal and no format arguments [-Wformat-security]
and am not quite sure how to write the format string so all of buf can be written, because, as I remember it %s will stop at the first space, and this data has lots of spaces in it, which I need. It is positionally formatted data.
Addendum
Let me restate the problem. I believe %s will cause fprintf to stop scanning at the first 0x20 character in each line of data, in which there are one or more and usually many space and non-space, readable ASCII data. Are my assumptions correct?
%s stops at a space when scanning as part of a scanf format, not when printing as part of a printf format. fprintf(outfile, "%s", buf); will work just fine for you.
If you're sure that your buf string is safe - that is, it doesn't contain any % escapes that might cause undefined behaviour in printf, you could also just ignore/disable the warning in this case.
Change
fprintf(outfile, buf);
to
fprintf(outfile, "%s", buf);
and it will work as expected.
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.