我试图通过scanf捕获用户的输入:

char numStrings[5000];
printf("Enter string of numbers:\n\n");
scanf("%s", numStrings);


但是,输入的字符串的长度为5000个字符。 c99中的翻译限制为4095个字符。我是否需要指示用户将输入减半,还是有我无法想到的更好的解决方法?

最佳答案

我是否需要指示用户将输入减半,还是有我无法想到的更好的解决方法?


就给定的代码而言,如果输入字长于4999字节,则可能会导致缓冲区溢出。是的,明智的做法是让某人(例如,用户或下一个维护此代码的人)知道这是最大长度。可以使用以下代码截断输入,这是很好的:scanf("%4999s" "%*[^ \n]", numStrings); ...在这种情况下,%*[^ \n]指令执行截断。

如果您可以在用户溢出缓冲区时通知用户,那会更好,但是scanf并不是一件容易的事。如果您可以使用动态分配,那会更好(对于用户而言)。

啊,动态调整输入大小的问题。如果可以避免,那就避免它。避免此问题的一种常用方法是要求输入argv而不是stdin ...的形式,但这并不总是可能,有用或可行的。

scanf并没有使这个问题特别容易解决;实际上,要解决%s是否提供类似于fgets的接口形式的功能,要容易得多。

无需再赘述,这是对我在this answer中编写的代码的改编,该改编目的在于以与%s后面相似的过程读取(并同时分配)单词,而不是与后面的过程类似的行fgets。如果您想进一步了解其背后的灵感,请随时阅读该答案。

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

char *get_dynamic_word(FILE *f) {
    size_t bytes_read = 0;
    char *bytes = NULL;
    int c;
    do {
        c = fgetc(f);
    } while (c >= 0 && isspace(c));
    do {
        if ((bytes_read & (bytes_read + 1)) == 0) {
            void *temp = realloc(bytes, bytes_read * 2 + 1);
            if (temp == NULL) {
                free(bytes);
                return NULL;
            }
            bytes = temp;
        }

        bytes[bytes_read] = c >= 0 && !isspace(c)
                            ? c
                            : '\0';
        c = fgetc(f);
    } while (bytes[bytes_read++]);
    if (c >= 0) {
        ungetc(c, f);
    }
    return bytes;
}

10-08 09:33
查看更多