The problem is you are not handling the strings properly. You should overwrite the '\n'
with \0
.
...
char input[100];
char reverse[100];
int numLen = 0;
printf("Enter a number\n");
fgets(input, 100, stdin);
printf("The number is: %s\n", input);
input[strcspn(input,"\n")]='\0'; // getting the length of the
// string without `\n`
// and overwriting with `\0`
numLen = strlen(input) ; // now you don't need to put the -1
printf("Length of string is: %d\n", numLen);
for (int i = 0; i < numLen; i++)
{
....
Apart from these two changes everything else remains the same. You were reversing it all right. And then you used strcmp
right way. But the extra \n
is removed in the code I have shown.
(still) Why it works?
Now to give you a better idea. You formed the reversed string alright. But the original string has \n
within itself.
printf("The reverse number is: (%s)\n", reverse);
printf("The original number is: (%s)\n", input);
In the previous program you just do write these two lines. You will understand where you went wrong.
On giving input 1001
Enter it gives this output.
The reverse number is: (1001)
The original number is: (1001
)
What is strcspn
doing?
I have using strcspn
function got the length without \n
and overwriting it with \0
.
0 1 2 3 4 5 --> indices
1 0 0 1 \n \0 --> strcspn(input,"\n") returns 4.
1 0 0 1 \0 \0 --> input[strcspn(input,"\n")]='\0'
You can do simply like this without the copying and everything.
Without extra memory - in place palindrome checking
bool checkPal(const char *s){
for(int i = 0, j= strlen(s)-1; i< strlen(s) && j>=0 ; i++)
if(s[i] != s[j])
return false;
return true;
}
int main(void)
{
char input[100];
char reverse[100];
printf("Enter a number\n");
if( fgets(input, 100, stdin) )
printf("The number is: %s\n", input);
input[strcspn(input,"\n")]='\0';
int numLen = strlen(input) ;
printf("Length of string is: %d \n", numLen);
printf("These numbers are %spalindromes\n", checkPal(input)?"not ":"");
return 0;
}
A more succinct way to write the checkPal()
would be,
bool checkPal(const char *first){
const char *last = first + strlen(first);
while (first < last) {
if (*first++ != *--last) {
return false;
}
}
return true;
}
last
points to the \0
character. Subtraction is necessary before we start doing comparison. To get a clear idea of what happens you have to know the precedence and few rules.
The first<last
part is obvious. We are comparing till we reach a point where we first > last
(For even length strings) or first = last
(for odd length strings).
The if
is a bit tricky. *first++
there are two operators involved. *
(indirection) and ++
(post increment).
And precedence of ++
is higher than de-reference *
.
So *first++
will be - first is incremented. Then you might think that we are missing one character very first time but that's not the case. Value of a postfix expression is the value before we do first++
. So now you have the first character.
Same way *--last
will have the same effect except the value of the prefix expression is the value after the operation. So you are considering the last character.
If they matches we continue. first
and last
already contain the modified value. We repeat the same logic for rest of the characters in the smaller sub-string.
If a mismatch occurs then we return immediately. (Because it's not a palindrome).