【发布时间】:2018-09-17 00:10:54
【问题描述】:
我正在尝试优化一个问题,我必须通过相同的速度优化使其更具可读性。我的问题在于:
允许的函数:write.c,仅此而已。
编写一个程序,它接受两个字符串,并在没有双精度的情况下显示 出现在任一字符串中的字符。
将按照字符在命令行中出现的顺序显示,并且 后面会跟一个\n。
如您所见,在使用 GCC 编译它之后,它会将您的两个参数字符串(argv[1] 和 argv[2])带入我们的函数(void remove_dup(char *str, char *str2))。该临时数组将保存 ASCII 值检测到重复后的字符。例如,str1 = "hello" 和 str2 = "laoblc"。使用 write 函数,预期的输出将是“heloabc”。
但是,GCC 抱怨,因为我有一个数组下标,其中我的临时字符数组用我的字符串索引中的零填充。为了停止让编译器抱怨,我不得不将字符串索引转换为 int 以将 ASCII 值保存在我的临时数组中。这将是我们的检查器,它将根据字符的值确定我们的字符串中是否存在重复项。再次重新编译它,但这次使用警告标志:gcc -Wextra -Werror -Wall remove_dup.c。这是我得到的错误:
remove_dup:11 错误:数组下标是 'char' 类型 [-Werror,-Wchar-subscripts]
if (temp[str[i]] == 0) ^~~~~~~remove_dup:13 错误:数组下标是 'char' 类型 [-Werror,-Wchar-subscripts]
temp[str[i]] = 1; ^~~~~~~remove_dup:21 错误:数组下标是 'char' 类型 [-Werror,-Wchar-subscripts]
if (temp[str2[i]] == 0) ^~~~~~~~remove_dup.c:23 错误:数组下标是 'char' 类型 [-Werror,-Wchar-subscripts]
temp[str2[i]] = 1; ^~~~~~~~
现在我真正的问题是,如何在不使用任何类型的转换的情况下获得相同的时间效率?该程序以O(m + n) 运行,其中m 是我们的第一个字符串,n 是我们的第二个字符串。
这是代码:
void remove_dup(char *str, char *str2)
{
int temp[10000] = {0};
int i;
i = 0;
while (str[i])
{
if (temp[(int)str[i]] == 0)
{
temp[(int)str[i]] = 1;
write(1, &str[i], 1);
}
i++;
}
i = 0;
while (str2[i])
{
if (temp[(int)str2[i]] == 0)
{
temp[(int)str2[i]] = 1;
write(1, &str2[i], 1);
}
i++;
}
}
int main(int argc, char *argv[])
{
if (argc == 3)
remove_dup(argv[1], argv[2]);
write(1, "\n", 1);
return (0);
}
我希望我解释的逻辑结构足够清楚。我可能有语法错误,所以请耐心等待:)。
【问题讨论】:
-
AFAIK 转换不会导致运行时损失。在相关说明中,
temp只需要 256 个元素长,因为这就是char的大小。 -
我同意施文的观点。你的代码看起来不错。消除烦人的 gcc 警告的稍微更优雅的方法是将
temp[(int)str[i]]替换为temp[+str[i]]。这也将避免显式转换;最好尽可能避免强制转换。 -
更正:除非你的字符是
signed! -
@JosephQuinsey 你能解释一下为什么在这种情况下必须对字符进行签名吗?