2014-02-27 56 views
2

我有格式的CSV文件:C程序來解析文件

name,num-one,num-two,num-three 

我有我使用(如下圖)解析腳本,但我想編輯的腳本來檢查整個文件繼續前進。腳本的

僞代碼:

Read through the whole file/ 
Find a line where token 1 matches a set value AND 
Token two matches another set value THEN 
Set the value two tokens as new variables 
Otherwise move onto the next line. 

如果令牌酮(name)和令牌兩(num-one)等於當前正由我的程序處理中的值,然後設置令牌三個和四個爲value1value2

char line[32]; 
int  count; 
FILE *read_file; 

read_file = fopen ("/location/of/file.csv", "r"); 

fgets (line,32,read_file); 

pch = strtok (line,","); 

while (pch != NULL ) 
{ 
    if (count == 1) 
    { 
     if ((strcmp(pch,name) == 0)) 
     { 
      count++; 
     } 
    } 
    else if (count == 2) 
    { 
     if ((strcmp(pch,num-one) == 0)) 
     { 
      count++; 
     } 
    } 
    else if (count == 3) 
    { 
     value1 = atoi(pch); 
     count++; 
    } 
    else if (count == 4) 
    { 
     value2 = atoi(pch); 
     count = 1; 
    } 
    pch = strtok (NULL, ","); 
} 

回答

6

你真的不應該使用strtok()這樣的東西。

相反,做簡單得多:

  1. 閱讀使用fgets()線。你已經這樣做了。
  2. 使用sscanf()解析該行。

隨着sscanf(),解析出的四個字段是一個函數調用:

char name[16]; 
int num1, num2, num3; 

if(sscanf(line, "%15s,%d,%d,%d", name, &num1, &num2, &num3) == 4) 
{ 
    printf("got '%s' with values %d, %d and %d\n", name, num1, num2, num3); 
} 

我不是100%肯定你所期望的領域是正確的,我發現你的描述(和代碼)很難理解。我假定一個字符串後面跟着四個整數。

請注意,上述將字符串部分視爲簡單字符串;它不能嵌入空白。若要改爲依靠逗號分隔字段,可使用:

if(sscanf(line, "%15[^,],%d,%d,%d", name, &num1, &num2, &num3) == 4) 
        ^
        | 
       changed this 

這將把第一部分作爲非逗號字符的字符串,允許嵌入的空格。

+0

我認爲你的意思是'\ n'並且錯誤地轉義了錯誤 – ajay

+0

這段代碼中的'== 4'做了什麼? –

+0

@DustinCook sscanf()調用返回成功轉換的次數;'if'將該值與'4'進行比較,看看是否所有四次轉換都是成​​功的,在依賴具有明確定義的值的變量之前,這是必須的 – unwind

1

爲什麼不考慮在awk中編寫檢查器(如果我瞭解您的文章的目的)? awk將遍歷你的.csv文件,如果你使用gawk -vFS =','將以逗號分隔的字段,你可以很容易地在你的字段之間添加任何類型的測試或重新排列它們。那麼無論你的目標是什麼,你都可以假設一旦awk程序運行完成了所有的前提條件。

#!/usr/bin/gawk -f 
BEGIN { OFS=FS=',';} 

{ 
    print $1+$3, $2, $3, $4; 
} 

該代碼將複製輸入文件,同時用第一個和第三個數之和替換第一個數。 awk程序的寫入速度比C快很多,維護和修改起來會更容易一些,我敢打賭它的運行速度會快於未磨光的C版本。

+1

您的'awk'腳本需要一個條件。另外,從OP的問題是否想要將匹配線打印到終端還不清楚。他說,「值應該設置」,這對我來說看起來好像他需要這些值在C中進行進一步處理。 –

+0

OP的代碼沒有條件......他只是檢查輸入有多少個字段。順便說一句,上面的代碼不應該解決OP的問題,只是爲了演示這個東西用適當的工具是多麼的容易......因爲所有的OP代碼都是由awk免費爲你完成的。 – user1666959

1

您的問題已經得到解答。儘管如此,我想展示如何使用strtok來達到您的目的。您的count方法不起作用。相反,如果條件不滿足,您可以一次分析一個字段,並循環使用continue循環。 (你似乎在你的例子中缺少外部循環,我不知道你是否在「檢查整個文件」的意思。該循環逐行讀取文件; continue手段讀取下一行和break意味着停止閱讀。)

for (;;) { 
    char line[32]; 
    char *pch; 
    int x; 

    if (fgets(line, 32, read_file) == NULL) break; 

    pch = strtok(line, ","); 
    if ((strcmp(pch, name) != 0)) continue; 

    pch = strtok(NULL, ","); 
    if (sscanf(pch, "%d", &x) < 1 || x != num) continue; 

    pch = strtok(NULL, ","); 
    if (sscanf(pch, "%d", &value1) < 1) continue; 

    pch = strtok(NULL, ","); 
    if (sscanf(pch, "%d", &value2) < 1) continue; 
} 

但我不得不承認,sscanf的做法是爲您的目的簡單,大概就夠了。如果輸入更復雜,例如,如果字段的含義和數據類型取決於第一個字段,則strtok方法可能更靈活。