[C語言] 讀入一行再剖析字串

在寫UVa或其他線上題目時,很容易遇到要從stdin剖析

10 20 3 5 6 -3 4
3 22 13 3 42

-1

這類的題目一次要處理以一行為單位,裡面有數字轉存int陣列又不同長度,每一行代表每一圈loop的執行,最後結尾來個-1代表測資輸入完畢的題目

如果直接用迴圈每個每個數字讀又有換行的問題要考慮

有做過這種題目的人應該對這種題目印象深刻吧

常常光在寫輸入的部分就花費了不少行數

以下是我在parse這類輸入的方法,分享給大家參考。

char inputLine[100];
int result[20];
int resultLength = 0;

if(fgets(inputLine, sizeof(inputLine), stdin) != NULL)
{
	char *lineTheRest = inputLine;
	int offset;
	while(sscanf(lineTheRest, " %d%n", &result[resultLength], &offset) == 1)
	{
		resultLength++;
		lineTheRest +=offset;
	}
}

 

代碼說明

首先宣告個char陣列,做stdin輸入暫存用

一個result整數陣列儲存最終parse完的數字結果

以及resultLength來記錄parse出幾個數字來

char inputLine[100];
int result[20];
int resultLength = 0;

 

前置作業都部署好了我們就先用fgets抓取一行

(用gets也可以,但因為有buffer overflow的風險,所以已經被deprecated在往後版本的gcc)

if(fgets(inputLine, sizeof(inputLine), stdin) != NULL)
{
    ...
}

從stdin讀入,放進inputLine這個字元陣列內,陣列最大長度不超過inputLine的大小

如果以上步驟都順利無誤讀取完,則回傳s,反之NULL

…的地方等等要寫如何從該行parse出個別數字

 

宣告一個char的指標來指向還未被parse到的字串起始處

由於目前還沒開始parse,所以也會等於inputLine的起始位址

offset拿來存每次讀取的長度,讓restOfTheLine往後移用

char *lineTheRest = inputLine;
int offset;

 

接著我們就要開始從inputLine開始迴圈parse每個數字進result陣列了

while(sscanf(lineTheRest, " %d%n", &result[resultLength], &offset) == 1)
{
	resultLength++;
	lineTheRest +=offset;
}

用sscanf從lineTheRest讀取(%d)一個數字,以及(%n)該數字所佔用的記憶體大小

並將數字存入result[resultLength]裡,resultLength也剛好是index,直接借來用

offset放讀入的前一個字元(%d)的記憶體大小,多少個byte

由於%d是整數,所以一般系統下是4bytes

若該行指令無誤則回傳1,並跳進迴圈內執行

resultLength加一

lineTheRest往後偏移offset個byte

 

當lineTheRest被整個parse完後就不再讓sscanf順利讀取

也就不會再進入迴圈

於是我們整個inputLine裡的數字就被成功依序放進result數字陣列裡了。


發佈留言