關於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);
}
}
}