【问题标题】:Create a new string that will consist of common letters from other two strings创建一个新字符串,该字符串由其他两个字符串中的常用字母组成
【发布时间】:2013-05-24 21:25:41
【问题描述】:

我是 C 编程新手。我有一个任务要做。 用户输入两个字符串。我需要做的是创建一个仅由这两个给定字符串的常用字母组成的新字符串。 例如: 如果给出:

str1 = "ABCDZ"
str2 = "ADXYZ"

新字符串将如下所示:"ADZ"。 我不能让它工作。我认为必须有一个更好(更简单)的算法,但是我已经为此花费了太多时间,所以我想完成它..需要你的帮助!

到目前为止我所做的是:

char* commonChars (char* str1, char* str2)
{
    char *ptr, *qtr, *arr, *tmp, *ch1, *ch2;
    int counter = 1;
    ch1 = str1;
    ch2 = str2;
    arr = (char*) malloc ((strlen(str1)+strlen(str2)+1)*(sizeof(char))); //creating dynamic array
    strcpy(arr, str1);
    strcat(arr,str2);
    for (ptr = arr; ptr < arr + strlen(arr); ptr++)
    {
        for (qtr = arr; qtr < arr + strlen(arr); qtr++) // count for each char how many times is appears
        {
            if (*qtr == *ptr && qtr != ptr)
            {
                counter++;
                tmp = qtr;
            }
        }
        if (counter > 1)
        {
            for (qtr = tmp; *qtr; qtr++) //removing duplicate characters
                *(qtr) = *(qtr+1);
        }
        counter = 1;
    }
    sortArray(arr, strlen(arr)); // sorting the string in alphabetical order
    qtr = arr;
    for (ptr = arr; ptr < arr + strlen(arr); ptr++, ch1++, ch2++) //checking if a letter appears in both strings and if at least one of them doesn't contain this letter -  remove it
    {
        for (qtr = ptr; *qtr; qtr++)
        {
            if (*qtr != *ch1 || *qtr != *ch2)
                *qtr = *(qtr+1);
        }
    }
}

不知道如何完成此代码.. 如有任何建议,我将不胜感激!

【问题讨论】:

  • 我注意到你的例子中的字母是按顺序出现的。示例:显然“ADZ”->“AZ”=“AZ”。但 "ZDA" -> "AZ" 可能是 "AZ" "ZA" 或 ""
  • 如果一个字母重复 2 次,输出会是什么?例如str1 = "AABCDZ"str2 = "ADXYZ"
  • 是否考虑大写和小写?以下字符串示例 str1 = "ABCDZ"str2 = "adxyz" 的输出可能是什么?
  • 你可以使用strchr()它让你的算法更容易

标签: c string letters


【解决方案1】:

所以我找到了解决问题的方法。最终我使用了另一种算法,结果证明它与@BLUEPIXY 和@user315052 所建议的非常相似。感谢所有试图提供帮助的人!非常好用的网络资源!

这是我的代码。觉得它有用的人可以使用它。 笔记: (1) str1 & str2 应按字母顺序排序; (2) 每个字符在每个给定的字符串中只能出现一次;

char* commonChars (char* str1, char* str2)
{
    char *ptr, *arr,*ch1, *ch2;
    int counter = 0;
    for (ch1 = str1; *ch1; ch1++)
    {
        for(ch2 = str2; *ch2; ch2++)
        {
            if (*ch1 == *ch2)
                counter++;
        }
    }
    arr =  (char*)malloc ((counter+1) * sizeof(char));
    ch1 = str1;
    ch2 = str2;
    ptr = arr;
    for (ch1 = str1; *ch1; ch1++,ch2++)
    {
    while (*ch1 < *ch2)
    {
        ch1++;
    }
    while (*ch1 > *ch2)
    {
        ch2++;
    }
    if (*ch1 == *ch2)
    {
        *ptr = *ch1;
        ptr++;
    }
    }
    if (ptr = arr + counter)
        *ptr = '\0';
    return arr;

}

【讨论】:

    【解决方案2】:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define min(x,y) ((x)<(y)? (x) : (y))
    
    char* commonChars (const char *str1, const char *str2){
        //str1, str2 : sorted(asc) and unique
        char *ret, *p;
        int len1, len2;
        len1=strlen(str1);
        len2=strlen(str2);
        ret = p = malloc((min(len1, len2)+1)*sizeof(char));
    
        while(*str1 && *str2){
            if(*str1 < *str2){
                ++str1;
                continue;
            }
            if(*str1 > *str2){
                ++str2;
                continue;
            }
            *p++ = *str1++;
            ++str2;
        }
        *p ='\0';
    
        return ret;
    }
    
    char *deleteChars(const char *str, const char *dellist){
        //str, dellist : sorted(asc) and unique
        char *ret, *p;
        ret = p = malloc((strlen(str)+1)*sizeof(char));
    
        while(*str && *dellist){
            if(*str < *dellist){
                *p++=*str++;
                continue;
            }
            if(*str > *dellist){
                ++dellist;
                continue;
            }
            ++str;
            ++dellist;
        }
        if(!*dellist)
            while(*str)
                *p++=*str++;
        *p ='\0';
    
        return ret;
    }
    
    int main(void){
        const char *str1 = "ABCDXYZ";
        const char *str2 = "ABCDZ";
        const char *str3 = "ADXYZ";
        char *common2and3;
        char *withoutcommon;
    
        common2and3 = commonChars(str2, str3);
        //printf("%s\n", common2and3);//ADZ
        withoutcommon = deleteChars(str1, common2and3);
        printf("%s\n", withoutcommon);//BCXY
    
        free(common2and3);
        free(withoutcommon);
        return 0;
    }
    

    【讨论】:

      【解决方案3】:

      输出数组不能长于两个输入数组中较短的一个。 你可以使用strchr()

      char * common (const char *in1, const char *in2) {
          char *out;
          char *p;
      
          if (strlen(in2) < strlen(in1)) {
              const char *t = in2;
              in2 = in1;
              in1 = t;
          }
      
          out = malloc(strlen(in2)+1);
          p = out;
          while (*in1) {
              if (strchr(in2, *in1)) *p++ = *in1;
              ++in1;
          }
          *p = '\0';
          return out;
      }
      

      这具有 O(NxM) 性能,其中 NM 是输入字符串的长度。由于您的输入是按字母顺序排列且唯一的,因此您可以获得 O(N+M) 最坏情况下的性能。您应用类似于合并循环的东西。

      char * common_linear (const char *in1, const char *in2) {
          char *out;
          char *p;
      
          if (strlen(in2) < strlen(in1)) {
              const char *t = in2;
              in2 = in1;
              in1 = t;
          }
      
          out = malloc(strlen(in2)+1);
          p = out;
          while (*in1 && *in2) {
              if (*in1 < *in2) {
                  ++in1;
                  continue;
              }
              if (*in2 < *in1) {
                  ++in2;
                  continue;
              }
              *p++ = *in1;
              ++in1;
              ++in2;
          }
          *p = '\0';
          return out;
      }
      

      【讨论】:

      • 感谢您的回复,但我对您提供的第一个和第二个示例都没有完全理解。我只需要算法来解决这个问题:我有字符串:str1 = "ABCDXYZ"。我还有这两个字符串:str2 = ABCDZ 和 str3 = ADXYZ。我想从“ABCDXYZ”中删除 str2 和 str3 中都没有出现的每个字母,以便 str1 看起来像这样:“ADZ”而不使用 strchr 函数。
      • 您在评论中描述的不是您在问题中描述的,也与您的commonChars() 函数的输入不匹配。您只提供 2 个输入,而不是 3 个。您能否说明我的第二个功能无法满足您的要求?
      【解决方案4】:

      对于 char 数组的奇怪使用感到抱歉,我只是想快速完成它。算法背后的想法应该很明显,您可以根据自己的目的修改一些类型、循环结束条件、删除 C++ 元素等。重要的是代码背后的想法。

      #include <queue>
      #include <string>
      #include <iostream>
      using namespace std;
      
      
      bool isCharPresent(char* str, char c) {
          do {
              if(c == *str) return true;
          } while(*(str++));
      
          return false;
      }
      
      int main ()
      {
          char str1[] = {'h', 'i', 't', 'h', 'e', 'r', 'e', '\0'};
          char str2[] = {'a', 'h', 'i', '\0'};
          string result = "";
      
          char* charIt = &str1[0];
      
          do {
              if(isCharPresent(str2, *charIt))
                  result += *charIt;
          } while(*(charIt++));
      
      
          cout << result << endl; //hih is the result.  Minor modifications if dupes are bad.
      }
      

      【讨论】:

        【解决方案5】:

        您可以使用 strpbrk() 函数,干净地完成这项工作。

        const char * strpbrk ( const char * str1, const char * str2 );
        char * strpbrk (       char * str1, const char * str2 );
        

        在字符串中定位字符 返回指向 str1 中第一次出现的作为 str2 一部分的任何字符的指针,如果没有匹配则返回空指针。

        搜索不包括任何一个字符串的终止空字符,而是在那里结束。

        #include <stdio.h>
        #include <string.h>
        
        int main ()
        {
          char str[] = "ABCDZ";
          char key[] = "ADXYZ";
        
          char *newString = malloc(sizeof(str)+sizeof(key));
          memset(newString, 0x00, sizeof(newString));
        
          char * pch;
          pch = strpbrk (str, key);
        
          int i=0;
          while (pch != NULL)
          {
             *(newString+i) = *pch;
             pch = strpbrk (pch+1,key);
             i++;
          }
        
          printf ("%s", newString);
          return 0;
        }
        

        【讨论】:

          【解决方案6】:

          我会做这样的事情:

          char*   commonChars(char* str1, char* str2) {
             char*  ret = malloc(strlen(str1) * sizeof(char));
             int    i = j = k = 0;
          
             for (; str1[i] != '\n'; i++, j++) {
                 if (str1[i] == str2[j]) {
                    ret[k] = str1[i];
                    k++;
                 }
              }
            ret[k] = '\0';
            ret = realloc(ret, k);
            return ret;
          }
          

          很久没学C了,希望是对的

          【讨论】:

          • 本练习中禁止我使用 realloc 函数:/ 但是谢谢。
          猜你喜欢
          • 2014-02-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-07-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多