【问题标题】:program that keeps accepting three numbers, and prints the maximum among the three持续接受三个数字并打印三个数字中的最大值的程序
【发布时间】:2015-12-04 18:09:31
【问题描述】:

持续接受三个数字并打印三个数字中的最大值的程序。 我收到运行时错误(SIGABRT) 这是我的代码

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

int main()
{
    char ch[30];
    char *c[3];
    long int i[3], mx_2;
    int o;
    while((fgets(ch,sizeof(ch),stdin))&&ch!='\0')
    {
        c[0] = (char *)malloc(10);
        c[1] = (char *)malloc(10);
        c[2] = (char *)malloc(10);
        c[0] = strtok(ch," ");
        c[1] = strtok(NULL," ");
        c[2] = strtok(NULL," ");
        i[0] = atoi(c[0]);
        i[1] = atoi(c[1]);
        i[2] = atoi(c[2]);
        mx_2 = i[0] > i[1] ? (i[0] >i[2] ? i[0] : i[2]) : (i[1] > i[2] ? i[1] : i[2]);
        printf("%ld\n",mx_2);
        fflush(stdin);
        for (o = 0; o < 3; o++) {
            free(c[o]);
        }
    }

    return 0;
}

任何帮助家伙 谢谢

【问题讨论】:

  • c[0]=strtok(ch," "); 之后立即执行i[0]=atoi(c[0]); 并检查c[0] != NULL。类似i[1]=atoi(c[1]); i[2]=atoi(c[2]);
  • 请注意ch!='\0' 始终为假,因为您将ch 的地址与'\0' 进行比较。
  • free(c[o]);这个点不能释放它,因为malloc的返回值被strtok的返回值重写(不需要malloc和free。)
  • 一如既往:请不要在 C 中强制转换 malloc & co 的返回值(在 C++ 中必须这样做,但在 C 中这被认为是不好的做法)

标签: c if-statement dynamic conditional


【解决方案1】:

当您执行c[0] = malloc(10); 和一些句子之后您执行c[0] = strtok(...); 时,您将用strtok(3) 的结果覆盖c[0]指针值(它本身就是一个指针),不复制字符串内容。当您到达free(3)for 循环时,您将传递给free() 函数由strtok 给出的值,而不是从malloc() 给出的值(当您重新分配数组@987654331 时,这些值将永远丢失@values) 所以这是你的SIGABRT 最可能的原因。

顺便说一句,您甚至不需要在程序中执行任何mallocfree。只需获得一个足够长的缓冲区来存储一整行输入,然后使用 strtok 获取所有块。另一方面,您必须测试strtok 结果,如果没有更多数据(您只输入两个值)它将返回NULL

这段代码不仅可以处理三个值,还可以处理不超过数组大小的任何数字:

#include <stdio.h> /* for input output routines like fgets */
#include <stdlib.h> /* for the constant EXIT_SUCCESS */
#include <limits.h> /* for INT_MAX and INT_MIN */
#include <string.h> /* for strtok */

int main()
{
    char buffer[1024];
    while (fgets(buffer, sizeof buffer, stdin)) {
        /* we have one full line of input up to sizeof buffer chars.  */
        int max = INT_MIN;
        int min = INT_MAX;
        char *s = strtok(buffer, " \t\n");
        if (!s) {
            fprintf(stderr, "Invalid line\n");
            continue;
        }
        while (s) {
            int x = atoi(s);
            if (x > max) max = x;
            if (x < min) min = x;
            s = strtok(NULL, " \t\n");
        }
        if (max != INT_MIN)
            printf("MAX: %d\n", max);
        if (min != INT_MAX)
            printf("MIN: %d\n", min);
    } /* while */
    return EXIT_SUCCESS;
} /* main */

【讨论】:

  • 谢谢,但是如果我们在这样的循环中使用它,为什么会出现运行时错误ideone.com/N4RQH3
  • 好吧,在链接中的代码中,您不会检查从 strtok 返回的可能的 NULL 值,并且,如果您只是按回车键(没有数字),所有值都将是 @ 987654340@(甚至是第一个),您将尝试atoi(NULL);,它会喊出SEGFAULT 运行时。在我的循环中,一旦strtok 返回NULL,我就会停止,所以我不会属于你的情况。看,如果你在我的情况下点击返回,除了一条消息说"Invalid line",你什么也得不到,因为你没有数据需要考虑。
【解决方案2】:

更好地使用 scanf 来完成您的任务:

 scanf(" %d %d %d", i, i+1, i+2);//note the leading space in the format

【讨论】:

  • scanf 格式中添加了一个前导空格以跳过缓冲区中的空格
  • 使用%ld 而不是%d格式中的前导空格不是必需的。
  • @BLUEPIXY:不是必需的,但建议使用,尤其是考虑到 OP 将在循环中调用 scanf\
  • @EliasVanOotegem 不需要在循环中被调用。 %d 跳过前面的空格。
  • %ld 格式是必需的,如果你正在处理long s。在 32 位架构中,它们是相同的,但在 16 位架构中不同,您将获得 U.B.
猜你喜欢
  • 1970-01-01
  • 2019-03-29
  • 1970-01-01
  • 2018-09-10
  • 2020-11-09
  • 1970-01-01
  • 2014-10-30
  • 1970-01-01
  • 2022-12-09
相关资源
最近更新 更多