【问题标题】:Combining two strings into one string which eliminates the same letters in C将两个字符串组合成一个字符串,从而消除 C 中的相同字母
【发布时间】:2015-02-04 17:34:56
【问题描述】:

你好,我是编程新手,想向你学习一些:) 我正在.c 中做一个程序,我被困在一个部分。 我想获得 3 个或更多输入,最大大小为 5 个字符。 (例如:HELLO、HI、GOOD、BYE) 而且我想将它们堆叠在一个新字符串中,该字符串仅包含这 4 个字符串中的一次相同的字母 (例如:H、E、L、L、O、I、G、D、B、Y)

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

int main(void) {
char first[5], second[5], third[5], fourth[5];
printf("Enter 1st word: \n");   scanf(" %5s", &first);
printf("Enter 2nd word: \n");   scanf(" %5s", &second);
printf("Enter 3rd word: \n");   scanf(" %5s", &third);
printf("Enter 4th word: \n");   scanf(" %5s", &fourth);

char stack[21];  // i want a new string like this and then combine first 4 strings
                 // in this string...

return 0;
}

我希望你能告诉我我可以通过哪种方式做到这一点。 (我也是这个网站的新手。我搜索了这个但我找不到。对不起,如果它存在。)

【问题讨论】:

  • 您希望结果字符串中的字母按任何特定顺序排列吗?
  • @5gon12eder -- 不,我只想将这些字符串组合成一个字符串,以消除多余的字母。
  • 我建议创建堆栈数组 [21] 以考虑所有唯一字母(和空值)的可能性。
  • 感谢@doppelheathen,已编辑
  • 次要:" %5s" 中不需要该空间 - 你没有什么害处。许多(不是全部)scanf() 格式说明符(例如 "%s""%d""%f")都已准备好使用前导空白。

标签: c string letters combinators


【解决方案1】:

首先在您的代码中添加一些 cmets:

  • 正如其他人在评论中已经提到的,您需要一个大小为 n + 1 的缓冲区来保存 n 字符串。这是因为在 C 中,字符串的长度不会存储在任何地方。相反,一个特殊的 NUL 字节被附加到标记其结束的字符串中。因此,您的 first、...、fourth 数组的长度应至少为 6。
  • 如果最坏的情况发生并且用户输入四个不相交的单词,每个单词值 5 个字符,该怎么办?然后你的组合字符串将计算 20 个字符。因此,您的 stack 数组应该能够容纳 21 个字符(对于终止 NUL 字节也是 1 个)。 (user3121023 的评论也提到了。)
  • 要使用scanf 读取字符串,请传递char * 类型的参数,而不是char (*)[6]first 已经衰减到 char *,所以不要另外获取它的地址(如&amp;first)。打开编译器的警告(至少使用-Wall)以了解此类错误。 (在我输入这个答案时,Dere0405 也提到过。)
  • 您对scanf 的使用不安全。如果用户输入的字符串长度超过 5 个字符,您将读取超出数组末尾的内容。您可以修改格式说明符以读取 %5s 以告诉 scanf 在第 5 个字符后停止读取。但是,这会在行尾留下多余的字符。更好的选择是使用fgetsgetline 来读取整行输入。或者,只需将字符串作为命令行参数传递(我的首选解决方案)。

现在来看实际问题:

我不会给你一个完整的解决方案,而只是一些提示,因为这看起来很像家庭作业。 (不幸的是,其他人已经给了你完整的代码,所以你可能会忽略我的回答。)

您必须遍历所有五个字符串并检查每个字符是否已添加到stack。如果是,请继续,否则,将其附加到stack。要遍历一个字符串,我们可以使用以下成语。

int i;
for (i = 0; first[i]; ++i)
  printf("The character at position %d is '%c'\n", i, first[i]);

或者,如果我们不需要引用当前索引,下面的成语更简洁。

char * pos;
for (pos = first; *pos; ++pos)
  printf("The current character is '%c'\n", *pos);

请注意我们如何使用 first(作为 C 字符串)以 NUL 字节结尾的事实,该字节的计算结果为 false。否则,我们将不知道在哪里停止迭代。

既然我们知道如何循环遍历字符串的字符,那么我们如何检查是否已经添加了字符?想到了两个解决方案:

  1. 循环遍历stack 并将每个元素与当前讨论的字符进行比较。虽然对于您的短字符串,这可能是首选方法,但对于较长的字符串,它会变得低效。

  2. 为每个字符创建一个计数器,并在添加到stack 时将其递增。您可以使用 chars 只是数字的事实。因此,您可以创建一个包含 256 个元素(有 256 个不同的chars)的数组,所有元素最初都设置为 0,然后增加当前添加的字符的位置。例如:

    int counters[256];
    memset(counters, 0, sizeof(counters));  /* fill with 0s */
    

    然后在您的代码中:

    if (counters[(unsigned char) (*pos)]++)
      {
        /* Character was already added.  Do nothing. */
      }
    else
      {
        /* Character was not added yet.  Add it to stack. */
      }
    

    if (counters[(unsigned char) (*pos)]++) 有点棘手。首先,*pos 引用指针pos 以产生当前字符,然后将其解释为unsigned char,因为数组不能有负索引。然后在counters 数组中查找该位置并在if 语句中进行评估。最后,该值通过后自增运算符递增(但仅在比较之后)。

不要忘记以 NUL 字节结束 stack

【讨论】:

  • 非常感谢,这正是我想要的 :) 我会自己尝试看看你输入的内容 :)
【解决方案2】:

请更新您的代码如下:

printf("Enter 1st word: \n");   scanf(" %s", &first);

printf("Enter 1st word: \n");   scanf(" %s", first);

请更新到其他行。

【讨论】:

  • 这是为什么呢? scanf 中的变量不应该有 & 吗?
  • 嗯,这是我唯一确定的 ^^ ,我想我没有错,执行时我也没有收到任何警告
  • @Gorki 你应该得到编译器警告。执行时,它只是调用未定义的行为,因此任何事情都可能发生也可能不会发生。请参阅我的答案以获得更多解释。
【解决方案3】:

试试:

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

int main(void) {
    char strings[4][6];
    printf("Enter 1st word: \n");   scanf(" %s", strings[0]);
    printf("Enter 2nd word: \n");   scanf(" %s", strings[1]);
    printf("Enter 3rd word: \n");   scanf(" %s", strings[2]);
    printf("Enter 4th word: \n");   scanf(" %s", strings[3]);

    char stack[21];  // This needs to be pretty much bigger than all combined just in case

    // Initialize the stack string to 0 length
    stack[0] = '\0'

    // Move through each word
    for(unsigned char word = 0; word < 4; word++){

        // Move through each letter of each word
        for(unsigned char letter = 0; letter < strlen(strings[word]); letter++){
            // Test to see if the current letter is within the current stack string
            unsigned char schar;
            for(schar = 0; schar < strlen(stack); schar++){
                if(stack[schar] == strings[word][letter]) break;
            }

            if(schar >= strlen(stack)){
                unsigned char sstacklen = strlen(stack);
                stack[sstacklen] = strings[word][letter];
                stack[sstacklen+1] = '\0';
            }

        }
    }

    return 0;
}

这应该可以满足您的要求,这是一个快速的写作,所以可能会有小错误!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-13
    • 1970-01-01
    • 1970-01-01
    • 2014-02-25
    • 1970-01-01
    • 2013-05-24
    相关资源
    最近更新 更多