David hehe
David hehe

Reputation: 7

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);

Upvotes: 0

Views: 247

Answers (4)

Matthieu
Matthieu

Reputation: 16397

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

Upvotes: 0

Richard Chambers
Richard Chambers

Reputation: 17583

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.

Upvotes: 0

Marlon
Marlon

Reputation: 20312

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.

Upvotes: 0

Keith Thompson
Keith Thompson

Reputation: 263267

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

Upvotes: 2

Related Questions