简体   繁体   中英

Removing punctuation and white space from a string in c?

This is for homework at school. I'm not asking for correct answers just a push in the right direction. An explanation as to why this is going wrong would be great as well as an explanation of the correct method. What this C program should be doing is reading in the user input without spaces and punctuation and assigning it to the character array string. This array should then be passed into the function palindrome. Palindrome should length of the string and if equal to either 1 or 0 return TRUE or 1 else move on and check the first and last character of the string. If they match retrieve the 2nd and 2nd to last characters, and all the characters in between, and pass that into the function palindrome.

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

#define TRUE 1
#define FALSE 0
typedef int Bool;

Bool palindrome(char str[]);
main()
{
char string[1000], ch;
int i = 0;

printf("Enter a message: ");
while((ch = getchar()) != '\n'){
  if(isspace(ch)==FALSE || ispunct(ch)==FALSE);
    string[i] = tolower(ch);
    i++;
}

string[i] = '\0';

printf("\n");
if(palindrome(string))
  printf("Palindrome\n");
else
  printf("Not a palindrome\n);

return 0;
}

Bool palindrome(char str[])
{
   int length = strlen(str);
   if((length == 1) || (length == 0))
     return TRUE;
   else
   {
     if((str[0] == str[length - 1])
       {
         char str_new[length-1];
         int i, j;
         for(i = 1, j = 0; str[i]!=str[length-1]; i++, j++)
           str_new[j] = str[i];

         str_new[i] = '\0';
         palindrome(str_new);
       }
       else
         return FALSE;

   }
}

Not matter what the input it always prints that the string given was a not a palindrome. For instance when I input

He lived as a devil, eh?

it prints out

Not a palindrome

Also when I edited the program to check what was in the array string using the previous input it was

He lived as a devil, eh?

Feel free to comment on any other aspects of my code that you see code use improvement. They really don't provide anything other than a yes its right or a no it isn't concerning our code.

EDIT:
I did check to see what the value in the char array, string, was. I say this before the last blockquote.

Have a look here...

while((ch = getchar()) != '\n'){
  if(isspace(ch)==FALSE || ispunct(ch)==FALSE);
    string[i] = tolower(ch);
    i++;
}

Note the ';' at the end of the if statement. That ';' is causing the string[i] = tolower(ch) to always execute. In addition, your logic is incorrect, you want to the code to execute if the character is not white space AND it is not punctuation.

In addition, watch your indentation. The i++ should be inside the if statement, as well, but it is lacking braces around it. So, even if you did remove the ';', the i++ would still always execute. So...

while((ch = getchar()) != '\n'){
  if(isspace(ch)==FALSE && ispunct(ch)==FALSE)
  {
    string[i] = tolower(ch);
    i++;
  }
}

Or... even better still...

while((ch = getchar()) != '\n'){
  if(isspace(ch)==FALSE && ispunct(ch)==FALSE)
    string[i++] = tolower(ch);
}

A style comment as well... it's often a good idea to have a single exit point from functions for the sake of maintenance and readability. Others may argue differently there, but that's been the hard and fast rule I've lived for the past 30 years doing DoD work. Have a look at this for readability and see if it makes more sense to you.

Bool palindrome(char str[])
{
   Bool result = TRUE;
   int length = strlen(str);

   if( length > 1 && str[0] == str[length-1] )
   {
     char str_new[length-1];
     int i, j;

     for(i = 1, j = 0; str[i]!=str[length-1]; i++, j++)
        str_new[j] = str[i];

     str_new[i] = '\0';
     result = palindrome(str_new);
   }

   return result;
}

Lastly... from an efficiency point of view, rather than copy the string, you could just as easily index into it...

Bool palindrome(char str[])
{
    Bool result = TRUE;
    int length = strlen(str);

    if( length > 1 && str[0] == str[length-1] )
    {
       str[length-1] = '\0';
       result = palindrome(&str[1]);
    }

    return result;
}
if(isspace(ch)==FALSE || ispunct(ch)==FALSE);

This is your mistake. First, there shouldn't be a semicolon ( ; ) at the end.

Second, you shouldn't be using OR, you should be using AND because you want to make sure that you're filtering everything except for alphabet:

if(isspace(ch)==FALSE && ispunct(ch)==FALSE)

Also:

for(i = 1, j = 0; str[i]!=str[length-1]; i++, j++)

Here, the boolean expression is wrong. You should be evaluating j :

for(i = 1, j = 0; j < length - 1; i++, j++)

Finally, your positioning of the i++ statement while you're appending characters to your new string is incorrect. Space it back so the compiler knows it needs to be part of the body of the while loop and outside the if block.

Some obvious points:

  • The code in the question doesn't compile.
  • Your main declaration is not standard.
  • The if statement has an erroneous semi-colon at the end of the line.
  • The logic in your if statement is incorrect. The logical or test will always evaluate to true since a character can't be both space and punctuation.
  • Your palindrome checking function is far more complex than it needs to be.

The key change to make is that your if statement should be like so:

if (!isspace(ch) && !ispunct(ch))

A complete working program looks like this:

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

#define TRUE 1
#define FALSE 0
typedef int Bool;

Bool palindrome(char str[]);

int main(void)
{
    char string[1000], ch;
    int i = 0;

    printf("Enter a message: ");
    while((ch = getchar()) != '\n'){
        if (!isspace(ch) && !ispunct(ch))
        {
            string[i] = tolower(ch);
            i++;
        }
    }

    string[i] = '\0';
    printf("string = %s\n", string);
    if(palindrome(string))
        printf("Palindrome\n");
    else
        printf("Not a palindrome\n");

    return 0;
}

Bool palindrome(char str[])
{
   int left = 0;
   int right = strlen(str)-1;
   while (left<right)
   {
       if(str[left] != str[right])
           return FALSE;
       left++;
       right--;
   }
   return TRUE;
}

Here is the output:

Enter a message: He lived as a devil, eh?
string = helivedasadevileh
Palindrome

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM