In the loop, add sub-loops such that while !isalnum(letter[count])
and !isalnum(letter[countback])
are true; increment count
and decrement countback
respectively. e.g.:
// skip non-alphanum on left
while( !isalnum(letter[count]) )
{
count++ ;
}
// skip non-alphanum on right
while( !isalnum(letter[countback]) )
{
countback-- ;
}
However doing that breaks your outer loop because you can no longer make the assumption that the centre of the string is the centre of the possible palindrome. It is better in any case to simply test that count > countback
. e.g:
for( int count = 0, countback = tag ;
count < countback;
++count, --countback )
and because you have then modified the control variables in the loop, you need to add a check in the "not palindrome" test, and you also want to ignore case:
if( count < countback &&
toupper(letter[count]) !=
toupper(letter[countback])
{
flag = FALSE ;
}
That test can in fact be simplified:
if( count < countback )
{
flag = (toupper(letter[count]) ==
toupper(letter[countback]) ;
}
To avoid undefined behaviour of the ctype.h functions, the letter
array should have type unsigned char
also.
That is the minimal "tweak" as you asked. More of a comment than part of the answer, but I would suggest some "style" improvements too on structure, commenting, naming, scope and I/O; my re-implementation of your code for what it is worth :
// Test for a palindrome
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
int main()
{
bool terminate = false ;
while( !terminate )
{
// read in the text
unsigned char text[80] ;
printf("\nPlease enter a word, phrase, or sentence below:\n");
fgets( text, sizeof(text), stdin ) ;
int text_length = strlen(text) ;
if( text[text_length-1] == '\n')
{
text_length-- ;
text[text_length] = 0 ;
}
// test for end of program keyword END
terminate = text_length == 3 &&
toupper(text[0]) == 'E' &&
toupper(text[1]) == 'N' &&
toupper(text[2]) == 'D' ;
if( !terminate )
{
// Test for not palindrome
bool is_palindrome = true ;
for( int count = 0, countback = text_length - 1 ;
is_palindrome && count < countback;
count++, countback-- )
{
// skip non-alphanum on left
while( count < countback &&
!isalnum(text[count]) )
{
count++ ;
}
// skip non-alphanum on right
while( count_back > count &&
!isalnum(text[countback]) )
{
countback-- ;
}
// If not at or past middle...
if( count < countback )
{
// Test for left/right match
is_palindrome = (toupper(text[count]) ==
toupper(text[countback])) ;
}
}
// Output test and test result.
printf( "%s --> %s a Palindrome!\n\n",
text,
(is_palindrome ? "IS" : "IS NOT") ) ;
}
}
return 0;
}
This also allows strings such as "end Ådne"
and "end of the world"
to be tested without terminating as yours would.
Further it is always a good idea to separate processing from I/O. To that end you might create a function:
bool isPalindrome( const char* str )
{
const unsigned char* text = (const unsigned char*)str ;
size_t text_length = strlen(str) ;
if( text_length == 0u ) return true ;
// Test for not palindrome
bool is_palindrome = true ;
for( size_t count = 0, countback = text_length - 1;
is_palindrome && count < countback;
count++, countback-- )
{
// skip non-alphanum on left
while( count < countback &&
!isalnum(text[count]) )
{
count++ ;
}
// skip non-alphanum on right
while( countback > count &&
!isalnum(text[countback]) )
{
countback-- ;
}
// If not at or past middle...
if( count < countback )
{
// Test for left/right match
is_palindrome = (toupper(text[count]) ==
toupper(text[countback])) ;
}
}
return( is_palindrome ) ;
}
then in the main body you would simply have:
bool is_palindrome = isPalindrome( text ) ;
printf("%s --> %s a Palindrome!\n\n", text, (is_palindrome ? "IS" : "IS NOT"));
or even:
printf( "%s --> %s a Palindrome!\n\n", text,
(isPalindrome( text ) ? "IS" : "IS NOT") ) ;