2017-07-10 3 views
2

Was ich tun möchte, ist die gesamte erste Zeile der Datei zu lesen, aber dann nach der ersten Zeile lesen Sie nur die folgenden Zeilen, bis Whitespace getroffen wird. Mein Endziel ist es, den Benutzer zu fragen, welche Zeile er bearbeiten möchte, indem er der Zeile Zeit hinzufügt/subtrahiert.Einfaches C-Programm zum Lesen einer Datei Zeile für Zeile

Beispieldatei

My test file 
00:19.1 123456 
00:35.4 testing whitespace end 

gewünschte Ausgabe

1: My test file 
2: 00:19.1 
3: 00:35.4 

Code:

#include <stdio.h> 
#include <stdlib.h> 

int main() 
{ 
    FILE *fptr1, *fptr2; 

    char filechar[40]; 
    char c[50]; 
    int line_number = 1; 
    int replace_line, temp = 1; 

    printf("Please enter a file name: "); 
    scanf("%s", &filechar); 

    if ((fptr1 = fopen(filechar, "r")) == NULL) 
    { 
     printf("Error locating desired file"); 
     exit(1); 
    } 

    c = getc(fptr1); 
    while (c != EOF) 
    { 
     //printf("%d: %c",line_number, c); 
     printf("%s",c); 
     c = getc(fptr1); 
     //line_number++; 
    } 
    return 0; 
} 
+0

Hat Ihr Compiler die 'getline' Funktion haben: http://en.cppreference.com/w/c/experimental/dynamic/getline –

+2

Drop the' & 'in' scanf ("% s", & filechar); '-' scanf() 'erwartet ein' char * 'und Sie übergeben ein' char (*) [50] ', das ein anderer Typ ist (obwohl der Wert passiert so, dass es nur "filechar" ist, also kommst du damit durch. –

+0

Benutze entweder ['fgets()'] (http://pubs.opengroup.org/onlinepubs/9699919799/ Funktionen/fgets.html) oder POSIX ['getline()'] (http://pubs.opengroup.org/onlinepubs/9699919799/functions/getline.html) um Zeilen zu lesen. Dann verwenden Sie 'strchr()' oder ähnliches, um das erste Leerzeichen zu finden. Oder lesen Sie die erste Zeile mit einem dieser beiden, lesen Sie dann die folgenden ersten Felder mit 'scanf ("% s% * [^ \ n]% * c ", erstes_Feld);' - siehe ['scanf()'] (http : //pubs.opengroup.org/onlinepubs/9699919799/functions/scanf.html) für eine Erklärung. Im Großen und Ganzen würde ich für zeilenbasierte Eingabe und 'strchr()' gehen; Sie könnten 'strtok()' oder 'sscanf()' verwenden. –

Antwort

0

Bitte versuchen, wenn dieser Code C kann Ihnen helfen. Es liest nur die Datei Zeile für Zeile und ersetzt Leerzeichen durch das Zeichenfolge-Beendigungszeichen \0.

#define _GNU_SOURCE 
#include <stdio.h> 
#include <stdlib.h> 
#include <memory.h> 

char* replace_char(char* str, char find, char replace){ 
    char *current_pos = strchr(str,find); 
    while (current_pos){ 
     *current_pos = replace; 
     current_pos = strchr(current_pos,find); 
    } 
    return str; 
} 
int main(void) 
{ 
    FILE * fp; 
    char * line = NULL; 
    size_t len = 0; 
    ssize_t read; 

    fp = fopen("/home/developer/CLionProjects/untitled4/download.out", "r"); 
    if (fp == NULL) 
     exit(EXIT_FAILURE); 
    int count=0; 
    while ((read = getline(&line, &len, fp)) != -1) { 
     if (count==0) printf("%s", line); 
     else printf("%s\n", replace_char(line, ' ', '\0')); 
     count++; 
    } 

    fclose(fp); 
    if (line) 
     free(line); 
    exit(EXIT_SUCCESS); 
} 

Datei

My test file 
00:19.1 123456 
00:35.4 testing whitespace end 

Ausgabe

My test file 
00:19.1 
00:35.4 
+0

Ich bekomme zwei Fehler bei der Verwendung dieser Methode. Der erste ist ein nicht definierter Bezug auf getline, der zweite ist ld returned 1 exit status. – Collin

2

In C Sie haben Zeicheneingabe orientierte Funktionen (zB getchar, fgetc), haben Sie formatierte Eingabe Funktionen (zB die scanf Familie) und dann hast du Zeilenorientierte Eingabe Funktionen. (z.B. fgets und POSIX getline). Wenn Sie Zeilen Daten, Zeile orientierte Eingabe Funktionen lesen, sind das richtige Werkzeug für den Job. (Unter Benutzereingabe mit scanf hat viele Fallen, die neue (und auch nicht so neu) C-Programmierer in den Herbst)

Alle Linie orientierte Funktionen lesen und schließen die '\n' im Puffer sie zu füllen. Sie können und sollten den Zeilenumbruch aus dem resultierenden Puffer entfernen, wenn er später in Ihrem Code verwendet wird. Eine einfache

size_t n = strlen (buf); 
if (buf[n-1] == '\n') 
    buf[--n] = 0; 

ist alles, was Sie das hintere '\n' mit einem nul abbreche Zeichen zu überschreiben müssen. Wenn Sie die Zeile sofort drucken und nicht für die spätere Verwendung speichern, lohnt es sich nicht, den Zeilenumbruch zu entfernen (berücksichtigen Sie dies in Ihrer Ausgabe Formatstring).

zusammen die Stücke Einlochen, können Sie jede Zeile lesen, verarbeiten die erste, indem sie es einfach ausgegeben wird, und für jede verbleibende Leitung, analysieren die Zeit (vermutliche einige verstrichene Zeit) aus der vollständigen Zeichenfolge gelesen von fgets mit sscanf und Formatieren Sie die Ausgabe wie angegeben. Z.B.

#include <stdio.h> 

#define MAXC 64  /* define constants, don't use magic number in code */ 

int main (int argc, char **argv) { 

    char buf[MAXC] = ""; /* buffer to hold each line -- size as reqd */ 
    int line = 1; 
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin; 

    if (!fp) { /* validate file open for reading */ 
     fprintf (stderr, "error: file open failed '%s'.\n", argv[1]); 
     return 1; 
    } 

    while (fgets (buf, sizeof buf, fp)) { /* read each line in file */ 
     char et[MAXC] = "";     /* buffer for holding time */ 
     if (line == 1)      /* if 1st line, just print */ 
      printf ("%d : %s", line, buf); /* note: \n included by fgets */ 
     else { 
      if (sscanf (buf, "%s", et) != 1) { /* parse up to first whitespace */ 
       fprintf (stderr, "error: invalid conversion, line %d\n", line); 
       return 1; 
      } 
      printf ("%d : %s\n", line, et); /* output elapsed time only */ 
     } 
     line++;        /* increment line count */ 
    } 

    if (fp != stdin) fclose (fp);   /* close file if not stdin */ 

    return 0; 
} 

Anmerkung: Sie gegen Puffer auf Parse überrannt schützen sollen einen Feldbreite Bezeichnern in dem sscanf Format-String, indem (zsscanf (buf, "%63s", et), und das ist ein Ort, der alles, was Sie magische Zahlen umfassen tun können in Ihrem Code, weil es keine Möglichkeit gibt, direkt eine variable Breite Spezifizierer für sscanf angeben - es sei denn, Sie kreativ sprintf verwenden, um die Format-String voraus zu erstellen Zeit - aber das ist für einen anderen Tag ..

Beispiel Eingabedatei

$ cat dat/et.txt 
My test file 
00:19.1 123456 
00:35.4 testing whitespace end 

Beispiel Verwendung/Output

$ ./bin/et <dat/et.txt 
1 : My test file 
2 : 00:19.1 
3 : 00:35.4 

Schauen Sie die Dinge über und lassen Sie mich wissen, wenn Sie weitere Fragen haben.

(Hinweis: Ich nehme den Dateinamen als erstes Argument für das Programm, oder lesen von stdin, wenn kein Dateiname angegeben ist. C bietet für Befehlszeilenargumente - verwenden Sie sie. Es ist in Ordnung, um Eingabe bei Bedarf, andernfalls , seine viel einfacher, nur Argumente auf der Kommandozeile angeben :)

+0

Vielen Dank, das funktioniert in gewissem Maße. Können Sie die ungültige Conversion-Zeile erklären, die Sie hinzugefügt haben? Vier Zeilen in meiner Testdatei habe ich ausgespielt. 'Zeile 1: Meine Testdatei Zeile 2: 00: 19,1 009-021 Zeile 3: 00: 35,4 017-003 018-003 Zeile 4: 00: 35,5 017-000 018-000' – Collin

+0

Sicher, es ist nur eine * Bestätigung *, dass * eine Umwandlung in '% s' * von' sscanf' durchgeführt wurde. (im Wesentlichen überprüfe ich nur die 'return' von' sscanf') Wenn 'sscanf' aus irgendeinem Grund fehlgeschlagen ist (was mit dem'% s' eher unwahrscheinlich ist), wollen Sie nicht weiter mit 'et' arbeiten als das wäre * Undefiniertes Verhalten *. C stellt keine Sicherheitsnetze zur Verfügung, es liegt also an Ihnen, alle Eingaben, Konvertierungen usw. zu validieren. '') 'Recall, alle' scanf' -Funktionen geben die Anzahl der erfolgreichen Konvertierungen zurück. –

+0

Okay, ich verstehe jetzt. Danke für die Hilfe! – Collin

Verwandte Themen