2012-12-06 34 views
0

在我的程序的功能,我想從文件中加載數據到這個結構數組:c - 從中​​文件加載用於fgets和sscanf

/* database struct */ 
typedef struct node { 
    char  name[MAX]; 
    char  address[MAX]; 
    long int number; 
}record_type; 

record_type record[100]; 

的功能如下:

/* load database from disk */ 
void load_database() { 
    char line[128]; 

    /* Set up database */ 
    database = fopen("database.txt", "r+w+a+"); 
    if(database == NULL) { 
     printf("\n\tWARNING: No database found."); 
     exit(1); 
    } 

    /* Get database file from disk */ 
    while(fgets(line, sizeof(line), database) != NULL) { 
     sscanf(line, "%s %s %lu", record[rec_num].name, 
      record[rec_num].address, &record[rec_num].number); 

     /* keeps track of array size */ 
     rec_num++; 
    } 
} 

我遇到的問題是與sscanf不一致。如果我包含名字和姓氏,我不能在它們之間放置空格,或者它將姓氏放在姓名[]中,並將姓氏放在地址[]中。

這裏是我從試圖輸入數據的樣本:

1. Name: james manes  Address: 220 test addr  Number: 5558889999 

我需要獲得「詹姆斯鬃毛」入名[]字段,220測試地址到地址[]字段和5558889999到結構的數字字段中。這可能嗎?

是否有更有效的方法來管理這種類型的輸入?

+0

請提供您嘗試解析的數據的示例。 – jomik

+4

如果您需要處理輸入中的可選空格,並且可能還在地址中,那麼除非您的輸入中的字段之間有可靠的分隔符,否則這很難處理。無論哪種方式,使用正則表達式解析器可能會更好(嘗試'man 3 regex')。 –

+0

@JimStewart我從來沒有看過正則表達式。我會研究一下。 –

回答

-2

首先,您可能需要再看看http://www.cplusplus.com/reference/cstdio/fgets/。在這裏,你將看到STR參數是指向緩衝區(你提供正確),然後NUM是你想讀最大字節的數量,你沒有不正確提供。

與傳遞到與fgets在你的代碼的字節數的問題是不正確的使用的sizeof運營商。正如您可能知道的,運算符的「返回」的大小可以是類型的大小。傳遞給sizeof的類型是一個指針類型(因爲C中的數組與指針相同)。指針的大小取決於你正在運行的系統(Intel x86上的32位,AMD64上的64位,ATmega AVR上的16位等等)。因此,讓我們假設你有一臺64位的機器,你將允許fgets'獲得'64位(即8字節)的數據,這不是你想要的。那麼正確的說法是什麼?

while(fgets(line, sizeof(*line)*128, database) != NULL) { 
    ... 

我在做什麼這裏提領該字符指針焦炭和數組的大小復接。

然後,其次,你的問題是否可能:是的。我現在也想自問一個問題。是否有必要在C語言中做這件事(例如,平臺不支持任何不同的東西,學習目的等),或者你也可以在C#,Java,Python中實現它。如果是的話,我強烈建議你這樣做。

最後但並非最不重要的是,你問我們關於你的代碼的用處。答案很簡單:不。不在目前的或固定的狀態。你遇到的問題和更復雜的問題是使用'真正'的數據庫(如MySQL)+它的API來修復的。

+0

這不是爲了好玩而完成的。這是我的大學爲C和UNIX開設的一門課。我正在學習C,我需要幫助我的這一小部分計劃。我非常感謝他們的幫助,但是我不需要大膽的臉型,聽起來好像你在跟我說話。再次,我不明白這一點。 –

+1

-1:雖然數組可以在很多地方默默轉換爲指針,但sizeof的操作數不是這些地方之一,James使用它是完全正確的。 –

1

scanf("%s"...在輸入中分析空白分隔的字符串,所以如果你想解析的字符串中有空格,它將不起作用。

雖然你可以使用正則表達式來得到你想要的東西,因爲你用固定的字符串作爲你的標記,你可以改用strstr拿出你的字符串:

while(fgets(line, sizeof(line), database) != NULL) { 
    char *Name = strstr(line, "Name:"); 
    char *Address = strstr(line, "Address:"); 
    char *Number = strstr(line, "Number:"); 
    if (Name && Address && Number) { 
     Name += strlen("Name:"); 
     *Address = '\0'; 
     Address += strlen("Address"); 
     *Number = '\0'; 
     Number += strlen("Number:"); 
     strcpy(record[rec_num].name, Name); 
     strcpy(record[rec_num].address, Address); 
     sscanf(Number, "%lu", &record[rec_num].number); 
     rec_num++; } } 

注意,這也將拉動在所有名稱和地址周圍的空白 - 如果您希望它更清潔,可以修剪前導空白和尾隨空白。

+0

我預見到這會給我的好朋友「Jonathon de l'Address:von Number:III」造成問題...... :-P –

+0

我將在明天與我的教授談論這件事並得到他的意見。 –