1. 程式人生 > >瞭解C中scanf單整數讀取,C++中cin.peek()用法

瞭解C中scanf單整數讀取,C++中cin.peek()用法

這兩天被人問到一個小題,題目是是這樣的:

輸入1個8位以上的數,將個位上的偶數取出,並按照原來從高位到低位相反的順序組成一個新數,並輸出這個新數:

輸入:27638496
輸出:64862

水題當然是水題,用char型別陣列很快就能寫出來,但是想用讀取整數的方式能不能寫出來呢?

我想到了之前用到的一個逐個讀取整數型的scanf("%1d", &num)方法;

// 失敗
#include<stdio.h>
#include<stdlib.h>
int main()
{
	int num[100];
    int need[100];
    int j = 0;
    char ch;
    for (int i = 0; scanf("%1d", &num[i]); i++)
    {
    	if (num[i] % 2 == 0)
    		need[j++] = num[i];
    }
    for (int k = j-1; k>=0; k--)
    {
    	printf("%d", need[k]);
    }
    system("pause");
}

但其實這裡是有問題的,scanf()函式每次以"1d"方式讀取不管是字元還是陣列時,讀取到的都將是0到9內的數(’\n’的ASCII值為10, 空格space的為32),就算遇到’\n’這樣原本是結束字元的也不能終止讀入,本方法解決失敗

不放棄的我又想到了用getchar()函式探測下一個字元是不是’\n’來判斷終止條件,但是這種情況只適用於每兩個字元間有一個空格(或其他什麼無關緊要的字元),結尾無空格的情況。
例1 2#3%4(結尾無空格及其它字元)
此時,沒到結尾時getchar()用於吸收空格,結尾時getchar()判斷’\n’。

// 只適用於每兩個字元間有一個無關字元,結尾無無關字元的情況
#include<stdio.h>
#include<stdlib.h>
int main()
{
	int num[100];
	int need[100];
	int j = 0;
	char ch;
	for (int i = 0; scanf("%1d", &num[i]) && (ch = getchar()!= '\n'); i++)
	{
		if (num[i] % 2 == 0)
			need[j++] = num[i];
	}
	for (int k = j-1; k>=0; k--)
	{
		printf("%d", need[k]);
	}
	system("pause");
}

再增加一種條件,如果我們知道了數字串的長度len,scanf("%1d", &num)方式確實也可以用:

// 適用於已知數字串長度len的情況
// 若len = 6
int j = 0;   // 這裡初始化為0是因為如果每一位都是奇數,後面print時會報錯
for (int i = 0; i<len; i++)    // 輸入:259840
{
	scanf("%1d", &num[i]);
	if (num[i]%2 == 0)
		need[j++] = num[i];
}
for (int i = j-1; i>=0; i--)
	printf("%d", need[i]);     // 輸出:0482

這時,如何完美解決問題呢,就用我們C++的cin.peek()函數了,顧名思義,就像一個窺探函式。(終於成功了!)

其功能是從輸入流中讀取一個字元 但該字元並未從輸入流中刪除。其返回值是一個char型的字元,其返回值是指標指向的當前字元,但它只是觀測指標,停留在當前位置並不後移;如果要訪問的字元是檔案結束符,則函式值是EOF(-1) ;更直白一點的說法,就像是偷看了一下當前指標指向的字元(或者說不管是數字還是字元,都當做字元看了一眼,沒做什麼實際行動,不影響後面其他函式讀取它的方式)。

若把輸入流比作一個 棧類 那麼這裡的peek函式就相當於棧的成員函式front(或者說像取top),而cin.get()則相當於棧的成員函式pop(直接刪除掉top元素)

// 成功!
#include<iostream>
using namespace std;
int main()
{
	int num[100];    // 能讀取100位數字的陣列
	int need[100];   // 儲存掉數字是偶數的位
	int j = 0;
	scanf("%1d", &num[0]);
	for (int i = 1; cin.peek()!='\n'; i++)  // 看一眼當前下標(指標)i 指向的"字元"是不是'\n',是就終止
	{
		scanf("%1d", &num[i]);
		if (num[i]%2 == 0)
			need[j++] = num[i];   // 提取偶數位數字
	}
	for (int k = j-1; k>=0; k--)
	{
		printf("%d", need[k]);
	}
	
	system("pause");
}

那麼在C語言沒有這樣一個庫函式可以實現C++的cin.peek()函式,不過可以自定義函式實現類似的功能。
有興趣請參考 https://blog.csdn.net/cFarmerReally/article/details/78474979