【问题标题】:Find common character in a string查找字符串中的共同字符
【发布时间】:2017-10-06 08:10:48
【问题描述】:

嗨,我有两个不同的字符串,我需要在字符串中找到共同的字符。我设法获得了公共字符串,但我需要为不具有相同字符的输入返回“空字符串”。

当前问题:

输入1:abc
输入2:定义
output: ' // 它应该是“空字符串”;

这是我的代码:

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

void strInterset(char * str1, char * str2, char * str3);

int main() {
    char str1[50], str2[50], str3[50];

    printf("Enter str1: \n");
    scanf("%s", str1);
    printf("Enter str2: \n");
    scanf("%s", str2);
    strInterset(str1, str2, str3);

    if (*str3 == '\0')
        printf("strIntersect(): null string\n");
    else
        printf("strIntersect(): %s\n", str3);

    return 0;
}

void strInterset(char * str1, char * str2, char * str3) {
    int i = 0, j;
    for (i; *(str1 + i) != '\0'; i++) {
        for (j = 0; *(str2 + j) != '\0'; j++) {
            if ( *(str2 + j) == *(str1 + i)) {
                strcpy(str3, str1 + i);
                str3++;
            }
        }
    }
}

【问题讨论】:

  • 上述代码遇到了什么问题?将 str3[50] 初始化为 null
  • 如果没有公共字符,str3 是一个未初始化的变量,具有不确定的值。
  • 即使有普通字符,str3也不会被NUL终止
  • @ChrisTurner strcpy 复制 nul 终止符。
  • 对不起,我的意思是输出应该是“空字符串”

标签: c string function


【解决方案1】:

原因是strInterset() 仅在找到匹配项时调用strcpy(),而不会修改str3 或其指向的数据。修复很简单 - 在 strInterset() 的循环之前添加语句

 *str3 = '\0';

如果找到匹配项,strcpy() 仍将被调用。否则,main() 中的测试将成功。

main() 中的数组初始化为零也适用于strInterset() 的第一次调用。但它可能不适用于后续调用(除非main() 在每次调用之前重新初始化str3)。因此最好在strInterset() 中进行初始化。

【讨论】:

    【解决方案2】:

    快速修复应该是str3[0] = '\0' 作为main 中的第二行。

    但是还有更多方法可以让你的程序变得更好:

    • 为什么需要完整的char str3[50]?您可以改为使用函数的返回值,如下所示:char strInterset(char * str1, char * str2); 然后在适当的位置添加return。 (顺便说一句:那应该是拼写intersect吗?)

    • 您的程序使用了两个嵌套的for-循环(在大输入时速度很慢)。相反,您可以创建一个数组,其中每个条目对应一个字符值(查看 ascii 表)。然后该数组可以包含该字符是否出现的真/假。您将所有条目初始化为 0。然后遍历第一个字符串,并为每个字符将其在数组中的条目设置为 1。然后遍历第二个字符串,并为每个字符检查数组中的条目是否 1. 如果找到了这种情况,那么您发现了一个同时出现在两个字符串中的字符。

    【讨论】:

      【解决方案3】:

      通过将 str3 声明为 NULL 来显式初始化它

      char str3[50] = { NULL }; 
      

      如果你不这样做,它是一个带有垃圾/不确定值的统一数组。

      【讨论】:

        【解决方案4】:

        您应该将str3 初始化为NULL,如下所示:

        char str3[50] = {0};
        

        因为如果你不这样做,它将保持一个未初始化的数组,这意味着它会在访问时调用 Undefined Behavior,因为它的值是垃圾。

        此外,即使存在公共字符,str3 也不会以 NULL 结尾。

        我会亲自将您的功能更改为:

        void strInterset(char * str1, char * str2, char * str3) {
            int i = 0, j;
            *str3 = '\0'; // NULL terminate
            for (i; *(str1 + i) != '\0'; i++) {
                ...
        }
        

        输出:

        Enter str1: abc
        Enter str2: dfg
        strIntersect(): null string
        

        PS:编译时启用警告,你会得到:

        prog.c: In function 'strInterset':
        prog.c:26:5: warning: statement with no effect [-Wunused-value]
             for (i; *(str1 + i) != '\0'; i++) {
             ^~~
        

        只需将其更改为:for (; *(str1 + i) != '\0'; i++) {,或者更好的是for (int i = 0; *(str1 + i) != '\0'; i++) {。这不是您的问题,但可以很好地修复警告。

        【讨论】:

        • 糟糕,错过了@PeterJ_01,谢谢!现在怎么样了?
        • 对不起,我的意思是输出应该显示“空字符串”而不是空字符
        • 它会输出strIntersect(): null string,以防找不到@Denise 的常用字符。
        【解决方案5】:

        这是您的函数,它检查常见字符并将它们添加到结果字符串中而不重复。如果您不关心重复,只需删除第二个 if (并且只删除 if 所在的行,但将其主体留在括号中)

        char *strcomm(const char *s1, const char *s2, char *s3)
        {
            const char *tmp;
            char *tmps3 = s3;
            *s3 = 0;
            while(*s1)
            {
                tmp = s2;
                while(*tmp)
                {
                    if(*s1 == *tmp)
                        if(strchr(s3,*s1) == NULL)
                        {
                            *s3++ = *s1;
                            *s3 = 0;
                        }
                    tmp++;
                }
                s1++;
            }
            return tmps3;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-03-24
          • 1970-01-01
          • 2021-08-04
          • 2013-09-13
          • 2012-10-24
          相关资源
          最近更新 更多