wolffsen
wolffsen

Reputation: 11

Deleting isalpha out of function, causes it to return 0 all the time

I have to write a function to check for palindromes in sentences and words.

For sentences it looks like this (and works):

int checkSentencepalindrome(char * str)
{
    size_t len = strlen(str);
    
    char *pntr1 = str;
    char *pntr2 = str + len - 1;
    
    while(pntr2 >= pntr1)
    {
        if (!isalpha(*pntr2))
        {
            pntr2--;
            continue;
        }
        
        if (!isalpha(*pntr1))
        {
            pntr1++;
            continue;
        }
        
        if(tolower(*pntr1) != tolower(*pntr2))
        {
            return 0;
        }
        
        pntr1++;
        pntr2--;
    }
    return 1;
}

for word palindromes it looks like this:

int checkWordpalindrome(char * str)
{
    size_t len = strlen(str);
    
    char *pntr1 = str;
    char *pntr2 = str + len - 1;
    
    while(pntr2 >= pntr1)
    {
        if(tolower(*pntr1) != tolower(*pntr2))
        {
            return 0;
        }
        
        pntr1++;
        pntr2--;
    }
    return 1;
}

However, the function for word palindromes returns me 0 all the time. (I expect a 1 for palindrome and 0 for non-palindrome words)

I thought the if statements I deleted are just there to skip spaces, exclamation marks, etc. (everything not included in the alphabet) Why are they so crucial for my function to work properly then?

How can I solve this while using pointers only?

EDIT: The issue only occurs when passing the string as following:

int checkWpalindrome(char * str)
{
    printf("%s ", str);
    
    size_t len = strlen(str);
    
    if(len == 0)
    {
        return 0;
    }

    char *pntr1 = str;
    char *pntr2 = str + len - 1;
    
    while(pntr2 >= pntr1)
    {
        if(tolower(*pntr1) != tolower(*pntr2))
        {
            return 0;
        }
        
        pntr1++;
        pntr2--;
    }
    return 1;
}

void input(char * str)
{
    printf("Input: ");
    fgets(str, 101, stdin);
    fflush(stdin);
}

int main()
{
    char arr[10];
    
    input(arr);
    
    printf("%d", checkWpalindrome(arr));
    
    return 0;
}

Upvotes: 1

Views: 46

Answers (1)

chux
chux

Reputation: 154243

  • fgets() includes reading and saving a '\n' and causes checkWordpalindrome() to return 0 (unless maybe only "\n" was read). @Adrian Mole.

  • To lop off the potential '\n', use str[strcspn(str, "\n")] = 0; right after fgets().

  • Both functions risk undefined behavior (UB) as they can attempt to generate a pointer to before str. Consider check...("?").

  • In checkSentencepalindrome() the UB is is more so as code then attempts *pntr2 of an invalid pointer.

  • isalpha(ch) and tolower(ch) have (UB) when ch < 0 (and not EOF)

  • Calling code buffer too small: char arr[10]; ... fgets(str, 101, stdin);. Make them the same size like char arr[101]; ... fgets(str, 101, stdin);

  • fflush(stdin); is UB and not needed. @Adrian Mole

Repaired code:

int checkSentencepalindrome(const char * str) {
  size_t len = strlen(str);
    
  const unsigned char *left = (const unsigned char *) str;
  const unsigned char *right = left + len; // point one-past
    
  while(left < right) {
    if (!isalpha(right[-1])) {
      right--;
      continue;
    }
        
    if (!isalpha(left[0])) {
      left++;
      continue;
    }
        
    right--;
    if (tolower(left[0]) != tolower(right[0])) {
      return 0;
    }
    left++;
  }

  return 1;
}

A bit tidier with

  while(left < right) {
    if (!isalpha(*left)) {
      left++;
      continue;
    }

    right--;
    if (!isalpha(*right)) {
      continue;
    }
        
    if (tolower(*left) != tolower(*right)) {
      return 0;
    }
    left++;
  }

Upvotes: 0

Related Questions