C &引用;将数字串转换为其等效数字“quot;示例未按照K&;正常工作;R
我正试图从C &引用;将数字串转换为其等效数字“quot;示例未按照K&;正常工作;R,c,gcc,raspberry-pi,kernighan-and-ritchie,C,Gcc,Raspberry Pi,Kernighan And Ritchie,我正试图从stdlib.h中找出函数atoi()。根据K&R,它看起来如下所示: int atoi(char s[]) { int n, i; n = 0; for (i = 0; s[i] >= '0' && s[i] <= '9'; ++i) n = 10 * n + (s[i] - '0'); return n; } 输出: -123 0 0 -2147483648 但是,在我的程序中,我试图提供字符串作为输入,并仅
stdlib.h
中找出函数atoi()
。根据K&R,它看起来如下所示:
int atoi(char s[]) {
int n, i;
n = 0;
for (i = 0; s[i] >= '0' && s[i] <= '9'; ++i)
n = 10 * n + (s[i] - '0');
return n;
}
输出:
-123
0
0
-2147483648
但是,在我的程序中,我试图提供字符串作为输入,并仅获取数字作为输出:
代码2:
#include <stdio.h>
#include <stdlib.h>
int main() {
int c, i;
char s[i];
for (i = 0; (c = getchar()) != '\n'; ++i)
s[i] = c;
s[i] = '\n';
s[++i] = '\0';
printf("%i", atoi(s));
}
我得到的输出值不正确
问题:
1) 根据代码1,printf(“%i”,atoi(“-123junk”)
,函数atoi()
似乎可以接收字符串作为参数,并返回表示输入字符串中数字值串联的单个整数,不是吗
2) 来自stdlib.h的atoi()
返回什么
3) 如何修复代码2中的函数main()
,以便从stdin
中获取字符,写入数组,调用函数atoi()
,将数组作为参数提供,在输出中接收数字
4) 根据函数atoi()
的K&R示例,“表达式(s[i]-'0')
是存储在s[i]
中的字符的数值”,但是,为什么我们需要添加10*n
部分,而且,要将n
分配给它前面的0
,因为n*0=0
,因此,n*10=0
,这意味着n*10
在赋值语句n=10*n+(s[i]-“0”)中始终为零代码>,因此,我们为什么需要它
5) 如果atoi()返回一个整数,那么printf(“%i”,atoi(“-123junk”)的结果如何处理代码>返回带有数字的字符串-123
?换句话说,我是否理解正确:函数atoi()
在函数printf()
中调用,并以“-123junk”
作为参数。函数atoi()
返回整数,只返回一个整数,类似于n=10*n+(s[i]-“0”)代码>比,如何在-123
中展开?Q1)您的atoi()
版本太简单,标准版本忽略前导空格字符,并处理数字前的可选符号<代码>原子(“-123垃圾”)
的计算结果应为-123
Q2)atoi
是用原型intatoi(constchar*s)定义的标准函数代码>它返回一个整数
问题3)代码2
中有一些错误:
- 将
char
数组s
的大小指定为i
,这是未初始化的。您应该使用一个相当大的值来定义数组,例如64
- 您应该测试循环中是否存在潜在的缓冲区溢出
- 您应该检查
EOF
以停止循环,以防遇到文件结尾没有换行符的情况
以下是修改后的版本:
#include <stdio.h>
#include <stdlib.h>
int main() {
char s[64];
size_t i;
int c;
for (i = 0; i < sizeof(s) - 1 && (c = getchar()) != EOF;) {
s[i++] = c;
if (c == '\n')
break;
}
s[i] = '\0';
printf("%i", atoi(s));
return 0;
}
但是这个函数更麻烦,而且实际上可能比简单的版本效率更低。尝试在您的系统上对这两种方法进行基准测试
为了完整起见,这里有一个使用ctype.h>
的完全可移植版本,它处理可选的初始空格和可选符号。它还通过定义的行为处理溢出,尽管不需要标准版本的atoi()
来执行此操作
#include <limits.h>
#include <stdio.h>
int atoi(const char *s) {
int n = 0, d;
/* skip optional initial white space */
while (isspace((unsigned char)*s))
s++;
if (*s == '-') {
/* convert negative number */
s++;
while (isdigit((unsigned char)*s)) {
d = (*s++ - '0');
/* check for potential arithmetic overflow */
if (n < INT_MIN / 10 || (n == INT_MIN / 10 && -d < INT_MIN % 10)) {
n = INT_MIN;
break;
}
n = n * 10 - d;
}
} else {
/* ignore optional positive sign */
if (*s == '+')
s++;
while (isdigit((unsigned char)*s)) {
d = (*s++ - '0');
/* check for potential arithmetic overflow */
if (n > INT_MAX / 10 || (n == INT_MAX / 10 && d > INT_MAX % 10)) {
n = INT_MAX;
break;
}
n = n * 10 + d;
}
}
return n;
}
int main(int argc, char *argv[]) {
int i, n;
for (i = 1; i < argc; i++) {
n = atoi(argv[i]);
printf("\"%s\" -> %d\n", argv[i], n);
}
return 0;
}
#包括
#包括
int atoi(常量字符*s){
int n=0,d;
/*跳过可选的初始空白*/
while(isspace((无符号字符)*s))
s++;
如果(*s=='-'){
/*换算负数*/
s++;
while(isdigit((无符号字符)*s)){
d=(*s++-“0”);
/*检查潜在的算术溢出*/
如果(nINT_MAX/10 | |(n==INT_MAX/10&&d>INT_MAX%10)){
n=INT_MAX;
打破
}
n=n*10+d;
}
}
返回n;
}
int main(int argc,char*argv[]){
inti,n;
对于(i=1;i%d\n”,argv[i],n);
}
返回0;
}
您认为s
数组的大小是多少?为什么不使用fgets()
来读取一行输入,而不是编写自己的循环?s
的大小是不确定的,因为在声明char s[i]之前,您从未为i
分配过任何内容
@readonly这里的要点是,通过使用类似于程序的数组,程序具有未定义的行为,可能会产生任何结果。你在说什么atoi
不会为每个数字调用一次。它对整个字符串调用一次,并在字符串中的数字上循环。在将每个数字添加到结果中之前,它将乘以10。注意:如果(s[i]>='1'和&s[i]@chqrlie刚刚尝试运行您提到的代码,并且注意到,当我使用类似于“123242somelets12321”的字符串时
作为输入,我只得到第一个数字作为输出,这是预期的吗???@readonly-当中的测试条件(s[I]>='0'和&s[I]@chux:当然可以删除您提到的代码,但它确实保存了乘法,这正是此替代函数的目的。关于:while(s[I]='0'))
如果前导字符是空白怎么办?如果前导字符是“+”怎么办?如果前导字符是“-”怎么办?
#include <stdio.h>
#include <stdlib.h>
int main() {
char s[64];
size_t i;
int c;
for (i = 0; i < sizeof(s) - 1 && (c = getchar()) != EOF;) {
s[i++] = c;
if (c == '\n')
break;
}
s[i] = '\0';
printf("%i", atoi(s));
return 0;
}
int atoi(const char *s) {
int n = 0;
size_t i = 0;
while (s[i] == '0')
i++;
if (s[i] >= '1' && s[i] <= '9') {
n = s[i++] - '0';
while (s[i] >= '0' && s[i] <= '9')
n = 10 * n + (s[i++] - '0');
}
return n;
}
#include <limits.h>
#include <stdio.h>
int atoi(const char *s) {
int n = 0, d;
/* skip optional initial white space */
while (isspace((unsigned char)*s))
s++;
if (*s == '-') {
/* convert negative number */
s++;
while (isdigit((unsigned char)*s)) {
d = (*s++ - '0');
/* check for potential arithmetic overflow */
if (n < INT_MIN / 10 || (n == INT_MIN / 10 && -d < INT_MIN % 10)) {
n = INT_MIN;
break;
}
n = n * 10 - d;
}
} else {
/* ignore optional positive sign */
if (*s == '+')
s++;
while (isdigit((unsigned char)*s)) {
d = (*s++ - '0');
/* check for potential arithmetic overflow */
if (n > INT_MAX / 10 || (n == INT_MAX / 10 && d > INT_MAX % 10)) {
n = INT_MAX;
break;
}
n = n * 10 + d;
}
}
return n;
}
int main(int argc, char *argv[]) {
int i, n;
for (i = 1; i < argc; i++) {
n = atoi(argv[i]);
printf("\"%s\" -> %d\n", argv[i], n);
}
return 0;
}