【问题标题】:Removing punctuation and white space from a string in c?从c中的字符串中删除标点符号和空格?
【发布时间】:2013-03-23 16:49:09
【问题描述】:

这是学校的家庭作业。我不是要求正确的答案,只是朝着正确的方向前进。关于为什么会出错的解释以及对正确方法的解释会很好。这个 C 程序应该做的是在没有空格和标点符号的情况下读取用户输入并将其分配给字符数组字符串。然后应该将该数组传递给函数回文。回文应该是字符串的长度,如果等于 1 或 0,则返回 TRUE 或 1,否则继续检查字符串的第一个和最后一个字符。如果它们匹配,则检索倒数第二个和第二个字符,以及它们之间的所有字符,并将其传递给函数 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;

   }
}

不管它总是输出什么输入,给出的字符串不是回文。例如当我输入

他活得像个魔鬼,嗯?

打印出来

不是回文

当我编辑程序以使用先前的输入检查数组字符串中的内容时,它是

他活得像个魔鬼,嗯?

如果您看到代码使用改进,请随时评论我的代码的任何其他方面。他们真的不提供任何东西,除了“是”它是正确的或“不是”它与我们的代码无关。

编辑:
我确实检查了 char 数组 string 中的值是什么。我在最后一个引用之前说这个。

【问题讨论】:

  • 提示:在将经过清理的字符串传递给 palindrome() 之前,请将其打印出来。然后你就会知道你是否得到了正确的消毒。
  • if (!isspace(ch) &amp;&amp; !ispunct(ch)) 或更好:if (isletter(ch))
  • @user 我想你的问题已经回答了:meta.stackexchange.com/questions/5234

标签: c arrays string input getchar


【解决方案1】:
if(isspace(ch)==FALSE || ispunct(ch)==FALSE);

这是你的错误。首先,结尾不应有分号 (;)。

其次,您不应该使用 OR,而应该使用 AND,因为您要确保过滤除字母表之外的所有内容:

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

还有:

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

这里的布尔表达式是错误的。你应该评估j

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

最后,在将字符附加到新字符串时,i++ 语句的定位不正确。将其留空,以便编译器知道它需要成为 while 循环体的一部分,并且位于 if 块之外。

【讨论】:

    【解决方案2】:

    看看这里...

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

    注意';'在 if 语句的末尾。那 ';'导致 string[i] = tolower(ch) 始终执行。另外,您的逻辑不正确,如果字符不是空格并且不是标点符号,您希望代码执行。

    此外,请注意缩进。 i++ 也应该在 if 语句中,但是它周围没有大括号。因此,即使您确实删除了 ';',i++ 仍将始终执行。所以...

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

    或者……甚至更好……

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

    样式注释也是如此……为了维护和可读性,从函数中设置一个退出点通常是个好主意。其他人可能会有不同的看法,但这是我过去 30 年从事国防部工作所遵循的硬性规定。看看这个可读性,看看它是否对你更有意义。

    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;
    }
    

    最后...从效率的角度来看,您可以轻松地对其进行索引,而不是复制字符串...

    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中的逻辑错误,回文函数太复杂了。
    • 所以现在我们已经告诉你如何修复 if,你已经做到了。做得好。但是您的 palindrome 函数根本不起作用。对于我的一生,我无法理解为什么这个答案得到了赞成。
    【解决方案3】:

    一些明显的观点:

    • 问题中的代码无法编译。
    • 您的主要声明不标准。
    • if 语句的行尾有一个错误的分号。
    • if 语句中的逻辑不正确。逻辑或测试将始终评估为真,因为字符不能同时是空格和标点符号。
    • 您的回文检查功能远比它需要的复杂。

    要进行的关键更改是您的if 语句应该是这样的:

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

    一个完整的工作程序如下所示:

    #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;
    }
    

    这是输出:

    输入一条消息:他像魔鬼一样生活,嗯? 字符串 = helivedasadevileh 回文

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-08
    • 2011-08-16
    • 2021-01-27
    • 1970-01-01
    • 1970-01-01
    • 2017-08-21
    相关资源
    最近更新 更多