【问题标题】:Deleting a char and moving it in a string删除一个字符并将其移动到一个字符串中
【发布时间】:2019-06-26 21:17:59
【问题描述】:

我需要一个递归代码的想法,它可以删除字符串中的特定字符,并将所有其他字符串字符一起移动

例如:

“天气多云”

输入的字符是'e':

结果:

“多云”

我真的不知道如何开始,谢谢你的帮助。

【问题讨论】:

    标签: c string recursion


    【解决方案1】:
    
    #include <stdio.h>
    
    /**
    * Returns the number of removed chars.
    * Base case: if the current char is the null char (end of the string)
    * If the char should be deleted return 1 + no of chars removed in the remaining string.
    * If it's a some other char simply return the number of chars removed in the remaining string
    */
    int  removeCAfterwardsAndCount(char* s,char c){
      if((*s) == '\0'){
          return 0;
      }
    
      if((*s) == c){
         int noOfChars = removeCAfterwardsAndCount(s+1,c);// s+1 means the remaining string
          s[noOfChars] = *s; // move the current char (*s) noOfChars locations ahead
    
        return  noOfChars +1; // means this char is removed... some other char should be copied here...
    
      }
      else{
          int noOfChars  = removeCAfterwardsAndCount(s+1,c);
          s[noOfChars ] = *s;
        return  noOfChars ; // means this char is intact ... 
      }
    
    }
    
    int main()
    {
    
        char s[] = "Arifullah Jan";
        printf("\n%s",s);
        int totalRemoved = removeCAfterwardsAndCount(s,'a');
        char *newS = &s[totalRemoved]; // the start of the string should now be originalPointer + total Number of chars removed
    
        printf("\n%s",newS);
    
        return 0;
    }
    

    Test Code Here

    为了避免使用循环移动字符。我只是向前移动字符,这会在字符串的开头创建空白空间。 newS 指针只是同一字符串的新指针,用于消除空/垃圾字符串。

    【讨论】:

      【解决方案2】:

      这可以通过多种方式完成。我现在在想的是存储not Allowed char 数组,它将过滤哪些字符应该显示或不显示。像下面这样的..

      #include <stdio.h>
      #include <string.h>
      
      // Global Scope variable declaration
      int notAllowedChar[128] = {0}; // 0 for allowed , 1 for not allowed
      char inputString[100];
      
      
      void recursion(int pos, int len) {
      
          if( pos >= len ) {
             printf("\n"); // new line
             return;
          }
      
          if( notAllowedChar[inputString[pos]]) {// not printing
             recursion( pos + 1 , len );
          }
          else {
             printf("%c", inputString[pos]);
             recursion( pos + 1 , len );
          }
      
      }
      
      int main() {
      
       gets(inputString);  // taking input String
      
          printf("Enter not allowed chars:: "); // here we can even run a loop for all of them
          char notAllowed;
          scanf("%c", &notAllowed);
          notAllowedChar[notAllowed] = 1;
          int len = strlen(inputString);
          recursion( 0 , len );
      
      }
      

      这是如何工作的

      假设我们有一个简单的字符串“Hello world” 我们希望 l 应该从最终字符串中删除,所以最终输出将是“Heo word”

      这里的“Hello world”长度为 11 个字符 在调用递归函数之前,我们确保 'l' 索引是 108 个 ascii 值 link 1 在 notAllowedChar 数组中。

      现在我们使用 (0, 11) 值调用递归方法,在递归方法中,我们主要有 2 个逻辑 if 操作,第一个是 base case,当 pos 等于或大于时我们将终止递归调用11. 如果它不是真的,如果current char 是否可打印,我们将执行第二个逻辑操作。这只是检查此字符在notAllowedChar 列表中的位置。每次我们增加 pos value + 1 并进行递归调用,最后当 pos 等于或大于 11 时,这意味着我们已经决定是否打印 char 我们的递归将终止。我尝试用有意义的名称分配变量。如果您仍然不明白这项工作是如何工作的,您应该使用简单的递归模拟基础(在 youtube 中搜索),并且您应该尝试手动调试 recursion local scope 中的值如何变化。这可能需要时间,但值得理解。一切顺利。

      【讨论】:

      • 您现在可以查看。我只是想展示如何更早完成的主要想法。
      • @RafaelElkoby 如果您认为这个答案足够好,请您接受它作为正确答案。否则人们可能会误导问题的现状。
      【解决方案3】:

      轮到我提出建议了!我添加了一个断言测试并使用现有函数(strchr 和 strcpy)。

      #include <string.h>
      #include <stdio.h>
      #include <assert.h>
      
      int removeChar(char *str, char chr)
      {
          assert(str != 0);                   // Always control entry !
          char *str_pnt = strchr(str, chr);   
      
          if (str_pnt) {
              strcpy(str_pnt, str_pnt+1); 
              removeChar(str_pnt, chr);
          }
      }
      
      void main (void)
      {
          char str[] = "the weather is cloudy";
          char char_to_delete = 'e';
      
          removeChar(str, char_to_delete);
          puts(str);
      }
      

      【讨论】:

        【解决方案4】:
        #include <stdio.h>
        #include <string.h>
        
        char *remove_char(char *str, int c)
        {
            char *pos;
            char *wrk = str;
            while((pos = strchr(wrk, c)))
            {
                strcpy(pos, pos + 1);
                wrk = pos;
            }
            return str;
        }
        
        int main()
        {
            char str[] = "Hello World";
            printf(remove_char(str, 'l'));
        
            return 0;
        }
        

        或更快但模式难以理解的版本:

        char *remove_char(char *str, int c)
        {
            char *pos = str;
            char *wrk = str;
            while(*wrk)
            {
                if(*wrk == c)
                {
                    *wrk++;
                    continue;
                }
                *pos++ = *wrk++;
            }
            *pos = 0;
            return str;
        }
        

        两者都要求字符串是可写的(例如,你不能将指针传递给字符串字面量)

        【讨论】:

          【解决方案5】:
          #include <stdio.h>
          
          void remove_impl(char* s, char c, char* d) {
              if (*s != c) {
                  *d++ = *s;
              }
              if (*s != '\0') {
                  remove_impl(++s, c, d);
              }
          }
          
          void remove(char* s, char c) {
              remove_impl(s, c, s);
          }
          
          int main() {
              char s[] = "the weather is cloudy";
              remove(s, 'e');
              puts(s);
          }
          

          它是如何工作的?考虑remove_impls是原始字符串,c是要从s中删除的字符,d是结果字符串,其中写入了s,不等于c的字符。递归遍历s 的字符。如果下一个字符不等于c,则写入d。递归停止点是检查是否到达s 结尾的条件。由于需要修改源字符串,所以实现了包装器(remove),其中作为d,传递原始字符串(s)。

          【讨论】:

            【解决方案6】:

            一个简单的方法是遍历字符串并添加任何与不需要的字母不匹配的字母。

            这是一个演示:

            char *source = "the weather is cloudy";
            int source_len = strlen(source);
            
            char *target = (char *)calloc(source_len, sizeof(char));
            int target_len = 0;
            
            char to_remove = 'e';
            
            for(int i = 0; i < source_len; i++)
            {
                if(source[i] != to_remove)
                {
                    target[target_len++] = source[i];
                }
            }
            
            puts(target); // Output "th wathr is cloudy" in the console
            

            【讨论】:

              【解决方案7】:
              #include <stdio.h>
              
              void RemoveChar(char* str, char chr) {
              char *str_old = str;
              char *str_new = str;
              
              while (*str_old)
              {
                  *str_new = *str_old++;
                  str_new += (*str_new != chr);
              }
              
              *str_new = '\0'; }
              
              int main() {
              char string[] = "the weather is cloudy";
              
              RemoveChar(string, 'e');
              
              printf("'%s'\n", string);
              
              return 0; }
              

              【讨论】:

              • 即使我读了它也很糟糕,在我看来,我以为你说的只是删除所有出现的字符
              猜你喜欢
              • 1970-01-01
              • 2012-11-27
              • 2016-08-16
              • 1970-01-01
              • 1970-01-01
              • 2023-03-14
              • 1970-01-01
              • 2023-01-28
              相关资源
              最近更新 更多