1

我是 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);
        }
    }
}

不知道如何完成这段代码..我会感谢任何建议!

4

6 回答 6

1

输出数组不能长于两个输入数组中较短的一个。您可以使用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( Nx M) 性能,其中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;
}
于 2013-05-29T15:25:28.763 回答
0

我会做这样的事情:

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了,希望这是正确的

于 2013-05-29T14:44:57.933 回答
0

很抱歉奇怪地使用了 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.
}
于 2013-05-29T15:00:56.033 回答
0

您可以使用 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;
}
于 2013-05-29T15:04:43.810 回答
0
#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;
}
于 2013-05-29T22:40:32.680 回答
0

所以我找到了解决我的问题的方法。最终我使用了另一种算法,结果证明它与@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;

}
于 2013-05-30T20:57:26.210 回答