记录58
cpp
#include<bits/stdc++.h>
using namespace std;
int f(int x){
if(x==0) return 1;
int s=0;
while(x){
s++;
x=x/10;
}
return s;
}
int main(){
string s1="",s2="",s3="";
int i,n,m,ans=0,cnt=0;
char op,c;
cin>>i;
while(i--){
ans=0,cnt=0;
cin>>s1>>s2;
if(s1[0]>='a'&&s1[0]<='c'){
cin>>s3;
n=stoi(s2);
m=stoi(s3);
c=s1[0];
}
else{
n=stoi(s1);
m=stoi(s2);
}
switch (c){
case 'a':
ans=n+m;
op='+';
break;
case 'b':
ans=n-m;
op='-';
break;
case 'c':
ans=n*m;
op='*';
break;
default:
break;
}
cnt+=f(n)+f(m)+f(ans)+2;
if(ans<0) cnt++;
printf("%d%c%d=%d\n",n,op,m,ans);
cout<<cnt<<endl;
}
return 0;
}
题目传送门
https://www.luogu.com.cn/problem/P1957
突破点
若该行为三个数据则第一个数据表示运算类型,a 表示加法运算,b 表示减法运算,c 表示乘法运算,接着的两个数据表示参加运算的运算数。
若该行为两个数据,则表示本题的运算类型与上一题的运算类型相同,而这两个数据为运算数。
思路
- 运算符号跟等号是恒定的两个 👉 计算数字的长度
- 判断是否跟上一个相同 👉 输入的字符串第一个字符
- 进行对应的运算
代码简析
cpp
#include<bits/stdc++.h>
using namespace std;
int f(int x){
if(x==0) return 1;
int s=0;
while(x){
s++;
x=x/10;
}
return s;
}
int main(){
string s1="",s2="",s3="";
int i,n,m,ans=0,cnt=0;
char op,c;
cin>>i;
while(i--){
...
}
return 0;
}
int f(int x){...} 👉 计算数字的长度
string s1="",s2="",s3=""; 👉 输入的运算符或者数字
int i(算式数量),n(第一个数字),m(第二个数字),ans=0(运算的答案),cnt=0(总长度);
char op(运算符),c(运算类型);
while(i--){} 👉 输入i行算式
cpp
#include<bits/stdc++.h>
using namespace std;
int f(int x){
if(x==0) return 1;
int s=0;
while(x){
s++;
x=x/10;
}
return s;
}
int main(){
string s1="",s2="",s3="";
int i,n,m,ans=0,cnt=0;
char op,c;
cin>>i;
while(i--){
ans=0,cnt=0;
cin>>s1>>s2;
if(s1[0]>='a'&&s1[0]<='c'){
cin>>s3;
n=stoi(s2);
m=stoi(s3);
c=s1[0];
}
else{
n=stoi(s1);
m=stoi(s2);
}
switch (c){
case 'a':
ans=n+m;
op='+';
break;
case 'b':
ans=n-m;
op='-';
break;
case 'c':
ans=n*m;
op='*';
break;
default:
break;
}
cnt+=f(n)+f(m)+f(ans)+2;
if(ans<0) cnt++;
printf("%d%c%d=%d\n",n,op,m,ans);
cout<<cnt<<endl;
}
return 0;
}
ans=0,cnt=0; 👉 对每行算式初始化
if(s1[0]>='a'&&s1[0]<='c'){} 👉 判断运算类型在三种运算中,然后保留运算数字跟运算类型
else{} 👉 跟上个式子为同一个运算符
注意 :stoi()函数是将字符串类型转换为整数类型,如果报错,解决办法放在文章的补充部分介绍
switch (c){} 👉 选择操作的情况
cnt+=f(n)+f(m)+f(ans)+2; 👉 累加计算总长度
if(ans<0) cnt++; 👉 如果结果是负数,额外计算负号长度
补充
stoi()函数如果在Dev-C++中无法使用,根本原因是编译器不支持C++11标准(或支持但未开启)。以下是详细分析和解决方案:
1. 根本原因:Dev-C++默认编译器版本过旧
stoi()是C++11 引入的标准库函数,而Dev-C++默认搭载的MinGW编译器版本(通常是4.8或更早)不完全支持C++11 ,或默认未开启C++11支持。报错信息:
error: 'stoi' is not a member of 'std' error: 'stoi' was not declared in this scope
2. 解决方案(二选一)
方案A:开启C++11支持(推荐)
cpp// Dev-C++ 5.11及以上版本 // 菜单栏:工具 → 编译选项 → 编译器选项卡 // 在"编译器"框中添加: -std=c++11 // 或代码中添加(不推荐,治标不治本) #define _GLIBCXX_USE_C99 1 #include <string> using namespace std; int main() { string s = "123"; int x = stoi(s); // 现在可用 }方案B:改用兼容的替代函数(比赛保命)
cpp// 方式1:stringstream(C++98可用,最推荐) #include <sstream> string s = "123"; stringstream ss; ss << s; int x; ss >> x; // 方式2:atoi()(需转char*) #include <cstdlib> string s = "123"; int x = atoi(s.c_str()); // 必须c_str()转换 // 方式3:手动实现(竞赛常用) int myStoi(string s) { int ans = 0, sign = 1, i = 0; if (s[0] == '-') { sign = -1; i = 1; } for (; i < s.size(); i++) ans = ans * 10 + (s[i] - '0'); return ans * sign; }
3. 竞赛建议(CSP-J铁律)
** 绝对不要 在竞赛中使用
stoi()**原因:
编译环境未知:CSP-J评测机可能用旧版GCC(4.8),默认不开C++11
编译失败 = 0分 :
stoi()编译错误,题目直接WA替代方案成熟 :
stringstream和atoi()100%兼容推荐竞赛模板(100%安全)
cpp#include <bits/stdc++.h> using namespace std; // 万能字符串转数字模板(支持long long) inline long long strToLL(const string &s) { long long ans = 0, sign = 1, i = 0; if (s[0] == '-') { sign = -1; i = 1; } for (; i < (long long)s.size(); i++) ans = ans * 10 + (s[i] - '0'); return ans * sign; } inline int strToInt(const string &s) { return (int)strToLL(s); // 转int } // 使用 string s = "-12345"; int x = strToInt(s); // x = -12345 ll y = strToLL(s); // y = -12345LL
4. Dev-C++版本问题详解
Dev-C++版本 默认GCC版本 C++11支持 stoi()可用性 5.11 4.9.2 ✅ 支持(需手动开启) 添加 -std=c++11后可用5.10 4.8.1 ⚠️ 部分支持 可能编译失败 4.9 4.8.0 ❌ 不支持 必须替代 5.15+ 9.2.0 ✅ 支持(默认开启) 可用 建议 :升级Dev-C++到5.15 以上,或改用VS Code + MinGW-w64。
5. 一句话总结
stoi()在Dev-C++中不能用是因为编译器不支持C++11;竞赛中坚决不能用stoi(),统一用stringstream或手写转换函数,避免编译失败直接0分。