P1957 口算练习题

记录58

#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 表示乘法运算,接着的两个数据表示参加运算的运算数。

若该行为两个数据,则表示本题的运算类型与上一题的运算类型相同,而这两个数据为运算数。


思路

  1. 运算符号跟等号是恒定的两个  👉  计算数字的长度
  2. 判断是否跟上一个相同  👉 输入的字符串第一个字符
  3. 进行对应的运算 

代码简析

#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行算式

#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支持(推荐)

// 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:改用兼容的替代函数(比赛保命)

// 方式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() **

原因:

  1. 编译环境未知:CSP-J评测机可能用旧版GCC(4.8),默认不开C++11

  2. 编译失败 = 0分stoi()编译错误,题目直接WA

  3. 替代方案成熟stringstreamatoi()100%兼容

推荐竞赛模板(100%安全)

#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.114.9.2✅ 支持(需手动开启)添加-std=c++11后可用
5.104.8.1⚠️ 部分支持可能编译失败
4.94.8.0❌ 不支持必须替代
5.15+9.2.0✅ 支持(默认开启)可用

建议:升级Dev-C++到5.15以上,或改用VS Code + MinGW-w64


5. 一句话总结

stoi()在Dev-C++中不能用是因为编译器不支持C++11;竞赛中坚决不能用stoi(),统一用stringstream或手写转换函数,避免编译失败直接0分。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值