来啃硬骨头——c++各种字符串的题

题目一——给定一个字符串,如果该字符串符合人们日常书写一个整数的形式,返回int类
型的这个数;如果不符合或者越界返回-1或者报错。

 

思路:

首先要判断字符串能不能转成数字,之后要判断会不会在转成数字的时候发生溢出。

 

记录这个题主要不是为了记录怎么转换的,而是要记录一些防溢出的技巧

技巧一:用负数来接每一步的转换结果

cur='0'-input[i];

因为负数的最小值的绝对值的比正数的最大绝对值多一位,因此用负数更安全

#define MAX_val  2147483647
#define MIN_val -2147483648

 

技巧二:计算之前先判断一下是否会溢出,如果会,则不进行转换

int minq=MIN_val/10;
int minr=MIN_val%10;

//防溢出 前半部分代表乘10会溢出 后半部分代表乘10不会溢出,但是加上cur会溢出
if((res<minq)||(res==minq&&cur<minr)){
    cerr<<"会发生溢出,转换失败"<<endl;
    return 0;
}

res=res*10+cur;

 

技巧三:如果传入的是正数,而解析的过程我们是用负数来接的每一个结果,因此最后负数转正数之前,还要判断一下是否会发生溢出

//如果数字是正数,且res记录的结果值等于系统中负数的最小值
//此时将res转成正数会发生溢出
if(positive && res== MIN_val){
	cerr<<"转为正数时会发生溢出"<<endl;
	return 0;
}

return positive?-res:res;

 

上这道题的题解代码(很多的细节处理,都在代码的注释里):

#include<iostream>
#define MAX_val  2147483647
#define MIN_val -2147483648
using namespace std;

bool isValid(string input){
	int i=0;
	while(input[i]==' ')
		i++;
	
	//开头不是数字也不是负号
	if((input[i]!='-')&&((input[i]<'0')||(input[i]>'9')))
		return false;

	//开头是负号,但是后面是0,或者只有一个负号
	if((input[i]=='-')&&((input[i+1]=='0')||(input.length()==1)))
		return false;

	//以0开头且字符串长度大于1的
	if((input[i]=='0')&&input.length()>1)
		return false;

	for(int i=1; i<input.length(); i++){
		if((input[i]<'0')||(input[i]>'9'))
			return false;
	}
	return true;
}

int calculate(string input){
	if(input.length()==0) return 0;

	if(!isValid(input)){ 
		cerr<<"该数字不是正常书写的数字"<<endl;
		return 0;
	}

	//判断是不是正数
	bool positive=input[0]=='-'?false:true;

	int minq=MIN_val/10;
	int minr=MIN_val%10;

	int res=0, cur=0;
	for(int i=positive?0:1; i<input.length(); i++){
		//获取负数(因为负数的最小值的绝对值的比正数的最大绝对值多一位,因此哟经负数存更安全)
		//这是一个技巧
		cur='0'-input[i];

		//防溢出 前半部分代表乘10会溢出 后半部分代表乘10不会溢出,但是加上cur会溢出
		if((res<minq)||(res==minq&&cur<minr)){
			cerr<<"会发生溢出,转换失败"<<endl;
			return 0;
		}

		res=res*10+cur;
	}
	
	//由于负数比正数的绝对值多一位,如果res的值刚刚好是负数的最大值
	//也就是说转正数会发生溢出,因此此处抛出异常
	if(positive && res== MIN_val){
		cerr<<"转为正数时会发生溢出"<<endl;
		return 0;
	}
	
	return positive?-res:res;
}

int main(){
	string input;

	while(getline(cin,input)){
		cout<<calculate(input)<<endl;		
	}
	return 0;
}

 

持续更新中————————————————————————————————————————————————

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值