0

I've been racking my brain on this for a good hour or so.

It's a simple check on whether a string is palindrome or not.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define LEN 20

int main()
{

    char word[LEN], drow[LEN];
    printf("Insert a word: ");
    fgets(word, LEN + 1, stdin);

    strcpy(drow, word);
    strrev(word);

    if(strcmp(drow,word) == 0){
        printf("The string is a palindrome\n");
    }
    else{
        printf("The string isn't a palindrome\n");
    }

    return 0;

}

This code doesn't work, here's the output (with some more debug code to show what's happening)

(This is the version with the debug code implemented)

    char word[LEN], drow[LEN];
    printf("Insert a string: ");
    fgets(word, LEN + 1, stdin);

    strcpy(drow, word);
    strrev(word);

    puts(word);
    puts(drow);

    printf("strcmp=%d\n", strcmp(drow, word));

    if(strcmp(drow,word) == 0){
        printf("The string is a palindrome\n");
    }
    else{
        printf("The string isn't a palindrome\n");
    }

    return 0;

Insert a word: tacocat

tacocat //this is the "word" string
tacocat //this is the "drow" string

strcmp=1 //the return of strcmp
The string isn't a palindrome

Process returned 0 (0x0)   execution time : 4.589 s

But here's what happens when the fgets() at line 11 gets replaced by gets(word)

Insert a word: tacocat
tacocat
tacocat
strcmp=0
The string is a palindrome
Process returned 0 (0x0)   execution time : 3.897 s

I can't understand why gets() works, but fgets() doesn't.

I've tried replacing the max length of the string with sizeof, but it still doesn't.

santi
  • 29
  • 3
  • 1
    Did you try to check **what the content of the array is** (not just how it looks when interpreted as a string) after using each input method? For example, by iterating over each explicitly and printing the numeric values of the `char`s? (Hint: do you notice something different about the line spacing between the two outputs?) – Karl Knechtel Apr 15 '23 at 08:07
  • 2
    Try to explain the extra blank rows printed in the 'fgets()' version... Try printing the `strlen()` from both versions... Is this what you expect? Now, go read CAREFULLY the man page for `fgets()` and what the correct usage is... (You're risking scribbling out of bounds with the "LEN + 1" parameter...) – Fe2O3 Apr 15 '23 at 08:07
  • Does this answer your question? [Removing trailing newline character from fgets() input](https://stackoverflow.com/questions/2693776/removing-trailing-newline-character-from-fgets-input) – Karl Knechtel Apr 15 '23 at 08:07
  • 1
    `fgets(word, LEN + 1, stdin);` Why do you tell `fgets` to read more characters than you array can hold? – Gerhardh Apr 15 '23 at 08:21
  • [There is no such thing as `gets`](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf). – n. m. could be an AI Apr 15 '23 at 08:53
  • 1
    Instead of the dreaded `gets`, see if you can use the safer `gets_s`. – Steve Summit Apr 15 '23 at 11:42
  • @santi, Additional off-by-1 error : `fgets(word, LEN + 1, stdin)` --> `fgets(word, sizeof word, stdin)` or `fgets(word, LEN, stdin)`. – chux - Reinstate Monica Apr 15 '23 at 16:08

2 Answers2

2

fgets() does not strip newline which is part of the input (you had to press 'Enter' at the input prompt).

This is evident in your debug output by the presence of additional blank lines. You are comparing "tacocat\n" with "\ntacocat".

Rather than debugging by adding code (writing code to find bugs in code you wrote - what could possibly go wrong with that ;-) ), I strongly suggest you use a debugger. Inspecting these string arrays in a debugger would make the problem rather obvious. Also you might have noted the different semantics of gets() and fgets() in their respective documentation.

Clifford
  • 88,407
  • 13
  • 85
  • 165
  • 1
    @Fe2O3 yes that would be the inference from the spacing in the output. Also why I'd use a debugger so you need not have to spot the significance of the blank lines. Fixing. – Clifford Apr 15 '23 at 09:12
0

fgets will also read the newline char if the input buffer has space. Whereas gets doesn't. But gets has been removed from the C standard (since C11). So using it is not an option (it never was due to its inherent security flaw).

So use fgets but remove the newline character:

if (fgets(word, sizeof word, stdin)) {
    char *p = strchr(word, '\n');
    if (p) *p = '\0'; // Remove newline if present
} else {
    /* handle error */
}
P.P
  • 117,907
  • 20
  • 175
  • 238
  • Strictly gets() reads the newline and discards it. It is not left unread in the input buffer. Also removal from the standard does not make it magically disappear from an actual library implementation. So clearly it is an "option". It is _ill-advised_ for sure, and most toolchains will at least issue a warning or block it without setting an "allow-deprecated" macro or similar. I get the impression the OP knows that, since they are trying to implement it using fgets(). – Clifford Apr 15 '23 at 08:27
  • P.P, `fgets(word, LEN + 1, stdin)` perpetuates OP's off-by-1 error. Use `fgets(word, LEN, stdin)` or `fgets(word, sizeof word, stdin)`. – chux - Reinstate Monica Apr 15 '23 at 16:02