Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I set printf's output format with dynamic args?

I want to control the printf() functions output format with dynamic parameter, just as the code showed below:

    #include<stdio.h>

    int main(int argc,char ** argv)
    {
        printf(argv[1],"hello,world");
        return 0;
    }

Then I compile and run it:

$ gcc -o test test.c
$ ./test "\t%s\n"

The result is strange:

\thello,world\n$

Why "\n" and "\t" has no effect?

like image 300
storen Avatar asked May 20 '15 07:05

storen


People also ask

What will happen if you use wrong formatting characters in printf?

Oh yes - printf depends on the format string to determine the size and type of the variable to fetch next. When the format string is wrong it may try to fetch a variable that isn't even there, with all consequences that may have.

Can we use printf () apart from just printing values if yes then where?

The printf function of C can do a lot more than just printing the values of variables. We can also format our printing with the printf function. We will first see some of the format specifiers and special characters and then start the examples of formatted printing.

What is formatted output using printf () statement explain it?

One, the printf (short for "print formatted") function, writes output to the computer monitor. The other, fprintf, writes output to a computer file. They work in almost exactly the same way, so learning how printf works will give you (almost) all the information you need to use fprintf.

Does the printf function sends formatted output to stdout?

Description. The C library function int printf(const char *format, ...) sends formatted output to stdout.


2 Answers

Because the escapes you use (\t and \n) are interpreted inside string literals by the C compiler, not by printf(). This:

const char *newline1 = "\n", newline2[] = { '\n', 0 };

would generate the exact same content in newline1 and newline2, regardless of whether or not these are ever passed to printf(); the strings are there anyway.

Your code behaves just like this would:

printf("\\t%s\\n", "hello,world");

Here, I've double-escaped the special characters to generate a string with the same actual content as your command-line argument, i.e. "\t%s\n" (six characters rather than four).

The proper way to dynamically control printf() is to build the format string in code. If you want C-like escapes at runtime, you need to interpret them yourself in some way.

like image 68
unwind Avatar answered Oct 02 '22 19:10

unwind


The sequence \n in a string or character literal in C/C++ is a single byte with the numeric value 10 (on an ASCII system). When output on a terminal (try putchar(10)!) it just sets the output position for the next character on the terminal to the beginning of the next line (on *nix; on MacOS, I think, you need an additional \r, or 13 for carriage return to have the output position at the beginning of the line).

Similarily, a \t is the notation for a single byte with the value 9, which makes most terminals advance their cursor to the next tabulator position.

What you need is to insert a single byte of these values in the command line. How that can be done depends on your shell; in bash you can keep the shell from interpreting special characters by pressing Ctrl-V beforehand. That outputs e.g. a tab, displayed by showing some empty space (instead of making the shell show possible string continuations or whatever tab does in bash). bash strings in single or double quotes can include newlines without further efforts -- simply press enter.

Here is a sample run in a cygwin terminal with bash. I pressed the indicated keys at the indicated positions; I finished the command as usual with [return] after the closing single quote on the second line.

pressed Ctrl-v,[TAB] here | pressed [return] there 
                    v     v
$ ./printf-arg.exe '    %s
> '
        hello,world

The > in the second line was output by the shell after I pressed enter within the string delimited by single quotes. (Which inserts a newline in the string). It is an indication that the string being edited is continued on that line.

As an aside, it is probably unsafe to use command line arguments this way in potentially hostile environments. Carefully crafted strings could access memory which is not meant to be accessed and e.g. redirect return addresses, thus corrupting the program.

like image 42
Peter - Reinstate Monica Avatar answered Oct 02 '22 20:10

Peter - Reinstate Monica