zoukankan      html  css  js  c++  java
  • 浅谈将一个字符串转换为整数

    前一段时间刷到“把一个字符串转换为整数”这道题。据说是微软面试开发工程师最常用到的一个问题。写出了最终版本之后,竟然花费了大量的时间,这让我感到自己考虑问题还不是那么全面。所以,以此为例,一来想好好记住这个解题方法;二来是想要保持逻辑上这种解题思路。做以总结。

    很多人拿到题都会迅速的写出如下代码:

    
     int transform(char* string){
    
       int num=0;
       while(*string++){
       num=num*10+num-'0';
     
     }
       
       return number;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

           乍一看之下,可能会觉得逻辑实现没有什么问题,但是如果面试的时候你写出了这样的代码,那绝对是没有生还的希望。因为这样的代码是在是态Low了(灬ꈍ ꈍ灬)

           通常题目越是简单,面试官的期望就会越高。这道题,除了完成基本功能之外,我们还需要考虑到:
    1.边界条件
    2.错误处理
    3.最大的正整数溢出和最小的负整数溢出
    4.正负号
    5.输入中有非数字字符

    看看我们列出的这5点,你再想想自己是不是之前考虑的方面太少,代码是不是很挫?
    ok,先拿出最终改良版的代码:

    #include<iostream>
    #include<windows.h>
    using namespace std;
    
    
    //1.把一个字符串转换为整数
    
    
    	int string2int(char* string){
    	
    		if (*string==''||string == NULL)
    			return -1;
    
    		int  flag = 1;
    		int num = 0;
    			
    		char *_str = string;
    		//考虑到正负号
    
    		if (*_str == '+')               //解引用 高于 ==的优先级: 
    		{
    			flag == 1;
    			++_str;
    		}
    		else if (*_str == '-')
    		{
    			++_str;
    			flag = -1;
    		}
    		
    
    		while (*_str){
    		
    			if (*_str > '0' && *_str < '9'){
                    num = num * 10 + flag*(*_str - '0');
    				//判断数据是否溢出
    				if ((flag == 1 && num>0x7fffffff) 
    				    || (flag == -1 && num < (int)0x80000000))
    					return -2;   //溢出
     
    			}
    			else{
    				//输入的字符串中不全是数字
    				return -1;             //不合法
    			}
    		
    			++_str;
    		}
    
    		return num;
    	
    	}
    
    
    	void test1(){
    		char* str = "-1234";
    		int n = string2int(str);
    		cout << n << endl;
    
    
    
    	}
    
    
    
    int main(){
    
    	test1();
    
    	system("pause");
    	return 0;
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74

    其实最终版本的代码也并不复杂,也都可以分析明白。但是在这里,我还是有一个点要说一下。那就是在判断溢出的时候:

    if ((flag == 1 && num>0x7fffffff) 
    				    || (flag == -1 && num < (int)0x80000000))
    
    • 1
    • 2

    在分析这块的时候,我有花费了一些时间研究负数溢出的判断条件为什么是这种写法。我们知道在计算机中的数字都是采用补码表示的。比如我们要想打印-1,

            int a =0xffffffff;
    		cout << a << endl;
    //打印结果: -1
    
    • 1
    • 2
    • 3

           我们知道char类型的表示范围是-128~127。正数表示范围是0-127一共2的7次方128个数;那为什么负数可以表示-128呢?我们应该注意到-0的存在。

    -0 :原码 1000 0000 的补码为 1 0000 0000 
    由于 char 是 八位 ,所以取低八位 00000000。   
    
    +0 :原码 0000 0000 ,补码为也为 0000 0000 
    虽然补码 0 都是相同的,但是有两个 0 ,既然有两个 0 ,况且 0 既不是正数,也不是
    负数, 用原码为 0000 0000 表示就行了。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

           这样一来,有符号的 char,原码都用来表示 -127~127 之间的数了,唯独剩下原码 1000 0000 没有用,用排列组合也可以算出来,能表示 2^7 = 128 个数,刚好是 0~127。也能表示 128 个数,总共 signed char 有 256 个数,这与 -127~127 中间是两个 0 刚好吻合。

           现在再来探讨一下关于剩下的那个 1000 0000,既然 -127 ~ 0 ~ 127 都有相应的原码与其对应,那么 1000 0000 表示什么呢,当然是 -128 了,为什么是 -128 呢,网上有人说 -0 即 1000 0000 与 128 的补码相同,所以用 1000 0000 表示 -128,,这我实在是不敢苟同,或者说 -128 没有原码,只有补码 1000 0000,胡扯,既然没有原码何来补码,还有说 -128 的原码与 -0(1000 0000) 的原码相同,所以可以用 1000 0000 表示 -128,我只能说,回答得不要那么牵强, 原码 1000 0000 与 -128 的原码实际上是不同的。

           但为什么能用它表示 -128 进行运算,如果不要限制为 char 型(即不要限定是 8 位),再来看,-128 的原码:1 1000 0000 ,9位,最高位符号位,再算它的反码:1 0111 1111,进而,补码为:1 1000 0000,这是 -128 的补码,发现和原码一样,1 1000 0000 和 1000 0000 相同?如果说一样的人真是瞎了眼了,所以,-128 的原码和 -0(1000 000) 的原码是不同的,但是在 char 型中,是可以用 1000 000 表示 -128 的,关键在于char 是 8 位,它把 -128 的最高位符号位 1 丢弃了,截断后 -128 的原码为 1000 000 和 -0 的原码相同,

    也就是说 1000 0000 和 -128 丢弃最高位后余下的 8 位相同,所以才可以用 -0 表示 -128,这样,当初剩余的 -0(1000 0000),被拿来表示截断后的 -128,因为即使截断后的 -128 和 char 型范围的其他 (-127~127) 运算也不会影响结果, 所以才敢这么表示 -128。

           

    小笔记:

    对于char类型,最大的正数表示:0x7f , 最大的 负数表示 :0x80;
    对于int类型,最大的正数表示:0x7fffffff,最大的负数表示: 0x80000000;

    原文:https://blog.csdn.net/tonglin12138/article/details/91352612

  • 相关阅读:
    QT添加托盘代码
    2010年左右我说要做一个操作系统的时候,绝大多数人以为那是天方夜谭,是堂吉诃德式的行为。今天,我们讨论YunOS会成为一个新的生态和创新平台,更多人相信这件事是可能的。
    台哥算法练习:八皇后问题
    台哥算法练习 汉诺塔问题
    台哥算法练习:数组排序的几种算法
    面试遇到的两道算法题
    台哥算法练习 50人围圈报数
    台哥算法练习 自己写的一个LinkedList
    台哥算法练习 自己写的一个ArrayList
    台哥算法练习 寻找和为某值的子集
  • 原文地址:https://www.cnblogs.com/Ph-one/p/13502178.html
Copyright © 2011-2022 走看看