Search code examples
cprintfcurses

Forcing printf to ignore formatting


I'm using the pdcurses library and I'm writing a function which moves a line on the screen up one. This involves copying the current line and then pasting it above. The problem is that the curses function for printing whole lines, printw, uses the same format strings as printf. These lines could contain percentage signs, and so once pasted those signs are of course lost.

The printw() functions add a formatted string to the window at the current or specified cursor position. The format strings are the same as used in the standard C library's printf(). (printw() can be used as a drop-in replacement for printf().)

A small example would be:

chtype p[200]; 
winchnstr(w, p, 200); //obtain the line
clrtoeol(); //remove the line

wmove(w, y-1, x); //move up a line
clrtoeol(); //erase the line
wprintw(w, p); //print the new line

Is there any way to force printf to treat the percentage signs as normal without having to go through p and inserting a percentage sign between every one? That seems a rather annoying for something so simple.

The first solution would be to convert p to a string, iterate through the string, and insert a % behind every %. But when I moving lots of lines at once (I'm trying to create an effect of the screen moving "upwards") this might not be the best solution performance-wise, would it?

The other solution would instead iterate through p and just use addch() to add each character separately. But would this lose performance/efficiency in comparison to wprintw? Or is wprintw simply a glorified version of just pasting each character individually? Are these really the only two options I have?


Solution

  • To force printf to accept your string as it is, use the format specifier %s and pass your string as an argument. printf arguments are not subject for format processing. In case of strings, the bytes are simply copied over to the destination buffer.

    printf("%s", "My string with % signs");
    

    In case your string isn't zero-terminated, you can pass a length before the string to printf if you use the %*s format specifier:

    printf("%*s", 5, "ab%cdefghi"); // prints "ab%cd"
    

    Note that the length argument must be of type int.