2010-02-03 9 views
6

Lesen brauche ich wie eine Eingabedatei zu lesen:unbekannte Anzahl von ganzen Zahlen von stdin (C)

1 
19 20 41 23 
2 
41 52 43 
3 
90 91 941 
4 
512 
5 

6 
51 61 

Jede ungerade Linie ist eine ganze Zahl. Jede gerade Linie ist eine unbekannte Anzahl von ganzen Zahlen.

Es ist sehr einfach in C++

while(cin >> k){ 
............ 
} 

Ich bin so nicht zu C verwendet, so könnte ich es in C macht Alle Möglichkeiten, es zu tun?

+1

Haben Sie die Aufmerksamkeit auf Linien zu zahlen, oder ist das nur eine Reihe von ganzen Zahlen nicht kommt? In Ihrem Beispiel sieht es so aus, als ob die ungeraden Zeilen Sequenznummern sind und die geraden Zeilen etwas anderes darstellen. –

+0

david Ich muss auf die Zeilen achten. deshalb konnte ich es nicht tun. Ich muss aufhören, neue Werte am Ende jeder geraden Linie zu bekommen. Weil ich eine Struktur mit Attributen ID und Liste habe. jede ungerade Zeile ist eine ID und jede gerade Zeile ist eine Liste. Ich möchte eine Struktur mit 2 Zeilen von Daten füllen und zu einer anderen Struktur und füllen Sie sie mit weiteren 2 Zeilen von Daten etc ... – huhuhuuu

+0

Lesen Sie eine ganze Zeile zu einer Zeit und dann nur als String analysieren –

Antwort

9

So wie ich das tun würde, sie es in zwei Operationen zu brechen ist: eine Zeile gelesen, dann die ganzen Zahlen in dieser Zeile lesen. Hier ist eine faule Implementierung der Standard-C-Bibliothek:

char line[1024], *p, *e; 
long v; 
while (fgets(line, sizeof(line), stdin)) { 
    p = line; 
    for (p = line; ; p = e) { 
     v = strtol(p, &e, 10); 
     if (p == e) 
      break; 
     // process v here 
    } 
} 
+2

Vielen Dank. Ich werde es jetzt versuchen. Aber was, wenn ich nicht eine feste maximale Leitungslänge annehmen kann? – huhuhuuu

+2

Was ist, wenn der Eingabestream mehr als 1024 - 2 Zeichen enthält und 'fgets()' den Eingabestrom an einem numerischen Literal aufteilt? Sie werden mit zwei numerischen Werten anstelle von einem enden. Zum Beispiel könnte man 12345 in der letzten Iteration der for-Schleife und 45 in der ersten Iteration der for-Schleife nach dem nächsten Aufruf von 'fgets()' erhalten. Daher würde ich 'scanf()' und 'fscanf()' für diese Aufgabe bevorzugen, wie von Sean gezeigt. –

+1

@RobinKlose: Die von Sean veröffentlichte 'scanf()' Lösung löst das Problem nicht, da sie keine Zeilenumbrüche von anderen Leerzeichen unterscheidet. –

11

Laufen Ihre Eingabedatei durch:

#include <stdio.h> 

int main() { 
     int k; 
     while (scanf("%d", &k) == 1) { 
       printf("read number: %d\n", k); 
     } 
     return 0; 
} 

Ergebnisse in:

 
read number: 1 
read number: 19 
read number: 20 
read number: 41 
read number: 23 
read number: 2 
read number: 41 
read number: 52 
read number: 43 
read number: 3 
read number: 90 
read number: 91 
read number: 941 
read number: 4 
read number: 512 
read number: 5 
read number: 6 
read number: 51 
read number: 61 

Dies ist der C-Analogon des Code, den Sie in Ihrer ursprünglichen Frage verweisen.

+0

kann ich Lesen Sie die Zeile korrekt, aber die Scanf-Schleife druckt die erste Nummer für mich. – tarabyte

0

hat einen Blick auf getc (3) oder scanf (3)

1

ich tun würde, eines von:

  • fgetc() einzelne Zeichen zu lesen und zu analysieren, sie selbst (akkumulieren Ziffern, bis Sie Leerzeichen getroffen und Sie haben eine ganze Zahl mit atoi() zu konvertieren; wenn das Leerzeichen ein newline ist, dann ist es eine Liste von ganzen Zahlen beendet)

  • fgets(), um eine Zeile zu einem Zeitpunkt zu lesen, und dann die Zeichenfolge analysiert (wieder, Suche nach Leerzeichen, die die Werte trennen, die zurückgegeben werden.

3

Ich würde das Programm in verschiedenen Aufgaben brechen.

Der erste Schritt ist in der Lage sein, ein Paar Zeilen zu lesen, die erste Zeile, die die Anzahl der Zahlen sagt zu lesen, und dann die zweite Zeile die tatsächlichen Zahlen zu lesen. Dazu rief eine Funktion so etwas wie read_set könnte nützlich sein. Es sollte in der Lage sein, die gelesenen Zahlen zurückzugeben und das Ende der Datei sowie Fehler zu signalisieren. Dazu können wir eine Datenstruktur wie definieren:

struct numbers { 
    long *data; /* or choose a type depending upon your needs */ 
    size_t len; 
}; 

und dann können wir unsere Funktion mit dem Prototyp deklarieren:

int read_set(FILE *fp, struct numbers *num); 

Die Funktion Speicher für num->data zuteilen wird, und legen Sie num->len auf die korrekter Wert. Es gibt 0 für den Erfolg und ansonsten eine Reihe von Fehlerbedingungen zurück. Wir könnten Lust bekommen und später eine enum für die Rückkehr Status verwenden. Denn jetzt, sagen wir, dass 0 = Erfolg, 1 = Ende der Datei, und alles, was ein Fehler ist.

Der Anrufer ruft dann read_set() in einer Schleife:

struct numbers numbers; 
int status; 
while ((status = read_set(fp, &numbers)) == 0) { 
    /* process numbers->data, and then free it */ 
} 
if (status == 1) { 
    /* hit end of file, everything is OK */ 
} else { 
    /* handle error */ 
} 

Für read_set() Umsetzung: Es hat zwei Zeilen zu lesen. Es gibt viele implementations of reading a full line in C, so dass Sie eine von ihnen verwenden können, und lesen Sie zuerst eine Zeile, dann sscanf()/strtoul() es für eine Nummer (überprüfen Sie den Rückgabewert!). Sobald Sie die Anzahl der Zahlen, n, können Sie die nächste Zeile in dem Speicher gelesen, und tun:

num->data = malloc(n * sizeof *num->data); 
num->len = n; 

können Sie dann sscanf() oder strtol() wiederholt Rufnummern zu speichern, in num->data. Sie sollten überprüfen, um sicherzustellen, genau n Zahlen sind in dieser Zeile.

Beachten Sie, dass Sie read_set() auch auf andere Weise schreiben können: lesen Sie eine Zeile Zeichen für Zeichen, und analysieren Sie die Zahlen beim Lesen. Dies hat den Vorteil, dass die Daten nur einmal durchlaufen werden und kein großer Puffer benötigt wird, um die gesamte Eingabezeile im Speicher zu speichern, aber der Nachteil besteht darin, dass man selbst Low-Level-Stuff ausführt und Zeichen für Zeichen langsam liest.

0

Ich kam mit einer Lösung wie folgt auf:

while(scanf("%d%c", &n, &ch)!=EOF) 
{ 
    if(ch=='\n') break; 
    /* rest of your code */ 
} 
+0

/* Rest von yout Code */sollte nach der Schleife sein. –