You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

C语言读取两行整数输入的代码问题咨询

问题排查与解决方案

嗨,我来帮你看看这段代码的问题所在,以及怎么修复它!

你的代码为什么会出问题?

你当前的实现依赖于scanf("%d%c")来读取整数和后续字符,以此判断是否到达行尾,但这里有几个关键问题:

  • 没检查scanf的返回值:当scanf无法读取整数时(比如遇到换行、非数字字符),它会返回小于2的数值,但你的代码直接忽略了这个情况,会导致数组元素被赋予不确定的值,甚至陷入死循环。
  • 跨平台换行符不兼容:在Windows系统中,回车键生成的是\r\n而非\n,你的第一个循环会把\r读入temp,因为它不等于\n,循环会继续执行下一次scanf,但此时下一个字符是\n,无法被%d读取,直接导致逻辑混乱。
  • 空白字符处理漏洞:如果一行末尾有多个空格再换行,读完最后一个整数后,下一次scanf会尝试读取空格后的整数,显然失败,同样会引发错误。

更可靠的解决方案:先读整行再解析

推荐用fgets先读取整行内容,再用strtoksscanf解析每行的整数,这种方式能避开所有换行符和读取失败的问题,逻辑也更清晰。

方案1:使用strtok分割字符串(简洁版)

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

int main() {
    int arr[10000], brr[10000];
    int i = 0, j = 0;
    char line[1024]; // 假设每行最多1024字符,可根据需求调整
    char *token;

    // 读取并解析第一行
    if (fgets(line, sizeof(line), stdin)) {
        // 用空格、换行、回车作为分隔符分割字符串
        token = strtok(line, " \n\r");
        while (token != NULL) {
            arr[i++] = atoi(token); // 把字符串转成整数
            token = strtok(NULL, " \n\r"); // 获取下一个分割后的片段
        }
    }

    // 读取并解析第二行
    if (fgets(line, sizeof(line), stdin)) {
        token = strtok(line, " \n\r");
        while (token != NULL) {
            brr[j++] = atoi(token);
            token = strtok(NULL, " \n\r");
        }
    }

    // 输出第一行数组
    for (int k = 0; k < i; k++) {
        printf("%d ", arr[k]);
    }
    printf("\n");

    // 输出第二行数组
    for (int l = 0; l < j; l++) {
        printf("%d ", brr[l]);
    }
    printf("\n");

    return 0;
}

方案2:使用sscanf逐次解析(更可控)

如果你不想用strtok,也可以用sscanf配合指针移动来解析:

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

int main() {
    int arr[10000], brr[10000];
    int i = 0, j = 0;
    char line[1024];
    char *ptr;

    // 处理第一行
    if (fgets(line, sizeof(line), stdin) != NULL) {
        ptr = line;
        // 每次解析一个整数,直到解析失败
        while (sscanf(ptr, "%d", &arr[i]) == 1) {
            i++;
            // 跳过当前数字后的所有非数字字符
            while (*ptr != '\0' && (*ptr < '0' || *ptr > '9')) {
                ptr++;
            }
            // 跳过当前数字本身
            while (*ptr != '\0' && (*ptr >= '0' && *ptr <= '9')) {
                ptr++;
            }
        }
    }

    // 处理第二行
    if (fgets(line, sizeof(line), stdin) != NULL) {
        ptr = line;
        while (sscanf(ptr, "%d", &brr[j]) == 1) {
            j++;
            while (*ptr != '\0' && (*ptr < '0' || *ptr > '9')) {
                ptr++;
            }
            while (*ptr != '\0' && (*ptr >= '0' && *ptr <= '9')) {
                ptr++;
            }
        }
    }

    // 输出结果
    for (int k = 0; k < i; k++) printf("%d ", arr[k]);
    printf("\n");
    for (int l = 0; l < j; l++) printf("%d ", brr[l]);
    printf("\n");

    return 0;
}

为什么这个方案更好?

  • fgets会一次性读取整行内容,不管系统的换行符是\n还是\r\n,都能正确处理。
  • 先拿到整行再解析,能完全避免scanf因混合读取整数和字符带来的各种边界问题。
  • 逻辑更直观,后续维护或扩展(比如处理更多行)也更方便。

内容的提问来源于stack exchange,提问作者Piotr Wasilewicz

火山引擎 最新活动