2

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

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

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

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

2 回答 2

3

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

假设您正在提示用户输入他/她的名字。我的名字是“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");
}

Here we check to see how long the string actually was. If it was too long we give an error message to the user. In theory, the user could have typed exactly 127 characters and the input would fit exactly, but we have no way to know if the user typed exactly 127 characters or more than that. And in practice we don't expect a first name to be anywhere near that long, so it's safe to treat this condition as an error.

Now, here is how to not do it. Never do this ever.

char short_buffer[16];

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

The function gets() has no way to know how many characters will fit in the buffer. If the user types "Lydiakalanirowealeekundemondisha" then gets() will write off the end of the buffer and likely cause an error. Never use gets().

于 2013-11-03T20:51:46.903 回答
1

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

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

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

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

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

如果您想接受(几乎)任何长度,您可以尝试我在此处提供的解决方案

这是防止给定数组溢出所必需的。为了使用字符串,您可以使用 来获取它的长度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()。如果是这样,我会把它留作练习。

于 2013-11-03T20:25:12.757 回答