9 Stimmen

Konvertieren Sie mit C ein dynamisch zugewiesenes int-Array so sauber wie möglich in eine durch Kommata getrennte Zeichenkette

Ich habe viel weniger Erfahrung mit C als mit höheren Sprachen. Bei Cisco verwenden wir C, und manchmal stoße ich auf etwas, das in Java oder Python leicht, in C aber sehr schwer zu bewerkstelligen wäre.

Ich habe ein dynamisch zugewiesenes Array von ganzen Zahlen ohne Vorzeichen, die ich in eine kommagetrennte Zeichenfolge für die Protokollierung konvertieren muss. Während die Integer wahrscheinlich nicht sehr groß sein, könnten sie konzeptionell überall von 0 bis 4.294.967.295 In Python, das ist eine kurze Zeile sein.

my_str = ','.join(my_list)

Wie elegant kann man das in C machen? Ich habe einen Weg gefunden, aber er ist ekelhaft. Wenn jemand einen schönen Weg kennt, es zu tun, bitte erleuchten Sie mich.

2 Stimmen

Können Sie die Art und Weise posten, wie Sie es in C gemacht haben?

2 Stimmen

Moment, join() ist eine Funktion der Klasse string!?

0 Stimmen

@BibedalShark: es ist C und nicht C++; keine Klasse

1voto

Jonathan Graehl Punkte 8962
unsigned *a; /* your input a[N] */
unsigned i,N;
char *b,*m;
b=m=malloc(1+N*11); /* for each of N numbers: 10 digits plus comma (plus end of string) */
for (i=0;i<N;++i)
  b+=sprintf(b,"%u,",a[i]);
if (N>0) b[-1]=0; /* delete last trailing comma */
/* now use m */
free(m);

hübsch, nicht wahr? :)

1voto

prime_number Punkte 758
#include <stdio.h>
#include <stdlib.h>

/* My approach is to count the length of the string required. And do a single alloc.
     Sure you can allocate more, but I don't know for how long this data will be retained.
*/ 

#define LEN(a) (sizeof a / sizeof *a)

int main(void) {

    unsigned a[] = {1, 23, 45, 523, 544};
    int i, str_len=0, t_written=0;
    char tmp[11]; /* enough to fit the biggest unsigned int */

    for(i = 0; i < LEN(a); i++) 
        str_len += sprintf(tmp, "%d", a[i]);

    /* total: we need LEN(a) - 1 more for the ',' and + 1 for '\0' */
    str_len += LEN(a);
    char *str = malloc(str_len); 
    if (!str) 
        return 0;

    if (LEN(a) > 1) {
        t_written += sprintf(str+t_written, "%d", a[0]);
        for(i = 1; i < LEN(a); i++)
            t_written += sprintf(str+t_written, ",%d", a[i]);
    } else if (LEN(a) == 1) 
        t_written += sprintf(str+t_written, "%d", a[0]);

    printf("%s\n", str);

    free(str);
    return 0;
}

1 Stimmen

#define LEN(a) (sizeof a / sizeof *a)

1 Stimmen

Wie viel müssen Sie ändern, um dieses Hauptprogramm in eine wiederverwendbare Funktion umzuwandeln?

1 Stimmen

Ich erschaudere jedes Mal, wenn ich Leute sehe, die Längen von Strings oder Arrays in int Typen. Was ist so schrecklich an size_t ?

1voto

Doug T. Punkte 61739
Ihr und eure unnötigen Sonderfälle, die sich um das nachgestellte Komma kümmern... Es ist billiger, einfach das letzte Komma zu zerstören, als jedes Mal, wenn die Schleife läuft, eine bedingte Prüfung durchzuführen.

)

include <stdio.h>

char toStr(int arr[], unsigned int arrSize, char buff[]) { if (arr && arrSize && buff) { int currInt = arr; char currStr = buff; while (currInt < (arr + arrSize)) { currStr += sprintf(currStr, "%d,", currInt++); } *--currStr = '\0'; } return buff; }

int main() { int arr[] = {1234, 421, -125, 15251, 15251, 52}; char buff[1000];

printf("Arr is:%s\n", toStr(arr, 6, buff));    

}

Geht davon aus, dass buff groß genug ist, um (Länge des größten int + 2) * arrSize) zu sein. Inspiriert von meinem memcpy :)

Editar Ich erkannte, dass ich vorhin einen Hirnfurz hatte und einfach um den Rückgabewert von sprintf hätte inkrementieren können, anstatt temp zu speichern. Anscheinend tun andere Antworten dies auch, ich habe meine Antwort bearbeitet, um die 2 unnötigen Zeilen zu entfernen.

Bearbeiten2 Sieht aus wie wrang-wrang mir zuvorkommen! Seine Antwort ist so ziemlich identisch mit meiner und wurde früher eingereicht. Ich schlage demütig vor, ihm eine + 1 zu geben.

0 Stimmen

*--currStr = '\0' braucht einen erklärenden Kommentar für jeden, der den Code nach Ihnen pflegen muss. (i == 0 ? :) nicht.

0 Stimmen

Ich schätze, es ist eine Frage der Meinung, aber ich +1'd Ihre für tatsächlich sicherer über die Zeichenfolge len.

1 Stimmen

Dies bricht ab, wenn arrSize == 0. Auch müssen Sie s/size/arrSize/, mindestens.

0voto

Steven Schlansker Punkte 35955

Unter der Annahme, dass Sie mit "für die Protokollierung" das Schreiben in eine Protokolldatei meinen, könnte Ihre Lösung etwa so aussehen (pseudocodiert):

for (int x in array) {
    fprintf(log, "%d", x);
    if (! last element)
        fputc(log, ',');
}

0voto

pbos Punkte 466

Ich persönlich würde der Einfachheit und wahrscheinlich auch der Geschwindigkeit halber einen großen Puffer mit Platz für ein Array der Größe "4.294.967.295" und ", " für jedes Element mallocen. Das ist allerdings nicht sehr platzsparend bei der Erstellung der Liste!

Dann würde ich sprintf die ints in dort, und anhängen "," zu allen Elementen

Schließlich würde ich den Zeiger neu zuweisen, um nicht mehr Platz als nötig zu haben. (Größe = strlen)

sprintf: Bei Erfolg wird die Gesamtzahl der geschriebenen Zeichen zurückgegeben. Diese Zahl beinhaltet nicht das zusätzliche Null-Zeichen, das automatisch am Ende der Zeichenkette angehängt wird.

So behält man den Überblick über die Position von strcpy in der Zeichenkette :)

Ich hoffe, das hilft! :)

Und wenn Sie sie nur ausdrucken wollen, lesen Sie stattdessen die anderen Antworten. (for-Schleife und printf)

0 Stimmen

Eigentlich ist size = strlen-1, da Sie das abschließende "," nicht wollen. :)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X