How to repeat a char using printf?
Asked Answered
M

13

104

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.

Meuser answered 4/2, 2013 at 0:23 Comment(9)
How many did you have in mind?Flynt
Not knowing the count at compile time isn't an obstacle to writing a loop.Furman
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.Furman
@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.Meuser
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.Furman
@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 :)Meuser
(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.Furman
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!Turgent
@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.Meuser
S
147

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.

[Edit]

Note that this format specifier will print a left substring of the input, so the number you use has to be <= the width of the string

Surinam answered 30/4, 2013 at 12:25 Comment(12)
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)Spirogyra
Thanks, I remembered doing this 10 years ago , but forgot it and then rediscovered it.Surinam
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).Janey
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.Spirogyra
@synthesizerpatel: Your other answer is, at the moment, above this one, not below it.Furman
Indeed it is. The Internet means serious business.Spirogyra
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 :DSurinam
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.Gomuti
Nice catch! @SurinamLepsy
Why is there a dot inside the format? I can't find it in my references.Goolsby
@Goolsby - See cplusplus.com/reference/cstdio/printf under ".precision"Surinam
so we're just not gonna explain why you used 16 equals signs?Wileywilfong
S
75

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;
}
Spirogyra answered 23/5, 2013 at 12:8 Comment(4)
That's still limited to a fixed maximum number of characters.Furman
How so? Width can be any value if your sprintf is inside a function.Spirogyra
I don't clearly remember what I was thinking, but in your code the upper bound is 4096. I suppose you could malloc the buffer.Furman
@cheshirekow: He means that this is not a good way to accomplish the goal of printing char repeatedly. There is no reason to create an array full of '0' characters and then replace them with the desired character, instead of just filling it with the desired character in the first place (well, no reason except to somehow use a format string in the process, which is the point here.)Extravagant
S
46

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);
Scirrhous answered 11/8, 2015 at 6:46 Comment(2)
Why does an empty string print spaces? I don't understand that. Shouldn't the last argument be " " instead of "" ?Pondweed
@Pondweed 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.Scirrhous
B
22

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
Bump answered 15/5, 2013 at 5:21 Comment(2)
That's UB / read access violation. Your temporary std::string is already out of scope by the time you're c_str()-ing it. (For posterity. I realise it's a 9 years old answer.)Chappy
@zyndor: No, it is not. The temporary will be destroyed after the printf() call (since it is part of the same full-expression)Cablegram
J
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.

Janey answered 4/2, 2013 at 0:26 Comment(6)
Very strange that I can have the most complicated expressions, but something simple like repeating a character is not supported.Meuser
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.Janey
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... ;)Janey
@MatsPetersson Thats no solution, because I don't know the format string in advance, see my response to Mokammel.Meuser
Why is this being downvoted - if you are downvoting this answer, please let me know what it is you are unhappy with...Janey
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.Saxen
F
11

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.

Furman answered 4/2, 2013 at 0:53 Comment(7)
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.Meuser
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.)Furman
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.Meuser
@Joshua: The arguments to what function? Your question doesn't even mention a function.Furman
@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.Salahi
@Muis passing a format string from user input is an utterly awful idea from a security perspectiveHodgkins
int count = 10; while(count-->0) putchar('*');Erny
S
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'));
Shala answered 24/12, 2013 at 17:54 Comment(2)
I would suggest putchar('x') instead of printf("%c", 'x').Lacrosse
yes less overhead since you dont call the variadic function printf. However the 10 times call to write are very damaging to the performance.Zen
J
4
#include <stdio.h>
#include <string.h>

void repeat_char(unsigned int count, char ch) {
    char buffer[count + 1];
    memset(buffer, ch, count);
    buffer[count] = '\0';
    printf("%s", buffer)
}
Julesjuley answered 21/11, 2014 at 1:40 Comment(0)
M
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

#####
Missile answered 18/9, 2015 at 12:53 Comment(3)
putchar() would be a better fit for the repeat() loopRevulsion
Indeed, but I’ve tried to make my code very basic to be uderstandable for any entry-level coderMissile
would be better to use i < count. Otherwise a negative input for count might result in a lot of unwanted prints.Sisson
D
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 />
Duque answered 27/2, 2018 at 22:27 Comment(0)
A
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'.

Ancipital answered 27/4, 2014 at 16:26 Comment(0)
R
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:

----------------------------------------
|                                      |
|                                      |
|                                      |
|                                      |
|                                      |
----------------------------------------
Rosalynrosalynd answered 27/8, 2023 at 22:59 Comment(0)
D
-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);
Dermoid answered 4/2, 2013 at 0:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.