如何检查字符串数组中是否存在字符串

时间:2015-04-06 01:13:19

标签: c arrays string

我正在寻找一种方法来检查特定字符串是否存在于大量字符串中。该数组是多维的:all_strings[strings][chars];。基本上,这个数组是一个字符数组的数组。每个字符数组以'\ 0'

结尾

给定另一个字符数组,我需要检查这些字符是否已经在all_strings中,类似于python in关键字。

我根本不确定如何解决这个问题,我知道strcmp可能会有所帮助,但我不确定如何实现它。

3 个答案:

答案 0 :(得分:5)

正如潜伏者所说,天真的方法是简单地循环调用strcmp的字符串数组。遗憾的是,由于对string_in的误解,他的sizeof(string_list)函数被打破了,应该看起来像这样:

#include <string.h>
int string_in(char *needle, char **haystack, size_t haystack_size) {
    for (size_t x = 0; x < haystack_size; x++) {
         if (strcmp(needle, haystack[x]) == 0) {
             return 1;
         }
    }
    return 0;
}
然而,这是相当低效的。如果您只是偶尔使用它,特别是在一小组字符串上,但如果您正在寻找一种有效的方法来反复执行搜索,那么该怎么办呢?更改每个搜索的搜索查询,我会考虑的两个选项是:

  • 如果all_strings相对静态,您可以按如下方式对数组进行排序:qsort(all_strings, strings, chars, strcmp); ...然后,当您想确定某个单词是否存在时,可以使用bsearch像这样执行binary searchchar *result = bsearch(search_query, all_strings, strings, chars, strcmp);。请注意,当all_strings发生更改时,您需要再次对其进行排序。
  • 如果all_strings经常更改,您可能会从使用其他数据结构中受益,例如triehash table

答案 1 :(得分:3)

使用for循环。 C没有内置的Python in

int i;

for ( i = 0; i < NUM_STRINGS; i++ )
    if ( strcmp(all_strings[i], my_other_string) == 0 )
        break;

// Here, i is the index of the matched string in all_strings.
//   If i == NUM_STRINGS, then the string wasn't found

如果你想让它像Python的in一样,你可以使它成为一个函数:

// Assumes C99
#include <string.h>
#include <stdbool.h>

bool string_in(char *my_str, char *string_list[], size_t num_strings)
{
    for ( int i = 0; i < num_strings; i++ )
        if (strcmp(my_str, string_list[i]) == 0 )
            return true;

    return false;
}

答案 2 :(得分:1)

您只需检查字符串数组中是否存在字符串即可。一个更好的解决方案可能是实际返回字符串

/*
 * haystack: The array of strings to search.
 * needle: The string to find.
 * max: The number of strings to search in "haystack".
 */
char *
string_find(char **haystack, char *needle, size_t max)
{
    char **end = haystack + max;
    for (; haystack != end; ++haystack)
        if (strcmp(*haystack, needle) == 0)
            return *haystack;
    return NULL;
}

如果您想要一个集合的行为,其中数组中的所有字符串都是唯一的,那么您可以这样使用它:

typedef struct set_strings {
    char **s_arr;
    size_t count;
    size_t max;
} StringSet;
.
.
.
int
StringSet_add(StringSet *set, const char *str)
{
    // If string exists already, the add operation is "successful".
    if (string_find(set->s_arr, str, set->count))
        return 1;

    // Add string to set and return success if possible.
    /*
     * Code to add string to StringSet would go here.
     */
    return 1;
}

如果你想真正对字符串做些什么,你也可以这样使用它:

/*
 * Reverse the characters of a string.
 *
 * str: The string to reverse.
 * n: The number of characters to reverse.
 */
void
reverse_str(char *str, size_t n)
{
    char c;
    char *end;

    for (end = str + n; str < --end; ++str) {
        c = *str;
        *str = *end;
        *end = c;
    }
}
.
.
.
    char *found = string_find(words, word, word_count);
    if (found)
        reverse_str(found, strlen(found));

作为通用算法,这是非常有用的,甚至可以根据需要应用于其他数据类型(当然需要一些重新工作)。正如undefined behaviour's answer所指出的那样,它在大量字符串上不会很快,但它对于简单和小的东西来说已经足够了。

如果您需要更快的东西,那么答案中给出的建议是好的。如果您自己编写某些内容,并且能够对内容进行排序,那么这样做是个好主意。这使您可以使用比线性搜索更好的搜索算法。标准bsearch很棒,但是如果你想要一些适合快速插入的东西,你可能想要一个搜索例程来为你提供插入新项目的位置,以避免在{{{{{{{ {1}}返回bsearch。换句话说,当你可以搜索一次并完成相同的事情时,为什么要搜索两次呢?