通过本例题介绍sscanf和sprintf函数的使用方法。字符串的处理是应用程序的重要操作,也是竞赛的考点,在编程时需要灵活处理。
这是一道常规问题,但是由于每行中输入的数据个数不一致,数据的处理是一个难点。进一步分析问题可知,每行有3个数据时,第一个数据是字符;每行有2个数据时,第一个数据是整数。这里应该用按行输入字符串的方式输入每行的算式。
每行算式按照字符串输入后,该如何进一步处理呢?这里可以使用一个有意思的函数sscanf,sscanf和scanf都是格式化输入函数,不过sscanf是指定从某个字符串中“输入”数据。printf函数其实有返回值,就是输出的内容的长度:
#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是将数据“输出”保存到字符串中。
#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; }
当然,也可以扫描字符串生成操作数\(a\)和\(b\),计算得出结果\(c\),使用数的拆分方法计算结果\(c\)的位数,不过程序会显得繁琐:
#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来将数据输出到字符串流或者从字符串流中输入数据到变量中:
#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; }