我正在寻找一种方法来检查特定字符串是否存在于大量字符串中。该数组是多维的:all_strings[strings][chars];
。基本上,这个数组是一个字符数组的数组。每个字符数组以'\ 0'
给定另一个字符数组,我需要检查这些字符是否已经在all_strings
中,类似于python in
关键字。
我根本不确定如何解决这个问题,我知道strcmp可能会有所帮助,但我不确定如何实现它。
答案 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 search:char *result = bsearch(search_query, all_strings, strings, chars, strcmp);
。请注意,当all_strings
发生更改时,您需要再次对其进行排序。all_strings
经常更改,您可能会从使用其他数据结构中受益,例如trie或hash 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
。换句话说,当你可以搜索一次并完成相同的事情时,为什么要搜索两次呢?