Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C &引用;将数字串转换为其等效数字“quot;示例未按照K&;正常工作;R_C_Gcc_Raspberry Pi_Kernighan And Ritchie - Fatal编程技术网

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