标签:
atoi是一个比较常用的字符串转换成整数的函数,原型是
int atoi(const char *str)
输入一个字符串,返回一个int型变量,但是它的实现在不同平台下不尽相同,今天做leetcode的时候就遇到了这个问题。
leetcode的这道题是这样的:
Expression Add Operators
Given a string that contains only digits 0-9
and a target value, return all possibilities to add binary operators (not unary) +
, -
, or *
between the digits so they evaluate to the target value.
Examples:
"123", 6 -> ["1+2+3", "1*2*3"] "232", 8 -> ["2*3+2", "2+3*2"] "105", 5 -> ["1*0+5","10-5"] "00", 0 -> ["0+0", "0-0", "0*0"] "3456237490", 9191 -> []
给一个只含有0-9字符的字符串和一个目标值,在字符串中添加 + / * 三种符号,使字符串形成的计算表达式的值和目标值相同,返回所有可能的结果。
这道题是常见的用递归可以解决的题,我的代码是这样的
class Solution { public: vector<string> addOperators(string num, int target) { vector<string> result; if(num.empty()) return result; string expression = ""; int last_result = 0; dfs(result, expression, num, ‘+‘, 0, 0, target); return result; } void dfs(vector<string> &result, string &expression, string &number_str, char pre_oper, long long val, long long pre_num, long long target) { int len = number_str.size(); int num = atoi(number_str.c_str()); if(number_str.empty()) { if(val + pre_num == target) { result.push_back(expression); return; } } for(int i = 1; i <= len; i++) { string num_left_str = number_str.substr(0, i); string num_right_str = number_str.substr(i); long long num_left = atoi(num_left_str.c_str()); long long new_pre_num = 0; expression += num_left_str; long long new_val = 0; if(pre_oper == ‘*‘) { new_pre_num = pre_num * num_left; new_val = val; } else { new_pre_num = pre_oper == ‘+‘ ? num_left : -num_left; new_val = val + pre_num; } if(num_right_str.empty()) dfs(result, expression, num_right_str, ‘ ‘, new_val, new_pre_num, target); else { expression.push_back(‘+‘); dfs(result, expression, num_right_str, ‘+‘, new_val, new_pre_num, target); expression.back() = ‘-‘; dfs(result, expression, num_right_str, ‘-‘, new_val, new_pre_num, target); expression.back() = ‘*‘; dfs(result, expression, num_right_str, ‘*‘, new_val, new_pre_num, target); expression.pop_back(); } expression.resize(expression.size() - i); if(num_left_str == "0") return; } } };
这里我用atoi来将字符串转换为数字,但是在提交之后出现了wrong answer, 出错的test case是
else if ( (flags & FL_OVERFLOW) || ( !(flags & FL_UNSIGNED) && ( ( (flags & FL_NEG) && (number > -LONG_MIN) ) || ( !(flags & FL_NEG) && (number > LONG_MAX) ) ) ) ) { /* overflow or signed overflow occurred */ errno = ERANGE; if ( flags & FL_UNSIGNED ) number = ULONG_MAX; else if ( flags & FL_NEG ) number = (unsigned long)(-LONG_MIN); else number = LONG_MAX; }
可以看到,当转换得到的数溢出时,函数返回LONG_MAX, LONG_MIN 或 ULONG_MAX,总而言之,返回最大值或最小值。
所以当输入“2147483648”时,得到的整数是2147483647,和目标值不同,最终结果为空。
而我们再看看leetcode用的atoi函数是如何处理的?由于没法看到源码,所以我改了一下代码,直接输出结果来看
vector<string> addOperators(string num, int target) { vector<string> result; if(num.empty()) return result; string expression = ""; int last_result = 0; int a = atoi(num.c_str()); //得到转换后的结果并输出 cout << a << endl; dfs(result, expression, num, ‘+‘, 0, 0, target); return result; }
Your stdout那一栏就是输出的a的值
可以看到当输入字符串为“2147483648”时,调用atoi得到的整数是-2147483648,正好和目标值相同,因此系统就将“2147483648”当作了结果。
因为这一个函数的实现差异,导致了最终不同平台上的不同结果。
总结:对于C++中的某些函数,linux下和windows的实现会有一些差异,而这些差异可能就会引发很严重的后果,所以如果要编写跨平台的程序,一定要慎重慎重再慎重。
标签:
原文地址:http://www.cnblogs.com/moonfighting/p/4834932.html