How to detect empty string from fgets
Asked Answered
T

4

6

I'm trying to detect the input of fgets from stdin as empty (when I press enter without entering in anything). Here is my program:

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

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

    return 0;

}

I want to do some sort of condition which makes it not print anything, but clearly this way isn't right. I also tried NULL, which did not work.

Thanks!

Tusker answered 8/11, 2011 at 23:55 Comment(1)
@JamesMcNellis In fact, that line will never do anything, regardless of where input came from. The strlen function just searches for the first '\0' in the string, so by definition input[strlen(input) - 1] == '\0'. The only thing it could change is the introduction of a segfault if input isn't null-terminated, and doesn't happen to be followed by any '\0's before running out of your program's address space.Falconry
F
8

I think this is the most readable (but not performant):

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

But for the sake of teaching here is your style, but then fixed:

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

Why input[0]? Because input acts like a pointer to the first element of the array if you compare it like that and you first have to dereference it to make the comparison useful.

Frontolysis answered 8/11, 2011 at 23:57 Comment(3)
+1, but input is an array, not a pointer to an array. It does decay into a pointer in the context of that comparison, but it's important to make the distinction.Packard
Yes, but you edited to the same (wrong) statement. Arrays and pointers aren't the same thing, even though they happen to be used interchangeably in this specific case.Packard
"arrays are pointers if you treat them as such" No, an array can be used as a pointer, but that does not mean that it is a pointer.Hanfurd
O
5

The obvious way would be something like:

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

Although using strlen will work, it's potentially quite wasteful -- it turns an O(1) operation into O(N).

Of course, you nearly always want to start by checking the return value from fgets first. Then if it says it succeeded at reading something, you check the content to be sure it's not empty.

Here's a quick demo of catching most of what can happen:

#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;
}

[Note: I've shortened the input size from 1000 to only 10 characters so it's easy to see what happens when you enter more input than you've allowed fgets to read.]

  • If you press (only) ctrl+d (Linux) or F6 (Windows), you should get the "fgets failed" message.
  • If you just press Enter, you should get the "empty input" message.
  • If you enter a string of less than 10 characters, you should get "removing new-line" followed by a display of the string you entered.
  • If you enter a string of 10 or more characters, you should get a display of the first 9 characters of the string you entered (but not the "Removing new-line" message).
Overdye answered 9/11, 2011 at 0:1 Comment(2)
If the user hits Ctrl-D then fgets returns NULL and input is unchanged. So if the input var is not initialized, that test will not work. Also, if the user hits Enter directly, as OP requested, that test won't work either as the \n will be in input[0]. Anyway, +1 because I was interested in that specific case that prompted me to do some research :)Monia
@Déjàvu: the \0' test will work because the code previously replaced the '\n' with a '\0'. But it really did that incorrectly, so it would lose a different character if you entered more than the buffer would hold. I've updated it with some demo code to show how to catch most of the different cases (and a correct way to remove the new-line if an only if it's present).Overdye
B
3

fgets will return a '\n' when the return key is pressed; this makes the total string "\n\0". You can do a string comparison with this value, but a more robust solution is to 'strip' or 'trim' the string to remove all leading and trailing whitespace (which you should do anyway before any processing) and then check for an empty string.

The easiest modification is to check whether (*input!='\n'). I should note that this also requires you to remove the null-terminating code, which strips out this newline (by design, presumably).

Bulbil answered 9/11, 2011 at 0:2 Comment(0)
N
2

To be on the safe side, better use this:

if(u_input[0] == '\n' && u_input[1] == '\0'){
    printf("hi");
}
Nomology answered 9/2, 2016 at 10:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.