Wie wiederhole ich ein Zeichen mit printf?

79

Ich würde gerne etwas tun printf("?", count, char), um einen Charakter countmal zu wiederholen .

Was ist die richtige Formatzeichenfolge, um dies zu erreichen?

EDIT: Ja, es ist offensichtlich, dass ich printf()in einer Schleife aufrufen könnte , aber genau das wollte ich vermeiden.

Muis
quelle
2
Wie viele hatten Sie im Sinn?
WhozCraig
4
Wenn Sie die Anzahl zur Kompilierungszeit nicht kennen, ist dies kein Hindernis für das Schreiben einer Schleife.
Keith Thompson
Ihre Frage ist ziemlich klar (und die eigentliche Antwort ist, dass es kein printfFormat gibt, das das tut, was Sie wollen), aber Ihre Kommentare lassen mich unsicher, was Sie fragen. Sie sprechen von einer Formatzeichenfolge und Argumenten, die an Ihre Funktion übergeben werden. Nach welcher Funktion fragen Sie? Es scheint, dass es Dinge gibt, die Sie uns nicht erzählen.
Keith Thompson
@KeithThompson Ich habe einen Wrapper um 'printf' geschrieben, daher waren diese Argumente dieselben wie für das Original, entschuldigen Sie die Verwirrung. Und ich hätte den Grund dafür besser beschreiben sollen, Sie haben Recht.
Muis
Ich fürchte, ich habe immer noch keine klare Vorstellung davon, was Sie versuchen oder (keine Beleidigung für @synthesizerpatel), warum Sie die Antwort akzeptiert haben, die nicht als ernsthafte Lösung gedacht war.
Keith Thompson

Antworten:

61

Kurze Antwort - ja, lange Antwort: nicht so, wie Sie es wollen.

Sie können die% * -Form von printf verwenden , die eine variable Breite akzeptiert. Und wenn Sie zum Drucken '0' als Wert verwenden, kombiniert mit dem rechtsbündigen Text, der links mit Null aufgefüllt ist.

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

produziert:

00000000000000000000

Mit fest in die Wange gesteckter Zunge biete ich diesen kleinen Horror-Show-Code-Ausschnitt an.

Manchmal muss man die Dinge nur schlecht machen, um sich daran zu erinnern, warum man sich den Rest der Zeit so sehr bemüht.

#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
quelle
3
Ich erinnere mich nicht genau, was ich gedacht habe, aber in Ihrem Code ist die Obergrenze 4096. Ich nehme an, Sie könnten mallocden Puffer.
Keith Thompson
2
Meinetwegen. Messerkampf == abgewendet!
Synthesizerpatel
4
Dieser Stil ist besser als das direkte Zuweisen von Zeichen in einer Schleife.
Liuyang1
2
Ja. Diese Methode ist schrecklich, beantwortet aber die Frage des OP.
Synthesizerpatel
2
Kannst du bitte klarstellen, was du mit Horrorshow meinst? Ich habe das Gefühl, Sie versuchen vor etwas zu warnen, aber ich bin mir nicht sicher, was ... versuchen Sie nur, auf die Gefahr eines Überlaufs hinzuweisen, wenn Sie "% *" verwenden?
Cheshirekow
116

Sie können die folgende Technik verwenden:

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

Dies wird gedruckt. "=====" Es funktioniert für mich in Visual Studio, kein Grund, warum es nicht auf allen C-Compilern funktionieren sollte.

rep_movsd
quelle
3
Es ist bedauerlich, dass diese Antwort nicht höher bewertet wird, da sie nicht nur korrekt ist, sondern auch plattformübergreifend funktioniert. Getestet unter OSX, Linux und OpenBSD in C sowie Perl (das den C-Druck umhüllt)
Synthesizerpatel
3
Danke, ich habe mich daran erinnert, dies vor 10 Jahren getan zu haben, es aber vergessen und dann wiederentdeckt.
rep_movsd
19
Es ist nicht gerade flexibel. Wenn die Breite größer als die Zeichenfolge selbst ist, wird nicht mehr als die Zeichenfolge gedruckt (zumindest nicht in meinem einfachen Experiment mit gcc).
Mats Petersson
1
Dies funktioniert besser als die Antwort von Synthesizerpatel. Wenn ich Leerzeichen anstelle einer Null ausprobiert habe und die Breite Null ist, wird immer noch ein einzelnes Leerzeichen gedruckt. Dieser tut es nicht.
schwarz
1
Schöner Fang! @rep_movsd
Juan Diego Godoy Robles
24

Wenn Sie sich darauf beschränken, entweder eine 0 oder ein Leerzeichen zu wiederholen, können Sie Folgendes tun:

Für Räume:

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

Für Nullen:

printf("%0*d", count, 0);
Ariel
quelle
18

In c ++ können Sie std :: string verwenden, um wiederholte Zeichen zu erhalten

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

Zum Beispiel:

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

Ausgabe:

aaaaa
Kristian Gregersen
quelle
15
Die Frage betraf C, nicht C ++.
Keith Thompson
9
Obwohl es nicht ausschließlich C ist, hat mir das geholfen. Vielen Dank
Portland Runner
1
C ++ Frage: stackoverflow.com/questions/7897163/…
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功
12

Es gibt keine solche Sache. Sie müssen entweder eine Schleife mit printfoder putsschreiben oder eine Funktion schreiben, die die Anzahl der Zeichenfolgen in eine neue Zeichenfolge kopiert.

Mats Petersson
quelle
2
Sehr seltsam, dass ich die kompliziertesten Ausdrücke haben kann, aber etwas Einfaches wie das Wiederholen eines Zeichens wird nicht unterstützt.
Muis
Warum? Sie können dies einfach tun, indem Sie eine Schleife um das hinzufügen, was Sie wiederholen möchten. Das meiste, was printf tut, sind Dinge, die Sie in Ihrem eigenen Code nicht [sehr einfach] tun können. Lassen Sie Bibliotheken den schwierigen Teil erledigen, und das Anwendungsprogramm erledigt den einfachen Teil. Ich denke, das ist das Thema hier.
Mats Petersson
5
Und wenn Sie sich stark dafür fühlen, ist das C-Standard-Komitee wahrscheinlich an Verbesserungsvorschlägen interessiert, und eine Beispielimplementierung in glibc würde möglicherweise die Chancen verbessern, dass es jemals zum Standard wird. Wenn Sie es implementieren, wird vielleicht jemand anderes denken, dass es eine gute Idee ist. Es hat erst in den letzten 50 Jahren seit der Einführung von printf gefehlt, also ist es vielleicht nur ein Versehen ...;)
Mats Petersson
@MatsPetersson Das ist keine Lösung, da ich die Formatzeichenfolge nicht im Voraus kenne, siehe meine Antwort auf Mokammel.
Muis
2
Warum wird dies abgelehnt - wenn Sie diese Antwort ablehnen, lassen Sie mich bitte wissen, womit Sie unzufrieden sind ...
Mats Petersson
6

printfmacht das nicht - und printfist übertrieben, um ein einzelnes Zeichen zu drucken.

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

Mach dir keine Sorgen, dass dies ineffizient ist. putchar()puffert seine Ausgabe, sodass keine physische Ausgabeoperation für jedes Zeichen ausgeführt wird, es sei denn, dies ist erforderlich.

Keith Thompson
quelle
Ich kenne die Formatzeichenfolge oder die Argumente, die an meine Funktion übergeben werden, nicht. Sie können aus einer XML-Datei gelesen oder vom Benutzer eingegeben werden.
Muis
Sie haben das Zeichen und die Häufigkeit, mit der Sie es drucken müssen, oder? Welche weiteren Informationen benötigen Sie? Um ein einzelnes Zeichen mit zu drucken printf, lautet die Formatzeichenfolge "%c". Aber Sie müssen nicht verwenden printf, und in diesem Fall benötigen Sie überhaupt keine Formatzeichenfolge. (Es gibt einfach keine printfFormatzeichenfolge, die ein Zeichen mehrmals druckt, aber es gibt andere und bessere Möglichkeiten, um die Aufgabe zu erfüllen.)
Keith Thompson
Wie gesagt, ich weiß nicht, was die Argumente für meine Funktion bedeuten. Angenommen, ich lese die Formatzeichenfolge und die Argumente aus einer XML-Datei und übergebe sie an printf (). Wie würde meine Funktion jemals erkennen, dass eine Schleife erforderlich ist und das zweite Argument eine Anzahl darstellt? Das meine ich damit, dass meine Eingabe zur Kompilierungszeit nicht bekannt ist.
Muis
4
@ Joshua: Die Argumente für welche Funktion? Ihre Frage erwähnt nicht einmal eine Funktion.
Keith Thompson
1
@Joshua Sie sind wirklich verwirrt, was sich aus Ihrer übermäßigen Nutzung der Kompilierungszeit und der Funktion ergibt, die Sie kennen werden. Es ist wirklich nicht so schwierig, wie Sie es erscheinen lassen. Sie benötigen eine Funktion, um ein Zeichen 'x' n-mal zu drucken. Wenn es aus XML stammt, analysieren Sie die XML-Datei und finden Sie heraus, welches Zeichen gedruckt werden soll und wie oft es gedruckt werden muss. Verwenden Sie strlen, um die Zeichenfolgenlänge an Stellen abzurufen, an denen Ihr XML-Zeichenfolgenfeld entscheidet, wie oft das Zeichen 'x' gedruckt werden muss.
SayeedHussain
6

Wenn Sie einen Compiler haben, der die Funktion alloca () unterstützt, ist dies eine mögliche Lösung (allerdings ziemlich hässlich):

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

Grundsätzlich werden 10 Bytes auf dem Stapel zugewiesen, die mit '\ 0' gefüllt sind, und dann werden die ersten 9 Bytes mit 'x' gefüllt.

Wenn Sie einen C99-Compiler haben, ist dies möglicherweise eine bessere Lösung:

for (int i = 0;  i < 10;  i++, printf("%c", 'x'));
Ramon
quelle
4
Ich würde putchar('x')stattdessen vorschlagen printf("%c", 'x').
Paddu
Warum? Ist die Ausführungszeit kürzer?
71GA
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)
}
Pavlos Fragkiadoulakis
quelle
2

Sie können eine Funktion erstellen, die diesen Job ausführt, und sie verwenden

#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;
}

Dies wird ausgegeben

#####
Loay Hussein
quelle
2
putchar () würde besser für die repeat ()
rsaxvc
In der Tat, aber ich habe versucht, meinen Code so einfach zu gestalten, dass er für jeden Einsteiger-Codierer verständlich ist
Loay Hussein
wäre besser zu benutzen i < count. Andernfalls kann eine negative Eingabe für die Anzahl zu vielen unerwünschten Ausdrucken führen.
イ き. ぐ
1
printf("%.*s\n",n,(char *) memset(buffer,c,n));

n<= sizeof(buffer)[vielleicht auch n <2 ^ 16]

Der Optimierer kann es jedoch ändern puts(buffer)und dann wird das Fehlen von EoS .....

Und die Annahme ist, dass memset ein Assembler-Befehl ist (aber immer noch eine Schleife, sei es auf dem Chip).

Streng genommen gibt es keine Lösung unter der Voraussetzung 'Keine Schleife'.

Rene
quelle
0
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 />
Charles
quelle
-2

Ich denke, so etwas zu tun.

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

printchar("*",10);
Lindosekai
quelle