在做PTA上的题目时,常常会要求读取字符串,但是会遇到gets无法使用或者用scanf("%s")却没法读取空格,以下有四种办法解决输入字符串时遇到的问题。
一、gets(适用于c)
其实gets函数是包含在stdio.h这个函数库里,但无法使用或者读取空白有以下原因:
1、编译器原因,在c++编译器里会报错。
2、先读常数后读字符串读到空白,PTA测试点里每一行结尾都换行符:\n(最后一行不一定有),当gets读到时会结束读取,所以会什么都没读到就结束了读取。
解决办法:
1、换编译器,用c的编译环境。
2、用getchar读掉\n或者在用scanf读取常数时加一个空格,挤掉\n的位置。
例如要读取以下数据(PTA中:L1-039 古风排版)
4
This is a test case
int n;
char a[1000]
//错误输入,只读到一部分字符,第一个空格以后读不到
scanf("%d",&n);
scanf("%s",&n);
//错误输入,常数后面带有'\n',gets读到'\n'后就结束了,导致gets什么都没读到
scanf("%d",&n);
gets(a);
//正确输入,把'\n'读掉后gets正常读取
scanf("%d",&n);
getchar();
gets(a);
//正确输入,用空格把'\n'的位置占掉,gets正常读取
scanf("%d ",&n);
gets(a);
二、getline(适用于c++)
gets在c++的编译环境里无法使用,但是可以用getline代替gets,要注意的是,getline也是读到‘\n’就停止,所以还是要读掉缓冲区的'\n'。
int n;
string a;
//错误读取,gets无法在c++中使用
cin>>n;
gets(a);
//错误读取,'\n'导致getline读空
cin>>n;
getline(cin,a);
//正确读取,用cin.ignore()读掉回车
cin>>n;
cin.ignore();
getline(cin,a);
//正确读取,用空格占掉回车
scanf("%d ",&n);
getline(cin,a);
三、scanf的特殊用法(c和c++通用)
在scanf里有一种特殊的读取方式是区间读取,格式:scanf("%[ ]",n);。
%[ ]表示输入内容的范围,也就是区间,例如%[0-9]就是只输入'0'到'9'之间的字符,%[a-z]就是'a'到'z',如此类推还有%[A-Z]等等
那要读取除除了'\n'之外的字符要怎么做?在数学有关区间的知识中'^'表示非,所以我们可以在[ ]里加'^\n'表示除了回车以外的集合,这样就可以读取了,要注意的是如果读到了回车scanf会退出读取或读取到奇特的字符,所以依然要想办法把常数后带的回车去掉
int n;
char a[1000]
//错误输入,读到奇怪字符或空
scanf("%d",&n);
scanf("%[^\n]",&n);
//错误输入,读到奇怪字符或空
cin>>n;
scanf("%[^\n]",&n);
//正确读取
scanf("%d ",&n);
scanf("%[^\n]",&n);
//正确读取
scanf("%d",&n);
getchar();
scanf("%[^\n]",&n);
//正确读取
cin>>n;
cin.ignore();
scanf("%[^\n]",&n);
除此之外,scanf还有一个特殊字符'*',%*[\n]表示从第一个字符开始匹配,匹配条件:是字符‘\n’。如果满足条件,则忽略掉该字符,继续匹配,不满足条件,则停止匹配。
int n;
char a[1000]
//正确读取,从回车开始匹配
scanf("%d",&n);
scanf("%*[\n]%[^\n]",&n);
利用scanf的特殊输入,我们可以做到读取快速和准确。
四、while或者for循环判断
一种少见的用法,利用循环一个个读取字符,判断读取的是否是想要的字符。
char a[1000],c;
int flag=0,i=0;
//读取结果与上面三种方法正确读取一样,但是效率低,常用于统计字符种类或操作字符串
while(1)
{
c=getchar();
if(c=='\n')
{
flag++;
if(flag>=2)break;
}
else
{
a[i]=c;
i++;
}
}
for(i=0;flag<2;i++)
{
c=getchar();
if(c=='\n')flag++;
else a[i]=c;
}