2015-04-05 97 views
0

我試圖掃描以下格式在C一個文本文件:功能的fscanf在.txt文件中忽略空格分隔符

key01 value01 
key02 value02 
key03 value03 

我想利用關鍵字和值字符串,並將其分配給一個struct我創建:

struct Mapping 
{ 
    char key[sizeof(char) * 5]; 
    char value[sizeof(char) * 7]; 
} MapElement; 

我的代碼要做到這一點是:

void initialize_server_map(struct Mapping serverMap[]) 
{ 
    char* fileName = "server1.txt"; 
    FILE *fp = fopen(fileName, "r"); 
    char *lineKey = (char*)malloc(sizeof(char) * 5); 
    char *lineValue = (char*)malloc(sizeof(char) * 7); 
    int i = 0; 
    while (fscanf(fp, "%s %s", lineKey, lineValue) != EOF) { 
    struct Mapping mapping; 
    memcpy(mapping.key, lineKey, sizeof(char) * 5); 
    memcpy(mapping.value, lineValue, sizeof(char) * 7); 
    printf("key: %s value: %s\n", mapping.key, mapping.value); 
    serverMap[i] = mapping; 
    i++; 
    } 
    fclose(fp); 
} 

int main(void) 
{ 
    int size = 4; 
    struct Mapping serverMap[size]; 
    initialize_server_map(serverMap); 
} 

我的輸出如下:

key: key01value01 value: value01 
key: key02value02 value: value02 
key: key03value03 value: value03 
key: key04value04 value: value04 

當然,我想這個輸出,而不是:

key: key01 value: value01 
key: key02 value: value02 
key: key03 value: value03 
key: key04 value: value04 

我敢肯定它做我分配我的記憶方式的東西。有人可以幫我解決這個問題嗎?另外,有沒有更有效的方法來做到這一點?

+0

另外,我知道一個事實,即它們鍵和值將始終是長度段5和7 – 2015-04-05 05:01:00

+0

在C語言中,字符串終止NUL字節,佔用一個字節。您應該(幾乎)從不使用'memcpy'來複制字符串;使用'strcpy'這將糾正NUL終止副本。請記住爲陣列和malloc中的NUL字節留出空間。而'char [sizeof(char)* 5]'顯然是錯誤的。聲明中的數字是單位的數量,而不是字節的數量(所以'int v [5]'有足夠的空間存放5個整數,不管整數可能有多大)。幸運的是,sizeof(char)總是一個。 – rici 2015-04-05 05:03:28

+0

如果您打算將它們視爲字符串,則忘記爲必需的'null-terminating'字符添加'+ 1'。 – 2015-04-05 05:03:39

回答

1

由於無法訪問數組,導致未定義的行爲。

爲了存儲"key01",您需要一個至少爲6 - 5的字符數組和一個用於終止空字符的數組。

同樣,您需要一個大小至少爲8的數組來存儲"value01"

您正在聲明大小分別爲57。因此,你在修改數組越界時,在使用

while (fscanf(fp, "%s %s", lineKey, lineValue) != EOF) { 
1

那麼,至少你已經忘記了字符串尾隨'\ 0'的空間。所以如果你有5個字符的字符串,你應該分配6個字符。

但通常整個方法都很脆弱。如果輸入數據中的鍵長度超過5個字符會怎麼樣?傳統的方法是使用「足夠大」的緩衝區(例如幾百字節),使用格式中的長度限制器(例如「%20s」而不是「%s」)限制可能的字符串長度,然後分配需要的空間通過strdup

所以整個大塊看起來像:

struct Mapping { 
    char* key; 
    char* value; 
}; 
... 
char lineKey[51]; 
char lineValue[51]; 
while (fscanf(fp, "%50s %50s", lineKey, lineValue) != EOF) { 
    struct Mapping* mp = (struct Mapping*)malloc(sizeof(struct Mapping)); 
    assert(mp); 
    mp->key = strdup(lineKey); 
    mp->value = strdup(lineValue); 
    ... 
}