【问题标题】:how to read an input without knowing its size in C? [duplicate]如何在不知道 C 中输入大小的情况下读取输入? [复制]
【发布时间】:2013-11-03 20:19:45
【问题描述】:

我正在尝试使用 scanf 运算符获取输入,但我还需要它的长度,我无法定义 char name[number],因为我不知道从用户那里获得的输入的大小...

任何想法如何在不使用string.h 的情况下做到这一点?

这是我尝试做的,但这是非法的,因为我定义了数组的长度:

char string1[30];
printf("Enter string1:");
scanf("%s",string1);

【问题讨论】:

  • getline() 对这类事情很有用。人 getline()
  • 您开始询问阅读任务和您在那里的长度,但现在您想详细说明strcmp()。是在您想要进行长度测试的strcmp() 中,还是在外面?这并没有变得那么清楚......

标签: c string input


【解决方案1】:

您不可能知道用户的输入字符串会提前多长时间。所以只能提供一定大小的缓冲区,希望输入比那个大小短;如果输入太长,那么您的程序将不会一次获得所有输入。

假设您提示用户输入他/她的名字。我的名字是“Steve”,所以我只需要 5 个字母,但其他名字更长。我刚刚在 Google 上搜索了“最长的名字”,我发现的一个例子是“Lydiakalanirowealeekundemondisha”,它需要 32 个字母。好的,让我们将输入缓冲区的长度设置为 128 个字母并计算它可能足够长。

#include <stdio.h>

char first_name[128];

printf("Please enter your first name: ");
fgets(first_name, sizeof(first_name), stdin);

所以这里我们使用fgets() 来获取用户输入。我们告诉fgets() 将输入存储在我们的缓冲区(first_name)中,并告诉它我们缓冲区的大小。注意:我们在这里使用sizeof() 运算符,因此如果有人编辑文件并更改缓冲区大小,程序仍然是正确的。

现在,无论用户输入什么(或从剪贴板粘贴),我们的程序都只会读取前 127 个字符。如果用户输入的内容少于这个值,我们就会得到所有内容。

所以现在我们可以检查一下我们得到了多少:

if (strlen(first_name) >= sizeof(first_name) - 1)
{
    printf("That input is too long, sorry.\n");
}

在这里我们检查字符串的实际长度。如果它太长,我们会给用户一个错误消息。理论上,用户可以准确输入 127 个字符,并且输入会完全匹配,但我们无法知道用户是否准确输入了 127 个字符或更多。在实践中,我们不希望名字接近那么长,因此将这种情况视为错误是安全的。

现在,这是不这样做的方法。永远不要这样做。

char short_buffer[16];

printf("Please enter your first name: ");
gets(short_buffer);

函数gets() 无法知道缓冲区可以容纳多少个字符。如果用户键入“Lydiakalanirowealeekundemondisha”,则gets() 将注销缓冲区的末尾并可能导致错误。永远不要使用gets()

【讨论】:

    【解决方案2】:

    如果不定义最大尺寸,您可能无法相处。

    不定义大小并不重要,重要的是事后了解并尊重它。

    从用户那里获取输入的最简单方法是fgets()

    char string1[50];
    fgets(string1, sizeof string1, stdin);
    

    当然,你应该检查它的返回值。

    如果你想接受(几乎)任何长度,你可以试试the solution I gave here

    这是防止给定数组溢出所必需的。为了使用字符串,您可以使用strlen() 来获取它的长度,或者,如果您不允许使用它或正在走到字符串,则通过计数字符直到您遇到 NUL 字节。

    其背景是 C 中的字符串以 NUL 字节终止。它们是chars 的序列,NUL 字节(0,而不是 '0',它将是 48)终止此序列。


    如果您唯一的任务是验证您读取的字符串是否足够小,如果不是则抱怨,那么就这样做:-)

    int main(int argc, char ** argv)
    {
        char string2[50]; // larger than required; in order to be able to check.
        char string1[30]; // if all is ok, you have maximum length of 29, plus the NUL terminator. So 30 is ok.
        char * ret = fgets(string2, sizeof string2, stdin);
        if (!ret) {
            fprintf(stderr, "Read error.\n")
            return 1; // indicate error
        }
        if (strlen(string2) >= sizeof string1) { // we can take this size as a reference...
            fprintf(stderr, "String 1 too long.\n")
            return 1; // indicate error
        }
        strcpy(string1, string2); // as we have verified that this will match, it is ok.
        // Otherwise, we would have to use strncpy.
    
        // Now read the 2nd string by the same way:
        ret = fgets(string2, sizeof string2, stdin);
        if (!ret) {
            fprintf(stderr, "Read error.\n")
            return 1; // indicate error
        }
        if (strlen(string2) >= sizeof string1) { // we can take this size as a reference...
            fprintf(stderr, "String 2 too long.\n")
            return 1; // indicate error
        }
        // Now we know that both strings are ok in length an we can use strcmp().
        int c = strcmp(string1, string2);
        printf("strcmp() result: %d.\n", c);
        return 0; // indicate success
    }
    

    我现在不清楚你是否也应该实现strcmp()。如果是这样,我会把它留作练习。

    【讨论】:

    • 我有一个任务是从 string.h 实现 strCmp 并且允许最大大小为 30,否则我必须打印 invauld 消息所以我认为我必须知道检查合法性的输入
    • @somebody 这是完全不同的事情。 strcmp() 与阅读无关。如果你试图模仿strcmp(),你必须通过计数字符来获取给定字符串的长度,直到你碰到第一个NUL字节。
    • 我们需要的是获取 2 个字符串,它们应小于 30,否则它是无效的,所以我必须保留值和一些变量
    • @somebody 最好使用添加到 cmets 的更改要求来扩展问题,或者甚至更好地开始一个新要求。我现在可以在这里详细说明strcmp(),但它与上面的问题不太匹配。
    • @somebody 好的。所以你得到 2 个字符串,检查它们的长度,然后再进行比较。这又是一些不同的东西,可以在这里适应,所以我会试着写一下。
    猜你喜欢
    • 2022-01-15
    • 1970-01-01
    • 2018-03-24
    • 1970-01-01
    • 2014-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多