如何从fgets中检测空字符串

6

我正在尝试检测来自标准输入的fgets输入是否为空(当我按下回车而不输入任何内容时)。这是我的程序:

int main()
{
    char input[1000];
    printf("Enter :");
    fgets(input, 1000, stdin);
    input[strlen(input) - 1] = '\0';

    if(input != '\0'){
        printf("hi");
    }

    return 0;

}

我希望能添加一些条件,以使其不打印任何内容,但很明显这种方式是不正确的。我还尝试了NULL,但没有成功。
谢谢!

@JamesMcNellis 实际上,无论 input 来自何处,那行代码都不会有任何作用。strlen 函数只是在字符串中搜索第一个 '\0',因此根据定义,input[strlen(input) - 1] == '\0'。它唯一可能改变的是如果 input 没有以 null 结尾,并且在程序地址空间耗尽之前没有跟随任何 '\0',则会引入 segfault。 - Aaron Dufour
4个回答

8
我认为这是最易读的方法(但不是最高效的):
if (strlen(input) != 0) {
    printf("hi");
}

但是出于教学目的,这是您的样式,但是之后需要进行修复:

if (input[0] != '\0') {
    printf("hi");
}

为什么是input[0]?因为如果你将input与指向数组第一个元素的指针进行比较,那么input就像指针一样指向数组的第一个元素,您首先需要取消引用它才能使比较有用。


+1,但是input是一个数组,而不是指向数组的指针。在比较的上下文中它会衰减为指针,但是区分这一点非常重要。 - Carl Norum
是的,但你编辑成了相同(错误)的陈述。数组和指针并不是同一回事,尽管它们在这种特定情况下可以互换使用。 - Carl Norum
1
如果你把数组当作指针来使用,那么它们就是指针。但这并不意味着数组本身就是指针。 - James McNellis

5

显而易见的方法可能是这样的:

if (input[0] != '\0')
   printf("hi");

尽管使用 strlen 可以 起作用,但很可能会浪费资源 -- 它将 O(1) 操作转化为 O(N)。

当然,你几乎总是希望首先检查从 fgets 返回的值。如果它说成功读取了某些内容,那么你需要检查其内容以确保不为空。

下面是一个快速演示,可以捕获大部分可能发生的情况:

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

int main()
{
    char input[10];
    printf("Enter :");
    if (!fgets(input, sizeof(input), stdin)) {
        printf("fgets failed\n");
        return 0;
    }
    char *pos = strchr(input, '\n');
    if (pos != NULL) {
        printf("Removing new-line\n");
        *pos = '\0';
    }

    if(input[0] == '\0') {
        printf("empty input");
    } else {
        printf("Read input: \"%s\"", input);
    }
    return 0;
}

[注意:我已将输入大小从1000缩短到仅10个字符,以便您看到当您输入的内容超过了fgets所允许的读取时会发生什么。]

  • 如果你按下(只有)ctrl+d(Linux)或F6(Windows),你应该会收到“fgets失败”的消息。
  • 如果你只是按下Enter,你应该会收到“空输入”消息。
  • 如果您输入少于10个字符的字符串,则应显示“删除换行符”,然后显示您输入的字符串。
  • 如果您输入10个或更多字符的字符串,则应显示您输入的字符串的前9个字符(但不包括“删除换行符”消息)。

如果用户按下Ctrl-D,则fgets会返回NULL,并且“input”保持不变。因此,如果未初始化输入变量,则该测试将无效。另外,如果用户直接按Enter键,正如OP所请求的那样,该测试也无法工作,因为\n将在input [0]中。无论如何,我对促使我进行一些研究的特定情况感到感兴趣,因此给您点赞+1 :) - Déjà vu
1
@Déjàvu:\0测试会成功,因为代码之前用\0替换了'\n'。但是它实际上替换得不正确,所以如果输入超过缓冲区容量,就会丢失一个不同的字符。我已经更新了一些演示代码,展示了如何捕获大多数不同情况(以及正确删除换行符的方法,仅当存在时)。 - Jerry Coffin

3

fgets函数在用户按下回车键时会返回一个'\n',这将使得完整的字符串为"\n\0"。您可以使用此值进行字符串比较,但更健壮的解决方案是对字符串进行修剪以去除所有前导和尾随的空格(在任何处理之前都应该这样做),然后检查是否为空字符串。

最简单的修改方法是检查(*input!='\n')。需要注意的是,这也需要您删除空字符,这会同时删除换行符(按设计而言)。


1
为了保险起见,最好使用这个:

要安全一些,最好使用这个:

if(u_input[0] == '\n' && u_input[1] == '\0'){
    printf("hi");
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接