我开始通过阅读 K&R 和完成一些练习来学习 C。经过一番努力,我终于能够用下面的代码完成练习 1-19:
/* reverse: reverse the character string s */
void reverse(char s[], int slen)
{
char tmp[slen];
int i, j;
i = 0;
j = slen - 2; /* skip '\0' and \n */
tmp[i] = s[j];
while (i <= slen) {
++i;
--j;
tmp[i] = s[j];
}
/* code from copy function p 29 */
i = 0;
while ((s[i] = tmp[i]) != '\0')
++i;
}
我的问题是关于将 tmp
字符数组复制到 s
的最后一段代码。为什么简单的 s = tmp;
不能代替?为什么必须逐个索引地遍历数组复制?
最佳答案
也许我只是老了脾气暴躁,但我看到的其他答案似乎完全没有捕获要点。
C 不做数组赋值,句号。与某些其他语言(例如 PL/1;Pascal 及其许多后代 - Ada、Modula、Oberon 等)不同,您不能通过简单的赋值将一个数组分配给另一个数组。 C 也没有真正的字符串类型。它只有字符数组,不使用循环或函数调用就不能复制字符数组(正如不能复制任何其他类型的数组一样)。 [字符串文字实际上不算作字符串类型。]
复制数组的唯一时间是当数组嵌入结构中并且您进行结构分配时。
在我的 K&R 第 2 版副本中,练习 1-19 要求函数 reverse(s)
;在我的 K&R 第 1 版副本中,它是练习 1-17 而不是 1-19,但提出了同样的问题。
由于现阶段还没有涉及指针,解决方案应该使用索引而不是指针。我相信这会导致:
#include <string.h>
void reverse(char s[])
{
int i = 0;
int j = strlen(s) - 1;
while (i < j)
{
char c = s[i];
s[i++] = s[j];
s[j--] = c;
}
}
#ifdef TEST
#include <stdio.h>
int main(void)
{
char buffer[256];
while (fgets(buffer, sizeof(buffer), stdin) != 0)
{
int len = strlen(buffer);
if (len == 0)
break;
buffer[len-1] = '\0'; /* Zap newline */
printf("In: <<%s>>\n", buffer);
reverse(buffer);
printf("Out: <<%s>>\n", buffer);
}
return(0);
}
#endif /* TEST */
用 -DTEST 编译它以包含测试程序,而不只是定义函数 reverse()
。
使用问题中给出的函数签名,您可以避免在每行输入中调用两次 strlen()
。注意 fgets()
的使用——即使在测试程序中,使用 gets()
也不是一个好主意。与 gets()
相比,fgets()
的缺点是 fgets()
不会删除尾随的换行符,其中 gets()
确实如此。 fgets()
的优点是您不会遇到数组溢出,并且您可以在遇到换行符之前判断程序是否找到了换行符或者它是否用完了空间(或数据)。
关于c - 为什么我不能使用 `=` 复制数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1022379/