2010-02-03 63 views
6

我需要閱讀等的輸入的文件:讀取從stdin(C)不明數目的整數的

1 
19 20 41 23 
2 
41 52 43 
3 
90 91 941 
4 
512 
5 

6 
51 61 

每個奇數行是一個整數。每個偶數行都是未知的整數。

,它在C++

while(cin >> k){ 
............ 
} 

我不這麼習慣於使用C很容易的,所以我不能讓它在C.做任何方式?

+1

你有講究線條,或者這只是一系列未來的整數?在你的例子中,它看起來像奇數行是序列號,偶數行代表了別的東西。 – 2010-02-03 22:09:09

+0

david我需要注意線條。這就是爲什麼我不能這樣做。 我需要停止在每條偶數行的末尾獲取新值。 因爲我有一個屬性id和列表的結構。每個奇數行是一個id,每一個偶數行都是一個列表。 我想用2行數據填充一個結構,並移動到另一個結構,並用另外2行數據填充它... – huhuhuuu 2010-02-03 22:14:35

+0

一次讀入整行,然後將其解析爲字符串 – 2010-02-03 22:39:37

回答

9

我會做到這一點是把它分解成兩種操作方式:讀取一行,然後讀取該行中的整數。這裏是一個懶惰的實現使用標準C庫:

char line[1024], *p, *e; 
long v; 
while (fgets(line, sizeof(line), stdin)) { 
    p = line; 
    for (p = line; ; p = e) { 
     v = strtol(p, &e, 10); 
     if (p == e) 
      break; 
     // process v here 
    } 
} 
+2

非常感謝。我現在就試一試。 但是,如果我不能假定一個固定的最大線路長度? – huhuhuuu 2010-02-03 23:24:48

+2

如果輸入流包含超過1024 - 2個字符並且'fgets()'用數字字面量分割輸入流會怎麼樣?你將得到兩個數值而不是一個。例如,從12345開始,在下一次fgets()調用之後,for循環的最後一次迭代中可以得到123,for循環的第一次迭代中可以得到45。因此,我寧願用'scanf()'和'fscanf()'來完成這個任務,如Sean所示。 – 2014-11-20 15:55:27

+1

@RobinKlose:由Sean發佈的'scanf()'解決方案並不能解決問題,因爲它不會將換行符與其他空格區分開來。 – 2014-11-20 18:19:43

11

運行輸入文件通過:

#include <stdio.h> 

int main() { 
     int k; 
     while (scanf("%d", &k) == 1) { 
       printf("read number: %d\n", k); 
     } 
     return 0; 
} 

結果:

 
read number: 1 
read number: 19 
read number: 20 
read number: 41 
read number: 23 
read number: 2 
read number: 41 
read number: 52 
read number: 43 
read number: 3 
read number: 90 
read number: 91 
read number: 941 
read number: 4 
read number: 512 
read number: 5 
read number: 6 
read number: 51 
read number: 61 

這是你在你原來的問題引用代碼的C模擬。

+0

我可以正確地讀取行,但scanf循環無限打印我的第一個數字。 – tarabyte 2014-06-01 04:03:35

0

看看GETC(3)或scanf(3)

1

我會做的一個:

  • 龜etc()讀取單個字符和自己分析它們(累積的數字,直到你打空格和你有一個要用atoi()轉換的整數;如果空格是換行符,那麼它終止整數列表)

  • fgets()一次讀取一行,然後解析字符串(再次,查找分隔值的空格)。

3

我會在不同的任務中破壞程序。

第一步是能夠讀取一對線,第一行告訴您要讀取的數字的數量,然後第二行讀取實際的數字。爲此,一個叫做read_set的函數可能會有用。它應該能夠返回讀取的數字,以及信號文件的結尾以及錯誤。對於這一點,我們可以定義一個數據結構,如:

struct numbers { 
    long *data; /* or choose a type depending upon your needs */ 
    size_t len; 
}; 

,然後我們可以與原型聲明我們的函數:

int read_set(FILE *fp, struct numbers *num); 

該函數將分配內存num->data,並設置num->len到正確的價值。它成功返回0,否則返回一組錯誤條件。我們可能會喜歡,稍後使用enum作爲返回狀態。現在,讓我們說0 =成功,1 =文件結束,其他一切都是錯誤。

主叫然後在循環中調用read_set()

struct numbers numbers; 
int status; 
while ((status = read_set(fp, &numbers)) == 0) { 
    /* process numbers->data, and then free it */ 
} 
if (status == 1) { 
    /* hit end of file, everything is OK */ 
} else { 
    /* handle error */ 
} 

爲了實現read_set():它具有讀取兩行。有很多implementations of reading a full line in C,所以你可以使用它們中的任何一個,先讀一行,然後sscanf()/strtoul()它爲一個數字(檢查它的返回值!)。一旦你有一個數字,n的數量,你可以讀取內存中的下一行,這樣做:

num->data = malloc(n * sizeof *num->data); 
num->len = n; 

然後,您可以反覆調用sscanf()strtol()存儲在num->data數字。你應該進行檢查以確保n號碼在該行上。

請注意,您也可以用其他方式編寫read_set():按字符讀取一行字符,並在讀取它們時解析數字。這樣做的好處是隻需掃描一次數據,而不需要一個大的緩衝區來將整個輸入行存儲在內存中,但缺點是自己做低級別的東西,逐字讀取數據可能會很慢。

0

我想出了這樣一個解決方案:

while(scanf("%d%c", &n, &ch)!=EOF) 
{ 
    if(ch=='\n') break; 
    /* rest of your code */ 
} 
+0

/*其餘代碼* /應在循環之後。 – 2017-08-04 06:31:05