3

I made a program, and found out gets(), and used it, it was great, however when I compiled the program it said that gets is dangerous, so then I searched up an alternative, even though the gets() function made it have the correct output, for the future I would rather use an alternative which isn't dangerous, which is when I stumbled upon fgets(). I thought that the code would compile the same and have the same output, however none of my if statments were being outputted.

Heres the code:

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

int main()
{
        char qOne[10];
        char qTwo[10];
        char guess[40] = "My guess is that you are thinking of a\0";

        printf("TWO QUESTIONS\n");
        printf("Think of an object, and i'll try to guess it.\n\n");

        printf("Question 1) Is it an animal, vegetable, or mineral?\n");
        printf("\n> ");
        //gets(qOne);
        fgets(qOne, 10, stdin);

        printf("\nQuestion 2) Is it bigger than a breadbox? (yes/no)\n");
        printf("\n> ");
        //gets(qTwo);
        fgets(qTwo, 10, stdin);

        printf("\n");

        if(strcmp(qOne, "animal") == 0 && strcmp(qTwo, "no") == 0 ||strcmp(qOne, "animal") == 0 && strcmp(qTwo, "No") == 0)

                printf("%s squirrel.\n", guess);

        else if(strcmp(qOne, "animal") == 0 && strcmp(qTwo, "yes") == 0 ||strcmp(qOne, "animal") == 0 && strcmp(qTwo, "Yes") == 0)

                printf("%s moose.\n", guess);

        else if(strcmp(qOne, "vegetable") == 0 && strcmp(qTwo, "no") == 0 ||strcmp(qOne, "vegetable") == 0 && strcmp(qTwo, "No") == 0)

                printf("%s carrot.\n", guess);

        else if(strcmp(qOne, "vegetable") == 0 && strcmp(qTwo, "yes") == 0 ||strcmp(qOne, "vegetable") == 0 && strcmp(qTwo, "Yes") == 0)

                printf("%s watermelon.\n", guess);

        else if(strcmp(qOne, "mineral") == 0 && strcmp(qTwo, "no") == 0 ||strcmp(qOne, "mineral") == 0 && strcmp(qTwo, "No") == 0)

                printf("%s paper clip.\n", guess);

        else if(strcmp(qOne, "mineral") == 0 && strcmp(qTwo, "yes") == 0 ||strcmp(qOne, "mineral") == 0 && strcmp(qTwo, "Yes") == 0)

                printf("%s Camaro.\n", guess);


        printf("\nI would ask you if I'm right, but I don't actually care.\n");

        return 0;
}

The output of this code is (inputting the strings "animal", and "yes"):

TWO QUESTIONS
Think of an object, and i'll try to guess it.

Question 1) Is it an animal, vegetable, or mineral?

> animal

Question 2) Is it bigger than a breadbox? (yes/no)

> yes


I would ask you if I'm right, but I don't actually care.

However when I only use gets() instead of fgets() my code gives the correct output, which is:

TWO QUESTIONS
Think of an object, and i'll try to guess it.

Question 1) Is it an animal, vegetable, or mineral?

> animal

Question 2) Is it bigger than a breadbox? (yes/no)

> yes

My guess is that you are thinking of a moose.

I would ask you if I'm right, but I don't actually care.

How can I get the same output, with fgets()?

Derrick Rose
  • 664
  • 2
  • 9
  • 21
  • Not may, does. `gets()` replaces the newline from the input with `\0`, but `fgets()` retains it. – chepner Sep 01 '15 at 20:21
  • both `fgets()` and `gets()` are probably in fact working correctly in a mature C library implementation. – The Paramagnetic Croissant Sep 01 '15 at 20:24
  • 2
    If `fgets()` *doesn't* leave a trailing `'\n'` in the destination array, that means the input line was longer than the buffer -- which means that the rest of the input line is left in place waiting to be read by the next input call. You should do probably do something to handle that case. (For example, you could just read and discard characters until you see `'\n'` or `EOF`.) – Keith Thompson Sep 01 '15 at 20:26
  • 1
    Just as a note, `gets` *will* introduce a point of failure in your code, and is no longer part of the standard library as of the 2011 revision. You really don't want to use it for anything. It is ridiculously unsafe to use. – John Bode Sep 01 '15 at 20:31
  • 1
    Keith Thompson is correct in "If fgets() doesn't leave a trailing '\n' ... input line was longer than the buffer" is certainly the most likely reason. Other possibilities include: 1) End-of-file occurred and the last character was not a `'\n'`. 2) An embedded `'\0'` occurred before the `'\n'` masking its presence. 3) The `fgets()` return value was not checked against `NULL` and buffer contents may be indeterminate. – chux - Reinstate Monica Sep 01 '15 at 20:32

1 Answers1

6

fgets() retains the end-line '\n' and gets() does not. Then the compares fail. @user3121023 Add code to eliminate the potential end-line.

if (fgets(qTwo, sizeof qTwo, stdin) == NULL) Handle_EOF();
qTwo[strcspn(qTwo, "\n")] = 0;

Removing trailing newline character from fgets() input


[Edit]

Note @Keith Thompson comment above about excessively long line of input.

Community
  • 1
  • 1
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • 2
    OP: Note that `fgets()`, in saving the `'\n'` needs a +1 longer buffer as `gets()`. BTW: Good to drop using `gets()`. – chux - Reinstate Monica Sep 01 '15 at 20:26
  • When I add in that piece of code, I have no idea what Handle_EOF() is, I put the code after the fgets, but I am still somewhat lost. – Derrick Rose Sep 01 '15 at 20:54
  • 1
    @Asad Mahmood `Handle_EOF()` means you need to write some code to handle the situation. `fgets()` returns either `qTwo` or `NULL`. When it returns `NULL` is means the end of file occurred (`stdin` is closed) or _rarely_ an Input error occurred. For simple programs like these suggest `if (fgets(qTwo, sizeof qTwo, stdin) == NULL) { puts("EOF Occurred"); return -1; }` – chux - Reinstate Monica Sep 01 '15 at 21:01
  • Works like a charm bud, +1 to you :) – Derrick Rose Sep 02 '15 at 00:44