2016-04-02 4 views
0

Okay, also weiß ich, wie man Werte aus einer Datei in eine Struktur einfügt.Setzen von Werten in eine Struktur aus einer Datei

Meine Werte in der Datei sind meine Kommata getrennt. Die Daten sind wie folgt aus:

number, product, price, other 

Nur einige Elemente den anderen Wert haben!

Wie habe ich einen optionalen Wert in einer Struktur?

so:

typedef struct stockItem { 
    int number; 
    char* product; 
    int price; 
    char *other; 
} stockItem; 

ich die Daten so etwas wie diese Eingabe:

while (fgets(str, 255, invf) != NULL){ 
    int numOfItems = atoi(strtok(str, " ,")); 
    char *stockCode = strtok(NULL, " ,"); 
    int price = atoi(strtok(NULL, " ,")); 
    char *other = strTok(NULL, " ")); 

    stockItem *item = stockItem_new(numOfItems , stockCode, price, other); 

Es ist natürlich nicht ausgeführt, weil einige Elemente, die andere haben, was sollte ich mache? Sollte ich null in jeden Wert einfügen, der keinen anderen hat?

Antwort

3

Ja, Sie sollten für jedes Element, das dieses Feld nicht enthält, other auf NULL setzen. Dies ist der normale Weg, auf die Abwesenheit von etwas hinzuweisen, auf das hingewiesen wird.

Außerdem gibt strtok() einen internen Zeiger an str zurück, den Sie für jedes Element wiederverwenden. Sie sollten sicherstellen, dass Ihre stockItem_new() Funktion diese Daten tatsächlich kopiert (strdup() oder strcpy()) und nicht nur dieses Feld gleich dem Zeiger setzt, oder dieses Feld in allen Ihren struct s wird am Ende auf den gleichen Speicher zeigen, der jede ändern wird Zeit, die Sie anrufen fgets(), und wird wahrscheinlich nicht mehr existieren, nachdem Ihre Lesefunktion zurückgibt.

Hier ist ein Beispielcode:

#define _POSIX_C_SOURCE 200809L 

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

#define BUFFER_SIZE 256 

struct stock_item { 
    int number; 
    char * product; 
    int price; 
    char * other; 
}; 

struct stock_item * stock_item_new(const int num_items, 
            const char * stock_code, 
            const int price, 
            const char * other); 
void stock_item_destroy(struct stock_item * item); 
void stock_item_print(struct stock_item * item); 

int main(void) 
{ 
    FILE * fp = fopen("data.txt", "r"); 
    if (!fp) { 
     perror("couldn't open data file"); 
     return EXIT_FAILURE; 
    } 

    char buffer[BUFFER_SIZE]; 
    const char * delim = " ,\n"; 
    while (fgets(buffer, BUFFER_SIZE, fp)) { 
     int num_items = atoi(strtok(buffer, delim)); 
     char * stock_code = strtok(NULL, delim); 
     int price = atoi(strtok(NULL, delim)); 
     char * other = strtok(NULL, delim); 

     struct stock_item * new_item; 
     new_item = stock_item_new(num_items, stock_code, price, other); 

     stock_item_print(new_item); 

     stock_item_destroy(new_item); 
    } 

    fclose(fp); 

    return 0; 
} 

struct stock_item * stock_item_new(const int num_items, 
            const char * stock_code, 
            const int price, 
            const char * other) 
{ 
    struct stock_item * new_item = malloc(sizeof *new_item); 
    if (!new_item) { 
     perror("couldn't allocate memory for stock item"); 
     exit(EXIT_FAILURE); 
    } 

    new_item->number = num_items; 
    new_item->price = price; 

    new_item->product = strdup(stock_code); 
    if (!new_item->product) { 
     perror("couldn't allocate memory for product name"); 
     exit(EXIT_FAILURE); 
    } 

    if (other) { 
     new_item->other = strdup(other); 
     if (!new_item->other) { 
      perror("couldn't allocate memory for 'other' field"); 
      exit(EXIT_FAILURE); 
     } 
    } 
    else { 
     new_item->other = NULL; 
    } 

    return new_item; 
} 

void stock_item_destroy(struct stock_item * item) 
{ 
    free(item->product); 
    free(item->other); 
    free(item); 
} 

void stock_item_print(struct stock_item * item) 
{ 
    printf("%d, %s, %d, %s\n", item->number, item->product, 
      item->price, item->other ? item->other : "(none)"); 
} 

die, wenn sie mit den folgenden Daten-Datei ausführen:

[email protected]:~/src/sandbox/itemfile$ cat data.txt 
20, rifle, 99 
33, bucket, 30, plastic 
50, fish, 5, gold 
12, hammer, 45, left-handed 
9, backscratcher, 13 
[email protected]:~/src/sandbox/itemfile$ 

erzeugt die folgende Ausgabe:

[email protected]:~/src/sandbox/itemfile$ ./itemfile 
20, rifle, 99, (none) 
33, bucket, 30, plastic 
50, fish, 5, gold 
12, hammer, 45, left-handed 
9, backscratcher, 13, (none) 
[email protected]:~/src/sandbox/itemfile$ 

Die stock_item_print() Funktion prüft, ob Das Feld other ist NULL, und wenn es ist, gibt "(none)" aus. Ansonsten druckt es normal.

Beachten Sie auch, dass NULL-free() vorbei ist in Ordnung, so müssen wir das other Feld in der stock_item_destroy() Funktion nicht aktivieren.

Schließlich habe ich keine Änderungen daran vorgenommen (außer '\n' zu der Liste der Trennzeichen hinzufügen), aber Ihr Parsing-Code mit strtok() ist sehr fragil, und sollte erweitert werden, um viel mehr Fehlerprüfung enthalten. Zum Beispiel ist strtol() besser als atoi(), und Sie sollten jedes Mal überprüfen, ob strtok()NULL zurückgibt.

+0

Ich habe sichergestellt, dass ich straddup innerhalb der stockItem_new() verwendet habe, also würde ich innerhalb meiner Struktur die Werte auf NULL ändern oder würde ich es in der Schleife tun? – Blarsssss

+0

Am einfachsten ist es in der Schleife zu tun. Dann kann 'stockItem_new()' überprüfen, ob der Wert von 'other', der an ihn übergeben wurde,' NULL' ist. Wenn dies der Fall ist, kann das Feld auf "NULL" gesetzt werden. Wenn nicht, kann es kopiert werden, genau wie bei 'stockCode'. –

+0

also, wenn ich es in der Schleife tun würde, müsste ich es auf NULL nach jeder Schleife setzen sonst würde der Wert nicht weitermachen? – Blarsssss

Verwandte Themen