提问人:ChenBr 提问时间:9/19/2023 最后编辑:ChenBr 更新时间:9/20/2023 访问量:181
使用指针比较 C 语言中的字符串
Compare strings in C using pointers
问:
我正在学习 C 课程,我很难弄清楚以下练习。
给定 2 个字符指针,该函数应按字典顺序比较指针指向的字符串(区分大小写)。如果发现第一个字符串分别小于、等于或大于第二个字符串,则应返回负数、0(零)或正整数值。
例如:(第一个)字符串“Fan”小于(第二个)字符串“Fun”,因此在这种情况下,函数应返回负整数值。
请注意:大写字母不同于小写字母('A' != 'a')。
我尝试创建每个字符串的总和,然后比较它们以查看哪个更大。 这是我写的函数:
int StringCompare(const char *str1, const char *str2)
{
int str1_sum = 0;
int str2_sum = 0;
while (*str1 != '\0')
{
str1_sum += *str1++;
str1++;
}
while (*str2 != '\0')
{
str2_sum += *str2++;
str2++;
}
if (str1_sum > str2_sum)
{
return 1;
}
else if (str1_sum < str2_sum)
{
return -1;
}
else
{
return 0;
}
}
不幸的是,它不起作用,我收到以下错误:
Running test: StringCompare("oeis03HWoLn\I7]JJ=7yCWei4H\SN7S", "BlA;Vx<2lYY6r`Mu0Z1bnXL\EMqRkau") -- Failed
当我尝试调试它时,它进展顺利,我不确定我是否遗漏了代码中的某些内容,或者我只是没有正确理解练习。
帮助将不胜感激!
更新: 我更新了我的代码:
int StringCompare(const char *str1, const char *str2)
{
while(*str1 != '\0' && *str2 != '\0'){
if(*str1 > *str2) {
return 1;
} else if(*str1 < *str2) {
return -1;
}
str1++;
str2++;
}
if(*str1 == '\0' && *str2 == '\0'){
return 0;
} else if(*str1 == '\0'){
return -1;
} else {
return 1;
}
}
不幸的是,现在我收到以下错误消息:
Running test: StringCompare("(null)", "Hello !!!???") -- Failed: Invalid memory reference
我还尝试运行下面建议的 Surge 代码,但我也收到了相同的错误。
有谁知道可能是什么原因?
更新2: 添加了以下验证:
assert(str1 != NULL && str2 != NULL);
它现在可以工作了:
#include <assert.h>
#include <stddef.h>
int StringCompare(const char *str1, const char *str2)
{
assert(str1 != NULL && str2 != NULL);
while(*str1 != '\0' && *str2 != '\0'){
if(*str1 > *str2) {
return 1;
} else if(*str1 < *str2) {
return -1;
}
str1++;
str2++;
}
if(*str1 == '\0' && *str2 == '\0'){
return 0;
} else if(*str1 == '\0'){
return -1;
} else {
return 1;
}
}
答:
关于对词典排序的理解,您收到的评论是正确的。为了完整起见,以下是我经过一些测试的解决方案:
#include<stdio.h>
#include<stdlib.h>
int StringCompare(const char *str1, const char *str2)
{
while (*str1 == *str2)
{
if (*str1 == 0) return 0;
str1++;
str2++;
}
return (*(unsigned char *)str2 < *(unsigned char *)str1)
- (*(unsigned char *)str1 < *(unsigned char *)str2);
}
int main(void) {
printf("\"AD\":\"BC\" -> %d\n", StringCompare("AD", "BC"));
printf("\"Ab\":\"aa\" -> %d\n", StringCompare("Ab", "aa"));
printf("\"xxx\":\"aa\" -> %d\n", StringCompare("xxx", "aa"));
printf("\"\":\"aa\" -> %d\n", StringCompare("", "aa"));
printf("\"a\":\"a\xd0\" -> %d\n", StringCompare("a", "a\xd0"));
printf("\"\xee\":\"\xef\" -> %d\n", StringCompare("\xee", "\xef"));
printf("\"\xd0\":\"\" -> %d\n", StringCompare("\xd0", ""));
return EXIT_SUCCESS;
}
希望它有所帮助。(空字符串是排序中最低的字符串。
更新:一条评论指出,您可能还需要检查无效的输入,例如 .遗憾的是,没有自然的方法可以对无效输入与有效输入进行排序。这就是为什么正确的方法是在将输入传递给该比较器之前检查输入的有效性。另一种方法是返回一个处理非结果的复杂类型(比如 )。NULL
struct{int order_int; int error_flag;}
Update2:感谢 @chux - 恢复 Monica,这是另一个边缘案例修复。由于可以有符号或无符号,因此根据实现的不同,与 0 的比较会受到影响。如果使用扩展的 ASCII 字符,则会将字符串放在较短的字符串之前(以 0 结尾)。还需要使空字符串相对于所有有效字符串正确排序。char
""
评论
char *
"(null)"
[i]
i
StringCompare("(null)", ...
NULL
仅适用于迂腐的人:
@Surge可以很好地处理许多字符串。然而,由于 may 是有符号的,因此以负数开头的字符串小于 。char
char
""
相反,它执行该操作,它会比较字符串,就好像它们是值一样,即使它们是有符号的。strcmp()
unsigned char
char
对于本子句中的所有函数,每个字符都应解释为具有类型(因此每个可能的对象表示都是有效的并且具有不同的值) C23dr § 7.26.1 4
unsigned char
int StringCompareAlt(const char *str1, const char *str2) {
const unsigned char *ustr1 = (const unsigned char *) str1;
const unsigned char *ustr2 = (const unsigned char *) str2;
while (*ustr1 == *ustr2 && *ustr1 != 0) {
ustr1++;
ustr2++;
}
return (*ustr1 > *ustr2) - (*ustr1 < *ustr2);
}
OP 表示未发布的调用代码存在问题。StringCompare("(null)", "Hello !!!???")
评论
"AD"
"BC"
65 + 68
133
66 + 67
133
\0
strcmp