102

I'd like to do something like printf("?", count, char) to repeat a character count times.

What is the right format-string to accomplish this?

EDIT: Yes, it is obvious that I could call printf() in a loop, but that is just what I wanted to avoid.

Maestro
  • 9,046
  • 15
  • 83
  • 116
  • 2
    How many did you have in mind? – WhozCraig Feb 04 '13 at 00:28
  • 4
    Not knowing the count at compile time isn't an obstacle to writing a loop. – Keith Thompson Feb 04 '13 at 00:54
  • Your question is reasonably clear (and the real answer is that there is no `printf` format that does what you want), but your comments leave me unsure what you're asking. You talk about a format string and arguments being passed into your function. What function are you asking about? It seems there are things you're not telling us. – Keith Thompson May 23 '13 at 14:55
  • @KeithThompson I wrote a wrapper around 'printf', so those arguments were the same as for the original, sorry for the confusion. And I should have described the reason for needing this better, you're right. – Maestro May 23 '13 at 20:56
  • 1
    I'm afraid I still have no clear idea what you're trying to do, or (no offense to @synthesizerpatel) why you accepted the answer you did, which was not intended as a serious solution. – Keith Thompson May 23 '13 at 21:01
  • @KeithThompson Your solution to simply just loop doesnt work if you need to send the arguments over a network, or store them on disk, because the loops will need to be replicated on the other side. And since this was an old question with no real answer, I just selected the most original :) – Maestro May 23 '13 at 21:03
  • 1
    (I happened to see this again 4½ years later.) My solution to use a simple loop works perfectly well to answer the question you asked. I fail to see how sending data over a network or storing it to disk matters. If any of this still matters, please consider updating your question or, better, posting a new one. – Keith Thompson Dec 29 '17 at 19:04
  • Even if you don't know either value @ compile time, you could still use a variable for both, & that would still work. As an aside, if you want to write your own `printf` or similar function, you could add this functionality, but you'd still have to do a loop, which you can still do, as the inputs would be variables, which is perfectly valid! – JustinCB Jun 06 '18 at 17:33
  • @KeithThompson I honestly cannot remember what my constraints were at the time of the question. But suppose you are reading the printf format strings from a file (or over a network, to be executed on the other side). Then you would need to include the C code to do the loop along with the format string, and dynamicly compile it somehow. Or you would need to modify the file format, especially to specify a loop amount for each format string. All those solutions would be much more complicated than simply repeating the char using the format string, like the accepted answer does. – Maestro Apr 29 '23 at 00:55

13 Answers13

141

You can use the following technique:

printf("%.*s", 5, "=================");

This will print "=====" It works for me on Visual Studio, no reason it shouldn't work on all C compilers.

nhahtdh
  • 55,989
  • 15
  • 126
  • 162
rep_movsd
  • 6,675
  • 4
  • 30
  • 34
  • 5
    It's unfortunate that this answer isn't rated higher considering it's not only correct but works cross-platform. Tested on OSX, Linux and OpenBSD in C as well as Perl (which is wrapping the C printf anywho) – synthesizerpatel May 22 '13 at 11:49
  • 3
    Thanks, I remembered doing this 10 years ago , but forgot it and then rediscovered it. – rep_movsd May 23 '13 at 09:28
  • 30
    It's not exactly flexible tho'. If the width is larger than the string itself, it won't print more than the string (at least not in my simple experiment with gcc). – Mats Petersson May 23 '13 at 09:56
  • In that context it's kind of the opposite of %5s though right? The usefulness of it is being able to dynamically modify the width. Although, it's kinda hacky and doesn't come up that much.. For giggles I played around and got a little closer to the OP's intent.. although it's more stupid than useful.. see below. – synthesizerpatel May 23 '13 at 11:56
  • @synthesizerpatel: [Your other answer](http://stackoverflow.com/a/16713553/827263) is, at the moment, above this one, not below it. – Keith Thompson May 23 '13 at 14:50
  • Indeed it is. The Internet means serious business. – synthesizerpatel May 23 '13 at 15:17
  • I used this quite a lot for displaying text based progress indicators :D when I am forced to use C rather than C++ But yeah, the internetz sucks - the early poster gets the karma :D – rep_movsd Jun 10 '13 at 10:20
  • 1
    This works better than synthesizerpatel's answer. When I tried space instead of a zero and the width is zero, is still prints a single space. This one doesn't. – black May 12 '14 at 10:13
  • 1
    Nice catch! @rep_movsd – Juan Diego Godoy Robles Oct 22 '15 at 10:12
  • Why is there a dot inside the format? I can't find it in my references. – nougako Jan 29 '21 at 23:01
  • @nougako - See http://www.cplusplus.com/reference/cstdio/printf/ under ".precision" – rep_movsd Feb 12 '21 at 15:48
73

Short answer - yes, long answer: not how you want it.

You can use the %* form of printf, which accepts a variable width. And, if you use '0' as your value to print, combined with the right-aligned text that's zero padded on the left..

printf("%0*d\n", 20, 0);

produces:

00000000000000000000

With my tongue firmly planted in my cheek, I offer up this little horror-show snippet of code.

Some times you just gotta do things badly to remember why you try so hard the rest of the time.

#include <stdio.h>

int width = 20;
char buf[4096];

void subst(char *s, char from, char to) {
    while (*s == from)
    *s++ = to;
}

int main() {
    sprintf(buf, "%0*d", width, 0);
    subst(buf, '0', '-');
    printf("%s\n", buf);
    return 0;
}
synthesizerpatel
  • 27,321
  • 5
  • 74
  • 91
42

If you limit yourself to repeating either a 0 or a space you can do:

For spaces:

printf("%*s", count, "");

For zeros:

printf("%0*d", count, 0);
Ariel
  • 25,995
  • 5
  • 59
  • 69
  • Why does an empty string print spaces? I don't understand that. Shouldn't the last argument be `" "` instead of `""` ? – n00b.exe Jun 17 '21 at 20:44
  • 2
    @n00b.exe printf is not acting as a repeat command, it's acting as a format command. Imagine trying to nicely line-up columns of text with varying width, so you want to left pad everything. So it's left-padding, a blank string. – Ariel Jun 18 '21 at 02:19
21

In c++ you could use std::string to get repeated character

printf("%s",std::string(count,char).c_str());

For example:

printf("%s",std::string(5,'a').c_str());

output:

aaaaa
16

There is no such thing. You'll have to either write a loop using printf or puts, or write a function that copies the string count times into a new string.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • 3
    Very strange that I can have the most complicated expressions, but something simple like repeating a character is not supported. – Maestro Feb 04 '13 at 00:33
  • Why? You can do it simply by adding a loop around what you want to repeat. Most of what printf does are things you couldn't do in your own code [very easily]. Let libraries do the hard part, and the application program do the easy parts, I think that's the theme here. – Mats Petersson Feb 04 '13 at 00:38
  • 7
    And if you feel strongly about it, I guess the C standard committee is interested in suggestions for improvements, and a sample implementation inside glibc would perhaps improve the chances of it ever becoming standard. If you implement it, maybe someone else will think it's a good idea. It's only been missing for the last 50 years or so since printf was first introduced, so it's perhaps just an oversight... ;) – Mats Petersson Feb 04 '13 at 00:40
  • @MatsPetersson Thats no solution, because I don't know the format string in advance, see my response to Mokammel. – Maestro Feb 04 '13 at 00:40
  • 3
    Why is this being downvoted - if you are downvoting this answer, please let me know what it is you are unhappy with... – Mats Petersson May 23 '13 at 09:53
  • You don't want `puts` because it adds a newline. Nor should you use `fputs` or `printf` because they are overkill when you are only printing a char. The proper choice is to loop over `putchar`. – SO Stinks Jun 18 '21 at 16:20
10

printf doesn't do that -- and printf is overkill for printing a single character.

char c = '*';
int count = 42;
for (i = 0; i < count; i ++) {
    putchar(c);
}

Don't worry about this being inefficient; putchar() buffers its output, so it won't perform a physical output operation for each character unless it needs to.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • I dont know the format-string or the arguments that will be passed into my function, they could be read from a xml-file or be user-input. – Maestro Feb 04 '13 at 01:36
  • You have the character and the number of times you need to print it, right? What more information do you need? To print a single character with `printf`, the format string is `"%c"`. But you don't need to use `printf`, and in that case you don't need a format string at all. (There simply is no `printf` format string that will print a character multiple times, but there are other and better ways to accomplish the task.) – Keith Thompson Feb 04 '13 at 02:19
  • Like I said, I don't know what the arguments to my function represent. Suppose I read the format-string and arguments from an XML file, and pass them on to printf(), how would my function ever be aware that it needs to loop and that the second argument represents a count? That is what I mean with that my input is not known at compile-time. – Maestro Feb 04 '13 at 11:19
  • 4
    @Joshua: The arguments to *what* function? Your question doesn't even mention a function. – Keith Thompson Feb 04 '13 at 15:18
  • 1
    @Joshua you are really confused which is evident from your excessive usage of compile time and function 'is going to know'. It is really not as difficult as what you are making it appear. You need a function to print a character 'x' n times. If it comes from xml, then parse the xml and find out the character to print and how many times it needs printing. Use strlen to get the string length in places where your xml string field decides how many times the character 'x' needs to be printed. – SayeedHussain Jun 18 '13 at 05:04
  • @Muis passing a format string from user input is an utterly awful idea from a security perspective – M.M Feb 28 '18 at 02:43
8

If you have a compiler that supports the alloca() function, then this is possible solution (quite ugly though):

printf("%s", (char*)memset(memset(alloca(10), '\0', 10), 'x', 9));

It basically allocates 10 bytes on the stack which are filled with '\0' and then the first 9 bytes are filled with 'x'.

If you have a C99 compiler, then this might be a neater solution:

for (int i = 0;  i < 10;  i++, printf("%c", 'x'));
ramon
  • 830
  • 1
  • 12
  • 12
4
#include <stdio.h>
#include <string.h>

void repeat_char(unsigned int cnt, char ch) {
    char buffer[cnt + 1];
    /*assuming you want to repeat the c character 30 times*/
    memset(buffer,ch,cnd); buffer[cnt]='\0';
    printf("%s",buffer)
}
alexpanter
  • 1,222
  • 10
  • 25
4

you can make a function that do this job and use it

#include <stdio.h>

void repeat (char input , int count )
{
    for (int i=0; i != count; i++ )
    {
        printf("%c", input);
    }
}

int main()
{
    repeat ('#', 5);
    return 0;
}

This will output

#####
LoayH
  • 41
  • 1
  • 6
2
char buffer[41];

memset(buffer, '-', 40);    // initialize all with the '-' character<br /><br />
buffer[40] = 0;             // put a NULL at the end<br />

printf("%s\n", buffer);     // show 40 dashes<br />
Rob
  • 26,989
  • 16
  • 82
  • 98
Charles
  • 29
  • 1
1
printf("%.*s\n",n,(char *) memset(buffer,c,n));

n <= sizeof(buffer) [ maybe also n < 2^16]

However the optimizer may change it to puts(buffer) and then the lack of EoS will .....

And the assumption is that memset is an assembler instruction (but still a loop be it on chip).

Strictly seen there is no solution given you precondition 'No loop'.

Qix - MONICA WAS MISTREATED
  • 14,451
  • 16
  • 82
  • 145
Rene
  • 11
  • 1
0

For best performance you could use memset then send that string directly to printf:

    char buffer[40];
    memset(buffer, '-', 39); // Set 39 characters
    buffer[39] = 0; // Tag the end of the string
    printf(buffer); // Print it

For instance, this method could be used to produce a rectangle of a given width and height:

#include <stdio.h>
 
int main() {
    int width = 40; // External width
    int height = 7; // External height

    char buffer[width + 2];
    memset(buffer, '-', width); // Set the dashes
    buffer[width] = '\n';  // Add carriage return
    buffer[width + 1] = 0; // Tag the end of string

    printf(buffer);

    char buffer2[width + 2];
    memset(buffer2 + 1, ' ', width - 2);
    buffer2[0] = '|';
    buffer2[width - 1] = '|';
    buffer2[width] = '\n';
    buffer2[width + 1] = 0;

    int l = height - 2;
    while (l-- > 0)
        printf(buffer2);

    printf(buffer);
    
    return 0;
}

Output:

----------------------------------------
|                                      |
|                                      |
|                                      |
|                                      |
|                                      |
----------------------------------------
Murilo Perrone
  • 452
  • 4
  • 7
-3

i think doing some like this.

void printchar(char c, int n){
     int i;
     for(i=0;i<n;i++)
         print("%c",c);
}

printchar("*",10);
lindosekai
  • 174
  • 8