【问题标题】:Compare char arrays比较字符数组
【发布时间】:2011-10-23 19:15:35
【问题描述】:

如果我有一个字符数组,例如:

A = [w, o, r, n, g, , w, o, r, d]

还有另一个数组例如:

B = [c, o, r, r, e, c, t, , w, o, r, d, .]

我需要将数组 A 中的单词(由空格分隔)与数组 B 进行比较,如果第一个数组中的任何单词存在于第二个数组中,则应该打印该单词。例如,既然“word”存在于第一个数组和第二个数组中,那么应该打印出“word”。

我该怎么做?

【问题讨论】:

  • 你必须使用 C 和数组吗?你可以改用 C++ 和标准库容器吗?如果是这样,您可以将单词存储在向量(或类似的东西)中,并且搜索和操作容器内容的方法要容易得多。与普通的 C 和内置数组相比,这是一种更现代的处理方式。
  • 这是作业吗?你试过什么?你在哪里卡住了?你知道C编程语言的基本语法吗?
  • @Dabbler,是的。不幸的是,我必须使用 C。我有 Java 编程思维,出于某种原因,C 真的让我感到困惑。
  • @JensGustedt,我不知道 C 语法,Google 正在为我提供 C# 和 C++ 的所有答案。我知道我需要使用一个 foor 循环,遍历每个数组,在 while 循环中使用分词器按空格和句点分隔单词,然后说 if A[i] == B[j] 然后打印出单词.我是一名 java 程序员,对 C 几乎一无所知。
  • @MarlonBrando,如果您是 Java 程序员,C 语法对您来说应该不会太陌生。这种练习正是那时学习 C 的正确方法。

标签: c arrays char compare


【解决方案1】:

让我们看看我会怎么做:

您将需要一个函数,给定一个char 数组,将其拆分为一个单词数组(并将它们放在C 字符串中,请以NUL 终止:-))。我会把这个数组的长度和数组放在一个结构中

struct WordCollection
{
    size_t NumWords;
    char **Words;
}

现在...如何实现这个功能?

假设我们“作弊”了一点,并确定我们的数组 AB 是 NUL 终止的(或者如果它们是像 B 一样终止的 .,那么您将 . 替换为 NUL)。现在,这是 C,您应该首先计算字符串中的空格数,分配一个足够大的 char* (WordCollection::Words) 数组以包含 n + 1 char*(并将此 n + 1 放入 @987654336 @) 并使用strtok“标记”字符串并将单词放入您创建的数组中。

那么您应该(可以)使用此函数将 A 和 B 数组拆分为单词。您将获得两个WordCollection,A1 和 B1。

为了更快,我会qsort B1。

然后,对于 A1 中的每个单词,您在 B1 中 bsearch 它(这不是一个坏词……这意味着二进制搜索,它是在有序数组中搜索某些内容的快速方法)

完成:-)

我要补充一点,如果这是您第一次使用bsearchqsort,最好看看您可以找到的示例。它们的语法可能很“棘手”。

现在...我知道你不会看代码 :-) 所以我会把它放在这里

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

struct WordCollection
{
    size_t NumWords;
    char **Words;
};

void splitWord(char *str, struct WordCollection *wc)
{
    char *c;
    char **currentWord;

    c = str;

    wc->NumWords = 1;

    while (*c != '.')
    {
        if (*c == ' ')
        {
            wc->NumWords++;
        }

        c++;
    }

    *c = '\0';

    wc->Words = (char**)malloc(wc->NumWords * sizeof(char*));

    c = strtok(str, " ");

    currentWord = wc->Words;

    while (c)
    {
        *currentWord = c;
        currentWord++;

        c = strtok(NULL, " ");
    }
}

int myComp(const void *p1, const void *p2)
{
    return strcmp(*(const char**)p1, *(const char**)p2);
}

int main(void)
{
    char a[] = { 'w', 'o', 'r', 'n', 'g', ' ', 'w', 'o', 'r', 'd', '.' };
    char b[] = { 'c', 'o', 'r', 'r', 'e', 'c', 't', ' ', 'w', 'o', 'r', 'd', '.' };

    struct WordCollection a1, b1;
    struct WordCollection *pSmaller, *pBigger;

    size_t i;

    splitWord(a, &a1);
    splitWord(b, &b1);

    if (a1.NumWords <= b1.NumWords)
    {
        pSmaller = &a1;
        pBigger = &b1;
    }
    else
    {
        pSmaller = &b1;
        pBigger = &a1;
    }

    qsort(pBigger->Words, pBigger->NumWords, sizeof(char*), myComp);

    for (i = 0; i < pSmaller->NumWords; i++)
    {
        void *res = bsearch(&pSmaller->Words[i], pBigger->Words, pBigger->NumWords, sizeof(char*), myComp);
        if (res)
        {
            printf("Found: %s", pSmaller->Words[i]);
        }
    }

    free(a1.Words);
    free(b1.Words);

    return 0;
}

然后在ideone

【讨论】:

  • @ChrisLutz 你是在告诉我我应该使用size_t 来表示字数吗?从技术上讲,我“不需要”这样做。我可以简单地说该程序“支持”最多 10 个单词:-)
  • @Chris Lutz 我看到你说了很多s/int/size_t/g。我不知道这意味着什么。你能解释一下吗?
  • @Marlon 我认为这是对我将int 用于NumWords 的事实的间接引用。在 C 中,当您“计算”内存元素时,通常最好使用size_t。而且我认为他正在使用某些 sed 或其他类似工具的格式来“替换”size_t 中的int。不幸的是,我是一个迟钝的 Windows 用户 :-)
  • @xanatos,感谢您的回答。我正在考虑这样做:我需要使用一个 foror 循环,遍历每个数组,在 while 循环中使用一个标记器来按空格和句点分隔单词,并说 if A[i] == B[j ] 然后打印出单词。你怎么看?
  • @MarlonBrando 如果你这样做,你有一个复杂性 O(MN),如果你按照我说的那样做,你只有一个复杂性 O(MlogN) :-) 如果你想成为超级,你决定 A 和 B 中的哪个是 M 和 N 通过选择最大的作为 N 和最小的作为 M(排序的数组是 N)
【解决方案2】:

基本上,您需要以某种方式将单词分开,然后遍历组合。有一百种方法可以做到这一点——只需要编程。

【讨论】:

  • 我不知道 C 语法,Google 正在为我提供 C# 和 C++ 的所有答案。我知道我需要使用一个 foor 循环,遍历每个数组,在 while 循环中使用分词器按空格和句点分隔单词,然后说 if A[i] == B[j] 然后打印出单词.我是一名 java 程序员,对 C 几乎一无所知。因此,如果您想提供帮助而不是在我面前抨击您的编程技能,我将非常感谢您的帮助。谢谢。
  • Get yourself a copy of K&R 这样你就可以停止说“我不知道 C 语法”。
  • 如果您纯粹使用 char 数组并且不使用 String 或任何 java.util 东西,请弄清楚您将如何在 Java 中执行此操作。这将相当容易地音译成C。 (无论如何,我认为使用标记器毫无意义。)
【解决方案3】:

你也可以这样做:

  1. 将集合 A 中的所有单词插入到集合 C 中,并带有后缀“A”。你会得到 =>
    worngA
    wordA

  2. 将集合 B 中的所有单词插入到集合 C 中,并带有后缀“B”。你会得到 =>
    correctB
    wordB

  3. 在集合 C 上运行排序算法,例如 qsort。你会得到 =>
    correctB
    wordA
    wordB
    worngA

  4. 在集合 C 中循环,直到它的大小为 1。比较 word[i]word[i+1] - 如果它们匹配除了最后一个字母 - 你发现重复,你可以打印出来。

我不知道这个算法的复杂性,但它显然应该比所有单词组合的暴力扫描更快:-)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多