【发布时间】:2021-02-20 12:51:09
【问题描述】:
在下面的函数中,我必须返回哈希表中所有重复字符串的列表,忽略参数值等于 1 的情况。
upo_strings_list_t upo_find_idup(const char **strs, size_t n, int ignore_case)
{
upo_strings_list_t list = NULL;
if(ignore_case) //Must lowercase each string of strs
{
size_t i;
size_t j;
size_t size = sizeof(char);
size_t len = 0;
char *aux = malloc(sizeof(char*)); //For each string of strs to lowercase
char **aux_strs = malloc(n * sizeof(char*)); //For store lowercase strings
assert( aux != NULL );
assert( aux_strs != NULL );
for(i = 0; i < n; ++i)
{
len = strlen(strs[i]) + 1;
aux_strs[i] = malloc(len * size);
strcpy(aux, strs[i]);
for(j = 0; aux[j] != '\0'; ++j)
{
aux[j] = tolower(aux[j]);
}
strcpy(aux_strs[i], aux);
}
list = upo_find_dup((const char**)aux_strs, n);
}
else
{
list = upo_find_dup(strs, n);
}
return list;
}
因此,忽略大小写意味着 strs 的每个字符串都必须变为小写。我试图通过一个动态的字符串数组来做到这一点。当所有字符串都是小写时,该函数调用另一个函数(upo_find_dup),该函数返回重复字符串列表(不要重写相同的代码)。
upo_strings_list_t upo_find_dup(const char **strs, size_t n)
{
size_t i;
int val = 1;
upo_strings_list_t list = NULL;
upo_ht_linprob_t ht = upo_ht_linprob_create(UPO_HT_LINPROB_DEFAULT_CAPACITY,
upo_ht_hash_str_kr2e, upo_str_cmp);
assert( ht != NULL );
for(i = 0; i < n; ++i)
{
if(upo_ht_linprob_contains(ht, &strs[i]))
{
upo_strings_list_node_t *ln = malloc(sizeof(upo_strings_list_node_t));
if(ln == NULL)
{
perror("Unable to allocate memory for a new node");
abort();
}
ln->str = (char*)strs[i];
ln->next = list;
list = ln;
}
else
{
upo_ht_linprob_put(ht, &strs[i], &val);
}
}
return list;
}
这似乎可行,因为如果我打印保存在列表中的每个字符串,它们就是它们必须是的:
void test_find_idup()
{
const char *ary[] = {"One", "two", "four", "two", "one"};
size_t n = sizeof(ary) / sizeof(ary[0]);
//const char *res[] = {"one","two"};
upo_strings_list_t list;
list = upo_find_idup(ary, n, 1);
assert( list != NULL );
//size_t i = 0;
while(list != NULL)
{
printf("%s\n", list->str);
//assert( list->str == res[i] );
list = list->next;
//++i;
}
/* PRINT: one two :OK*/
}
但是,当我尝试断言保存在列表节点中的字符串是否等于结果字符串(res[0] = "one" and res[1] = "two")时,断言失败并且出现核心转储错误:
test_hashtable_linprob: test_hashtable_linprob.c:1332: test_find_idup: Assertion `list->str == res[i]' failed.
==13842==
==13842== Process terminating with default action of signal 6 (SIGABRT)
==13842== at 0x4DEC18B: raise (raise.c:51)
==13842== by 0x4DCB858: abort (abort.c:79)
==13842== by 0x4DCB728: __assert_fail_base.cold (assert.c:92)
==13842== by 0x4DDCF35: __assert_fail (assert.c:101)
==13842== by 0x10E7E8: test_find_idup (test_hashtable_linprob.c:1332)
==13842== by 0x10EAF7: main (test_hashtable_linprob.c:1403)
==13842==
==13842== HEAP SUMMARY:
==13842== in use at exit: 901 bytes in 11 blocks
==13842== total heap usage: 234 allocs, 223 frees, 169,605 bytes allocated
==13842==
==13842== 13 bytes in 3 blocks are definitely lost in loss record 2 of 7
==13842== at 0x4A37ECB: malloc (vg_replace_malloc.c:307)
==13842== by 0x11029D: upo_find_idup (hashtable.c:593)
==13842== by 0x10E771: test_find_idup (test_hashtable_linprob.c:1324)
==13842== by 0x10EAF7: main (test_hashtable_linprob.c:1403)
==13842==
==13842== 424 (40 direct, 384 indirect) bytes in 1 blocks are definitely lost in loss record 6 of 7
==13842== at 0x4A37ECB: malloc (vg_replace_malloc.c:307)
==13842== by 0x10F482: upo_ht_linprob_create (hashtable.c:313)
==13842== by 0x110093: upo_find_dup (hashtable.c:546)
==13842== by 0x10E66D: test_find_dup (test_hashtable_linprob.c:1310)
==13842== by 0x10EAC1: main (test_hashtable_linprob.c:1398)
==13842==
==13842== 424 (40 direct, 384 indirect) bytes in 1 blocks are definitely lost in loss record 7 of 7
==13842== at 0x4A37ECB: malloc (vg_replace_malloc.c:307)
==13842== by 0x10F482: upo_ht_linprob_create (hashtable.c:313)
==13842== by 0x110093: upo_find_dup (hashtable.c:546)
==13842== by 0x11035A: upo_find_idup (hashtable.c:602)
==13842== by 0x10E771: test_find_idup (test_hashtable_linprob.c:1324)
==13842== by 0x10EAF7: main (test_hashtable_linprob.c:1403)
==13842==
==13842== LEAK SUMMARY:
==13842== definitely lost: 93 bytes in 5 blocks
==13842== indirectly lost: 768 bytes in 2 blocks
==13842== possibly lost: 0 bytes in 0 blocks
==13842== still reachable: 40 bytes in 4 blocks
==13842== suppressed: 0 bytes in 0 blocks
==13842== Reachable blocks (those to which a pointer was found) are not shown.
==13842== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==13842==
==13842== For lists of detected and suppressed errors, rerun with: -s
==13842== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
Aborted (core dumped)
这也是数据结构:
/** \brief The type for nodes of list of strings. */
struct upo_strings_list_node_s {
char *str;
struct upo_strings_list_node_s *next;
};
/** \brief Alias for the type for nodes of list of strings. */
typedef struct upo_strings_list_node_s upo_strings_list_node_t;
/** \brief The type for list of strings. */
typedef upo_strings_list_node_t *upo_strings_list_t;
【问题讨论】:
-
你不能用POSIX
strcasecmp吗? -
另外,在比较之前不需要复制字符串...您可以手动比较小写变体 (
int i = 0; while(str1[n][i] && str2[n][i] && tolower(str1[n][I]) == tolower(str2[n][i]) i++; if(!str1[n][i] && !str2[n][i) {/* equal */;})。 -
非常感谢!我使用了 strcasecmp() 并且它有效!