關於C++ scanf的一個小知識

計算機知識雜談發表於2022-02-09

關於C++的scanf,其實在使用時有一個注意的點。
我們來看一個簡單的例子。

對於輸入的一行,如果這一行的開頭需要輸入一個字元,例如這樣的輸入:

A 10 20
B 30
A 3 50
...

我們可以使用這種方式來讀入,使用一段程式碼來進行試驗:

#include<stdio.h>
using namespace std;
int main(){
	int n;
	scanf("%d",&n);
	while(n--){
		char c;
		scanf("%c",&c);
		if(c=='A'){
			int a,b;
			scanf("%d%d",&a,&b);
			printf("%d\n",a+b);
		}
		else if(c=='B'){
			int a;
			scanf("%d",&a);
			printf("%d\n",a);
		}
	}
}

應該能看懂,輸入A 20 30就是輸出20+30的和,輸入B 5就是直接輸出5,最前面輸入的n是次數。
好,執行試驗一下:

有人會問,輸入的n是5,但是為什麼兩次就停止了?我們來做個試驗:

int main(){
	int n;
	scanf("%d",&n);
	while(n--){
		char c;
		scanf("%c",&c);
		printf("%d\n",c); //這裡! 
		if(c=='A'){
			//略
		}
		else if(c=='B'){
			//略
		}
	}
}

我們同樣執行一次,結果是:

紅框圈出的位置就是輸出。我們可以看到,裡面除了正常的'A','B'的ASCII碼65,66以外,還有10的出現。
10代表換行符,那麼,我們可以知道:

scanf的輸入讀取,其實是按照連續的字元流為單位進行解讀的。讀入完一個數後,後面的空格或者換行符還是殘留在流中。
例如我輸入:"123\n",使用scanf的%d讀入,實際上只把123從流中讀入了進來,'\n'還殘留在流中。
因此,下一次讀入%c的時候,就會把\n讀進來。

解決方法:
方法一
使用字串的形式讀入,這種情況下,%s不會把殘留的\n讀入進來。
程式碼:

#include<stdio.h>
using namespace std;
int main(){
	int n;
	scanf("%d",&n);
	while(n--){
		char s[10];
		scanf("%s",s);//這裡!
		if(s[0]=='A'){
			int a,b;
			scanf("%d%d",&a,&b);
			printf("%d\n",a+b);
		}
		else if(s[0]=='B'){
			int a;
			scanf("%d",&a);
			printf("%d\n",a);
		}
	}
}

方法二
既然多了一個換行符,那麼把這個換行符使用某些方法讀掉就可以了,可以使用getchar來,也可以通過scanf的格式說明符來。
程式碼:

#include<stdio.h>
using namespace std;
int main(){
	int n;
	scanf("%d",&n);getchar();//這裡!
	while(n--){
		char c;
		scanf("%c",&c);
		if(c=='A'){
			int a,b;
			scanf("%d%d",&a,&b);getchar();
			printf("%d\n",a+b);
		}
		else if(c=='B'){
			int a;
			scanf("%d",&a);getchar();
			printf("%d\n",a);
		}
	}
}

方法三
先使用字串的形式讀入,再使用sscanf解析字串。這樣由於每次讀入的字串會被替換,因此殘留的換行符不會造成影響。

#include<stdio.h>
using namespace std;
char s[1000];
int main(){
	int n;
	fgets(s,1000,stdin);//這裡!
	sscanf(s,"%d",&n);
	while(n--){
		char c;
		scanf("%c",&c);
		if(c=='A'){
			int a,b;
			fgets(s,1000,stdin);
			sscanf(s,"%d%d\n",&a,&b);
			printf("%d\n",a+b);
		}
		else if(c=='B'){
			int a;
			fgets(s,1000,stdin);
			sscanf(s,"%d\n",&a);
			printf("%d\n",a);
		}
	}
}

相關文章