Processing math: 100%
NOIP学习小站
西安交通大学附属中学航天学校

字符串例题——P1957 口算练习题

通过本例题介绍sscanf和sprintf函数的使用方法。字符串的处理是应用程序的重要操作,也是竞赛的考点,在编程时需要灵活处理。

这是一道常规问题,但是由于每行中输入的数据个数不一致,数据的处理是一个难点。进一步分析问题可知,每行有3个数据时,第一个数据是字符;每行有2个数据时,第一个数据是整数。这里应该用按行输入字符串的方式输入每行的算式。

每行算式按照字符串输入后,该如何进一步处理呢?这里可以使用一个有意思的函数sscanf,sscanf和scanf都是格式化输入函数,不过sscanf是指定从某个字符串中“输入”数据。printf函数其实有返回值,就是输出的内容的长度:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
#include<cstdio>
#include<cstring>
char str[110],one[20];
int main()
{
int n,a,b,c,len;
char op;
scanf("%d\n",&n);
for(int i=1;i<=n;i++){
cin.getline(one,sizeof(one)); //使用cin.getline输入一行有空格的字符串
//sscanf指定从某个字符串中“输入”数据
if(one[0]>='a' && one[0]<='c'){
sscanf(one,"%c%d%d",&op,&a,&b);
}else{
sscanf(one,"%d%d",&a,&b);
}
//printf函数的返回值(输出内容的长度)保存到len变量中
switch(op){
case 'a':c=a+b;len=printf("%d+%d=%d",a,b,c);break;
case 'b':c=a-b;len=printf("%d-%d=%d",a,b,c);break;
case 'c':c=a*b;len=printf("%d*%d=%d",a,b,c);break;
}
printf("\n%d\n",len);
}
return 0;
}
#include<cstdio> #include<cstring> char str[110],one[20]; int main() { int n,a,b,c,len; char op; scanf("%d\n",&n); for(int i=1;i<=n;i++){ cin.getline(one,sizeof(one)); //使用cin.getline输入一行有空格的字符串 //sscanf指定从某个字符串中“输入”数据 if(one[0]>='a' && one[0]<='c'){ sscanf(one,"%c%d%d",&op,&a,&b); }else{ sscanf(one,"%d%d",&a,&b); } //printf函数的返回值(输出内容的长度)保存到len变量中 switch(op){ case 'a':c=a+b;len=printf("%d+%d=%d",a,b,c);break; case 'b':c=a-b;len=printf("%d-%d=%d",a,b,c);break; case 'c':c=a*b;len=printf("%d*%d=%d",a,b,c);break; } printf("\n%d\n",len); } return 0; }
#include<cstdio>
#include<cstring>
char str[110],one[20];
int main()
{
    int n,a,b,c,len;
    char op;
    scanf("%d\n",&n);
    for(int i=1;i<=n;i++){
        cin.getline(one,sizeof(one));  //使用cin.getline输入一行有空格的字符串

        //sscanf指定从某个字符串中“输入”数据
        if(one[0]>='a' && one[0]<='c'){
            sscanf(one,"%c%d%d",&op,&a,&b); 
        }else{
            sscanf(one,"%d%d",&a,&b);
        }

        //printf函数的返回值(输出内容的长度)保存到len变量中
        switch(op){
            case 'a':c=a+b;len=printf("%d+%d=%d",a,b,c);break;
            case 'b':c=a-b;len=printf("%d-%d=%d",a,b,c);break;
            case 'c':c=a*b;len=printf("%d*%d=%d",a,b,c);break;
        }
        printf("\n%d\n",len);
    }
    return 0;
}

与sscanf类似,sprintf和printf都是格式化输出函数,不过sprintf是将数据“输出”保存到字符串中。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
#include<cstdio>
#include<cstring>
char str[110],one[20];
int main()
{
int n,a,b,c;
char op;
scanf("%d\n",&n);
for(int i=1;i<=n;i++){
fgets(one,sizeof(one),stdin); //使用fgets输入一行有空格的字符串(本题不用关心输入后末尾可能存在的\n)
//sscanf指定从某个字符串中“输入”数据
if(one[0]>='a' && one[0]<='c'){
sscanf(one,"%c%d%d",&op,&a,&b);
}else{
sscanf(one,"%d%d",&a,&b);
}
//sprintf将数据格式化“输出”保存到字符串中
switch(op){
case 'a':c=a+b;sprintf(str,"%d+%d=%d",a,b,c);break;
case 'b':c=a-b;sprintf(str,"%d-%d=%d",a,b,c);break;
case 'c':c=a*b;sprintf(str,"%d*%d=%d",a,b,c);break;
}
printf("%s\n%d\n",str,strlen(str));
}
return 0;
}
#include<cstdio> #include<cstring> char str[110],one[20]; int main() { int n,a,b,c; char op; scanf("%d\n",&n); for(int i=1;i<=n;i++){ fgets(one,sizeof(one),stdin); //使用fgets输入一行有空格的字符串(本题不用关心输入后末尾可能存在的\n) //sscanf指定从某个字符串中“输入”数据 if(one[0]>='a' && one[0]<='c'){ sscanf(one,"%c%d%d",&op,&a,&b); }else{ sscanf(one,"%d%d",&a,&b); } //sprintf将数据格式化“输出”保存到字符串中 switch(op){ case 'a':c=a+b;sprintf(str,"%d+%d=%d",a,b,c);break; case 'b':c=a-b;sprintf(str,"%d-%d=%d",a,b,c);break; case 'c':c=a*b;sprintf(str,"%d*%d=%d",a,b,c);break; } printf("%s\n%d\n",str,strlen(str)); } return 0; }
#include<cstdio>
#include<cstring>
char str[110],one[20];
int main()
{
	int n,a,b,c;
	char op;
	scanf("%d\n",&n);
	for(int i=1;i<=n;i++){
		fgets(one,sizeof(one),stdin);  //使用fgets输入一行有空格的字符串(本题不用关心输入后末尾可能存在的\n)

		//sscanf指定从某个字符串中“输入”数据
		if(one[0]>='a' && one[0]<='c'){
			sscanf(one,"%c%d%d",&op,&a,&b); 
		}else{
			sscanf(one,"%d%d",&a,&b);
		}

		//sprintf将数据格式化“输出”保存到字符串中
		switch(op){
			case 'a':c=a+b;sprintf(str,"%d+%d=%d",a,b,c);break;
			case 'b':c=a-b;sprintf(str,"%d-%d=%d",a,b,c);break;
			case 'c':c=a*b;sprintf(str,"%d*%d=%d",a,b,c);break;
		}
		printf("%s\n%d\n",str,strlen(str));
	}
    return 0;
}

当然,也可以扫描字符串生成操作数ab,计算得出结果c,使用数的拆分方法计算结果c的位数,不过程序会显得繁琐:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
#include<cstdio>
#include<cstring>
char str[110],one[20];
int main()
{
int n,a,b,c,la,lb,lc,j;
char op;
scanf("%d\n",&n);
for(int i=1;i<=n;i++){
cin.getline(one,sizeof(one)); //使用cin.getline输入一行有空格的字符串
j = 0; //j记录字符串中第1个整数的开始下标
if(one[0]>='a' && one[0]<='c') op = one[0],j = 2;
//生成a并计算a的位数
a = la = 0;
while(one[j]>='0' && one[j]<='9') a = a*10+one[j]-'0',j++,la++;
j++;
//生成b并计算b的位数
b = lb = 0;
while(one[j]>='0' && one[j]<='9') b = b*10+one[j]-'0',j++,lb++;
switch(op){
case 'a':c=a+b;printf("%d+%d=%d",a,b,c);break;
case 'b':c=a-b;printf("%d-%d=%d",a,b,c);break;
case 'c':c=a*b;printf("%d*%d=%d",a,b,c);break;
}
lc = 2; //lc是c的位数+运算符+等于符号+结果是负数时的负号
if(c<0) c = -c,lc++; //结果是负数,特殊处理
if(c==0) lc++; //结果为0,特殊处理
else{
while(c) lc++,c /= 10; //计算c的位数
}
printf("\n%d\n",la+lb+lc);
}
return 0;
}
#include<cstdio> #include<cstring> char str[110],one[20]; int main() { int n,a,b,c,la,lb,lc,j; char op; scanf("%d\n",&n); for(int i=1;i<=n;i++){ cin.getline(one,sizeof(one)); //使用cin.getline输入一行有空格的字符串 j = 0; //j记录字符串中第1个整数的开始下标 if(one[0]>='a' && one[0]<='c') op = one[0],j = 2; //生成a并计算a的位数 a = la = 0; while(one[j]>='0' && one[j]<='9') a = a*10+one[j]-'0',j++,la++; j++; //生成b并计算b的位数 b = lb = 0; while(one[j]>='0' && one[j]<='9') b = b*10+one[j]-'0',j++,lb++; switch(op){ case 'a':c=a+b;printf("%d+%d=%d",a,b,c);break; case 'b':c=a-b;printf("%d-%d=%d",a,b,c);break; case 'c':c=a*b;printf("%d*%d=%d",a,b,c);break; } lc = 2; //lc是c的位数+运算符+等于符号+结果是负数时的负号 if(c<0) c = -c,lc++; //结果是负数,特殊处理 if(c==0) lc++; //结果为0,特殊处理 else{ while(c) lc++,c /= 10; //计算c的位数 } printf("\n%d\n",la+lb+lc); } return 0; }
#include<cstdio>
#include<cstring>
char str[110],one[20];
int main()
{
	int n,a,b,c,la,lb,lc,j;
	char op;
	scanf("%d\n",&n);
	for(int i=1;i<=n;i++){
		cin.getline(one,sizeof(one));  //使用cin.getline输入一行有空格的字符串

		j = 0;	//j记录字符串中第1个整数的开始下标 
		if(one[0]>='a' && one[0]<='c') op = one[0],j = 2;
		
		//生成a并计算a的位数
		a = la = 0; 
		while(one[j]>='0' && one[j]<='9') a = a*10+one[j]-'0',j++,la++;
		j++;
		
		//生成b并计算b的位数
		b = lb = 0;
		while(one[j]>='0' && one[j]<='9') b = b*10+one[j]-'0',j++,lb++;
		
		switch(op){
			case 'a':c=a+b;printf("%d+%d=%d",a,b,c);break;
			case 'b':c=a-b;printf("%d-%d=%d",a,b,c);break;
			case 'c':c=a*b;printf("%d*%d=%d",a,b,c);break;
		}
		
		lc = 2;	//lc是c的位数+运算符+等于符号+结果是负数时的负号 
		if(c<0) c = -c,lc++;	//结果是负数,特殊处理 
		
		if(c==0) lc++;	//结果为0,特殊处理 
		else{
			while(c) lc++,c /= 10;	//计算c的位数 
		}
		
		printf("\n%d\n",la+lb+lc);
	}
    return 0;
}

如果使用string来处理本问题的字符串,可以使用字符串流stringstream来将数据输出到字符串流或者从字符串流中输入数据到变量中:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
#include<iostream>
#include<sstream>
using namespace std;
int main()
{
int n,a,b,c;
cin>>n;
char op;
//前面输入了整数,后面循环体中要用getline按行输入string,这里用下面的语句来做特殊处理
//否则第一次循环的getline获取到的是一个换行符
string tmp = "\n";
getline(cin,tmp);
for(int i=1;i<=n;i++){
string s,ans;
getline(cin,s);
//字符串流ss1中的内容初始化成字符串s
stringstream ss1(s);
if(s[0]>='a' && s[0]<='c'){
//从字符串流ss1中输入字符op和两个整数a和b
ss1>>op>>a>>b;
}else{
//从字符串流ss1中输入两个整数a和b
ss1>>a>>b;
}
//将算式输出到字符串流ss2中
stringstream ss2;
ss2<<a;
switch(op){
case 'a':ss2<<"+";c = a+b; break;
case 'b':ss2<<"-";c = a-b; break;
case 'c':ss2<<"*";c = a*b; break;
}
ss2<<b<<"="<<c;
//从字符串流ss2中输入一个string变量ans
ss2>>ans;
cout<<ans<<endl<<ans.length()<<endl;
}
return 0;
}
#include<iostream> #include<sstream> using namespace std; int main() { int n,a,b,c; cin>>n; char op; //前面输入了整数,后面循环体中要用getline按行输入string,这里用下面的语句来做特殊处理 //否则第一次循环的getline获取到的是一个换行符 string tmp = "\n"; getline(cin,tmp); for(int i=1;i<=n;i++){ string s,ans; getline(cin,s); //字符串流ss1中的内容初始化成字符串s stringstream ss1(s); if(s[0]>='a' && s[0]<='c'){ //从字符串流ss1中输入字符op和两个整数a和b ss1>>op>>a>>b; }else{ //从字符串流ss1中输入两个整数a和b ss1>>a>>b; } //将算式输出到字符串流ss2中 stringstream ss2; ss2<<a; switch(op){ case 'a':ss2<<"+";c = a+b; break; case 'b':ss2<<"-";c = a-b; break; case 'c':ss2<<"*";c = a*b; break; } ss2<<b<<"="<<c; //从字符串流ss2中输入一个string变量ans ss2>>ans; cout<<ans<<endl<<ans.length()<<endl; } return 0; }
#include<iostream>
#include<sstream>
using namespace std;
int main()
{
	int n,a,b,c;
	cin>>n;
	char op;
	
	//前面输入了整数,后面循环体中要用getline按行输入string,这里用下面的语句来做特殊处理
	//否则第一次循环的getline获取到的是一个换行符
	string tmp = "\n";
	getline(cin,tmp);

	for(int i=1;i<=n;i++){
		string s,ans;
		getline(cin,s);
		
		//字符串流ss1中的内容初始化成字符串s 
		stringstream ss1(s);
		if(s[0]>='a' && s[0]<='c'){
			//从字符串流ss1中输入字符op和两个整数a和b 
			ss1>>op>>a>>b;
		}else{
			//从字符串流ss1中输入两个整数a和b 
			ss1>>a>>b;
		}
		
		//将算式输出到字符串流ss2中
		stringstream ss2; 
		ss2<<a;
		switch(op){
			case 'a':ss2<<"+";c = a+b; break;
			case 'b':ss2<<"-";c = a-b; break;
			case 'c':ss2<<"*";c = a*b; break;
		}
		ss2<<b<<"="<<c;
		//从字符串流ss2中输入一个string变量ans  
		ss2>>ans;
		cout<<ans<<endl<<ans.length()<<endl;
	}
	return 0;
} 

登录

注册