2016-08-12 4 views
1

Also arbeite ich an einem Klassenprojekt, das einen Lagerbestand verwalten wird. Das Programm muss Produkte entfernen/hinzufügen sowie Bestandszählungen aktualisieren. Wenn das Programm ausgeführt wird, muss das Strukturarray von einer Inventardatei initialisiert werden, deren Werte durch Kommas getrennt sind, wodurch nach jeder Verwendung alle Daten gespeichert werden.Importieren einer CSV-Liste in eine Array-Struktur in C

Hier sind die Dateidaten.

1000,1.49,3.79,10,0,Fish Food 
2000,0.29,1.59,100,1,Angelfish 
2001,0.09,0.79,200,1,Guppy 
5000,2.40,5.95,10,0,Dog Collar (Large) 
6000,49.99,129.99,3,1,Dalmatian Puppy 

Hier ist das Strukturlayout.

struct inventory_s 
    { 
     int productNumber; 
     float mfrPrice; 
     float retailPrice; 
     int numInStock; 
     char liveInv; 
     char productName[PRODUCTNAME_SZ]; 
    }; 

Und hier ist der Code

int fileData() 
{ 

FILE* pFile; 
char *buf = malloc(MAX_INVENTORY); // MAX INVENTORY = 50 
char *info; 
if ((pFile = fopen("inventory.txt", "r")) == NULL) //Reading a file 
{ 
    printf("File could not be opened.\n"); 
} 

int i = 0; 
while (fgets(buf, MAX_INVENTORY, pFile) != NULL) 
{ 
    if ((strlen(buf)>0) && (buf[strlen (buf) - 1] == '\n')) 
     buf[strlen (buf) - 1] = '\0'; 

    info = strtok(buf, ","); 
    inventory[i].productNumber = atoi(info); 

    info = strtok(buf, ","); 
    inventory[i].mfrPrice = atof(info); 

    info = strtok(NULL, ","); 
    inventory[i].retailPrice = atof(info); 

     info = strtok(NULL, ","); 
    inventory[i].numInStock = atoi(info); 

    info = strtok(NULL, ","); 
    strcpy(inventory[i].liveInv, info); 

    info = strtok(NULL, ","); 
    strcpy(inventory[i].productName, info); 


    printf("%i, %f, %f, %i, %s, %s \n", inventory[i].productNumber , inventory[i].mfrPrice, inventory[i].retailPrice , inventory[i].numInStock, inventory[i].liveInv, inventory[i].productName); 

    i++; 
} 

fclose(pFile); 
return 0; 
} 

Gerade jetzt alles, was ich nicht bekommen, wenn ich den Code ausführen, aber wenn ich laufe nur bis zur ersten Initialisierung

info = strtok(buf, ","); 
inventory[i].productNumber = atoi(info); 

ich alle ersten Werte richtig zugeordnet.

+1

Entfernen Sie nicht das Probelesen "\ n" und ändern Sie Ihre Delimiterliste in '", \ n "'. –

+0

OT: 'printf (" Datei konnte nicht geöffnet werden. \ N ");' aber Sie fahren fort, den Code auszuführen ... Ich schlage vor, 'exit (EXIT_FAILURE);' zu beenden oder von der Funktion in diesem Fall zurückzukehren. –

+0

Hinweis: Verwenden Sie Gleitkomma niemals für genaue Werte/Berechnungen. Verwenden Sie Ganzzahlen, die auf die kleinstmögliche Größe skaliert sind (z.Cent) statt. – Olaf

Antwort

0

Fortsetzung von dem Kommentar, es ist schwer zu sagen, ohne Ihren gesamten Code zu sehen, wo das Problem sein kann. Das Ding, das herausspringt, ist jedoch, dass es keine Notwendigkeit gibt, das nachfolgende '\n' von buf vor dem Aufruf von strtok zu entfernen. Sie werden besser bedient, indem Sie ein Trennzeichen von ",\n" verwenden und strtok die letzte Zeichenfolge in jeder Zeile verarbeiten lassen.

würde ein kurzes Beispiel sein:

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

enum { PRODUCTNAME_SZ = 32, MAXINV = 128, MAXC = 512 }; 

typedef struct { 
    int productNumber; 
    float mfrPrice; 
    float retailPrice; 
    int numInStock; 
    char liveInv; 
    char productName[PRODUCTNAME_SZ]; 
} inventory_s; 

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

    inventory_s *inv = NULL; 
    char buf[MAXC] = "", *delim = ",\n"; 
    size_t allocsz = MAXINV, idx = 0; 
    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; 
    } 

    if (!(inv = malloc (sizeof *inv * allocsz))) { 
     fprintf (stderr, "error: virtual memory exhausted.\n"); 
     return 1; 
    } 

    while (fgets (buf, MAXC, fp)) { /* read each line */ 
     char *p = buf; 
     size_t val = 0;  /* tokenize line with strtok */ 
     for (p = strtok (p, delim); p; p = strtok (NULL, delim)) 
      switch (val) { /* switch controls assignment */ 
       case 0 : inv[idx].productNumber = (int)strtol (p, NULL, 10); 
          val++; break; 
       case 1 : inv[idx].mfrPrice = strtof (p, NULL); 
          val++; break; 
       case 2 : inv[idx].retailPrice = strtof (p, NULL); 
          val++; break; 
       case 3 : inv[idx].numInStock = (int)strtol (p, NULL, 10); 
          val++; break; 
       case 4 : inv[idx].liveInv = (char)strtol (p, NULL, 10); 
          val++; break; 
       case 5 : strncpy (inv[idx].productName, p, PRODUCTNAME_SZ); 
          inv[idx].productName[PRODUCTNAME_SZ-1] = 0; break; 
      } 
     if (val != 5) {  /* validate all struct members filled */ 
      fprintf (stderr, "error: incomplete parse of values line: %zu\n", 
        idx+1); 
      return 1; 
     } 

     if (++idx == allocsz) { /* realloc when allocsz reached */ 
      void *tmp = realloc (inv, (allocsz + MAXINV) * sizeof *inv); 
      if (!tmp) { 
       fprintf (stderr, "error: realloc - virtual memory exhausted.\n"); 
       break; /* leave read loop preserving exhisting data in inv */ 
      } 
      inv = tmp; 
      allocsz += MAXINV; 
     } 
    } 

    for (size_t i = 0; i < idx; i++) 
     printf ("%5d %6.2f %7.2f %4d %d %s\n", inv[i].productNumber, 
       inv[i].mfrPrice, inv[i].retailPrice, inv[i].numInStock, 
       inv[i].liveInv, inv[i].productName); 

    free (inv); /* free allocated memory */ 

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

    return 0; 
} 

Anmerkung: wenn Ihr liveInv Wert wirklich nur eine einzelne Ziffer ist, dann können Sie (char)strtol (p, NULL, 10); mit einfach *p - '0'; ersetzen.

Beispiel Verwendung/Output

$ ./bin/inventory <dat/inventory.txt 
1000 1.49  3.79 10 0 Fish Food 
2000 0.29  1.59 100 1 Angelfish 
2001 0.09  0.79 200 1 Guppy 
5000 2.40  5.95 10 0 Dog Collar (Large) 

schauen Sie vorbei (Sie können PRODUCTNAME_SZ größer je nach vollständigen Datensatz festlegen müssen) und lassen Sie mich wissen, wenn Sie Fragen haben.

0

Ich bin ein Java-Programmierer, aber jetzt Aufbau seiner so genannten Java-Sammlungen in C & C++. Dieser Code ist ein Teil meines Projekts "Big Data Analysis Using C & C++".

Ich hatte bereits den Code, also, für Ihre Daten geändert. Es kann jedes Nein nehmen. von Spalten. Übergeben Sie einfach den geöffneten Dateizeiger & Trennungsart.

Sie können eine bestimmte Spalte erhalten, indem Sie alle if Teile von j (zB if (j == 1) usw.) in Ihre spezielle Spalte entfernen. Die meisten Leute vergessen das. :-D

#include <iostream> 
#include <stdio.h> 

int MAX=1000; // Size of Single String 
void analyse(FILE *fp, char separation) { 
/* fp is file pointer (already opened) 
* separation is how data is separated (' ' or '\t' or ',') 
*/ 
    char str[MAX],ch; 
    int i=-1; 
    long j=0; 
// J is Column. This Can Be Applied For Any No. of Columns. 
    cout<<"Reading File.."<<endl; 
    while((ch=getc(fp))!=EOF) { 
     i++; 
     if(ch!=separation && ch!='\n') 
      str[i] = ch; 
     else { 
      str[i] = '\0'; 
      if(ch == separation || ch == '\n') { 
       j++; 
      } 
// At Each if of j, you can write you code to store them. 
      if(j == 1) { 
       cout<<"Product No. : "<<str<<endl; 
      } 
      if(j == 2) { 
       cout<<"MFR Price : "<<str<<endl; 
      } 
      if(j == 3) { 
       cout<<"Retail : "<<str<<endl; 
      } 
      if(j == 4) { 
       cout<<"Num in Stock : "<<str<<endl; 
      } 
      if(j == 5) { 
       cout<<"LiveInv : "<<str<<endl; 
      } 
      if(j == 6) { 
       cout<<"Product Name : "<<str<<endl; 
      } 
      cout<<"-------------------------------------"<<endl; 
      if(ch == '\n') 
       j = 0; 
      i = -1; 
     } 
    } 
    cout<<"Reading Completed.."<<endl; 
} 
Verwandte Themen