gpt4 book ai didi

c - "string of digits into its numeric equivalent"示例无法根据 K&R 正常工作

转载 作者:太空宇宙 更新时间:2023-11-04 03:13:18 25 4
gpt4 key购买 nike

我试图从 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;
}

据我所知,stdlib.h 中的atoi() 函数应该获取任何字符的字符串作为输入,并且只输出数字,如下所示:

代码 1:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
printf("%i", atoi(" -123junk"));
printf("%i", atoi("0"));
printf("%i", atoi("junk")); // no conversion can be performed
printf("%i", atoi("2147483648")); // UB: out of range of int
}

输出:

-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));
}

在机器上执行时:

pi@host:~/new$ cc new.c
pi@host:~/new$ a.out
21412421How it is
0

我得到的输出值不正确。

问题:

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() 版本太简单了,标准版本忽略前导空白字符并处理数字前的可选符号。 atoi("-123junk") 的计算结果应为 -123

Q2) atoi 是一个用原型(prototype)int atoi(const char *s); 定义的标准函数;它返回一个整数。

Q3) 代码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;
}

Q4) 表达式 n = 10 * n + (s[i] - '0') 为字符串中找到的每个新数字求值。只要没有遇到非零数字,将当前值乘以 10 确实有点低效,但是这样写函数很简单。

为了避免这些无用的乘法,这里有一个替代方案:

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;
}

但是这个函数比较麻烦,实际上可能不如简单版本有效。在您的系统上尝试和基准测试。

为了完整起见,这里是一个完整的可移植版本,使用 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;
}

关于c - "string of digits into its numeric equivalent"示例无法根据 K&R 正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54225045/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com