为什么我不能使用`=`复制数组? [英] Why can't I copy an array by using `=`?

查看:25
本文介绍了为什么我不能使用`=`复制数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开始通过阅读 K&R 并完成一些练习来学习 C.经过一番挣扎,我终于能够用下面的代码完成练习 1-19:

/* reverse:反转字符串s */void reverse(char s[], int slen){字符 tmp[slen];内部 i, j;我 = 0;j = slen - 2;/* 跳过 '\0' 和 \n */tmp[i] = s[j];而 (我 <= slen) {++i;--j;tmp[i] = s[j];}/* 来自复制函数 p 29 的代码 */我 = 0;而 ((s[i] = tmp[i]) != '\0')++i;}

我的问题是关于将 tmp 字符数组复制到 s 的最后一点代码.为什么简单的 s = tmp; 不起作用?为什么必须遍历数组复制索引一个索引?

解决方案

也许我只是年纪大了脾气暴躁,但我看到的其他答案似乎完全没有抓住重点.

C 不做数组赋值,句号.您不能通过简单的赋值将一个数组分配给另一个数组,这与其他一些语言(例如 PL/1;Pascal 及其许多后代 - Ada、Modula、Oberon 等)不同.C 也没有真正的字符串类型.它只有字符数组,并且您不能在不使用循环或函数调用的情况下复制字符数组(就像复制任何其他类型的数组一样).[字符串字面量并不真正算作字符串类型.]

复制数组的唯一时间是当数组嵌入到结构中并且您进行结构赋值时.

在我的 K&R 第二版副本中,练习 1-19 要求一个函数 reverse(s);在我的 K&R 第 1 版副本中,练习 1-17 而不是 1-19,但也提出了同样的问题.

由于在此阶段尚未涵盖指针,因此解决方案应使用索引而不是指针.我相信这会导致:

#include 无效反向(字符 s[]){int i = 0;int j = strlen(s) - 1;而 (i int main(void){字符缓冲区[256];while (fgets(buffer, sizeof(buffer), stdin) != 0){int len = strlen(缓冲区);如果(长度== 0)休息;缓冲区[len-1] = '\0';/* Zap 换行 */printf("输入:<<%s>>\n", 缓冲区);反向(缓冲);printf("输出:<<%s>>\n", 缓冲区);}返回(0);}#endif/* 测试 */

使用 -DTEST 编译它以包含测试程序,而无需仅定义函数 reverse().

使用问题中给出的函数签名,您可以避免在每行输入中调用 strlen() 两次.注意 fgets() 的使用——即使在测试程序中,使用 gets() 也是一个坏主意.与 gets() 相比,fgets() 的缺点是 fgets() 不会删除 gets() 所在的尾随换行符 确实如此.fgets() 的好处是你不会遇到数组溢出,你可以判断程序是否找到了换行符,或者在遇到换行符之前是否用完了空间(或数据).>

I'm starting to learn C by reading K&R and going through some of the exercises. After some struggling, I was finally able to complete exercise 1-19 with the code below:

/* 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;

}

My question is regarding that last bit of code where the tmp char array is copied to s. Why doesn't a simple s = tmp; work instead? Why does one have to iterate through the array copying index by index?

解决方案

Maybe I'm just old and grumpy, but the other answers I've seen seem to miss the point completely.

C does not do array assignments, period. You cannot assign one array to another array by a simple assignment, unlike some other languages (PL/1, for instance; Pascal and many of its descendants too - Ada, Modula, Oberon, etc.). Nor does C really have a string type. It only has arrays of characters, and you can't copy arrays of characters (any more than you can copy arrays of any other type) without using a loop or a function call. [String literals don't really count as a string type.]

The only time arrays are copied is when the array is embedded in a structure and you do a structure assignment.

In my copy of K&R 2nd Edition, exercise 1-19 asks for a function reverse(s); in my copy of K&R 1st Edition, it was exercise 1-17 instead of 1-19, but the same question was asked.

Since pointers have not been covered at this stage, the solution should use indexes instead of pointers. I believe that leads to:

#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 */

Compile this with -DTEST to include the test program and without to have just the function reverse() defined.

With the function signature given in the question, you avoid calling strlen() twice per line of input. Note the use of fgets() — even in test programs, it is a bad idea to use gets(). The downside of fgets() compared to gets() is that fgets() does not remove the trailing newline where gets() does. The upsides of fgets() are that you don't get array overflows and you can tell whether the program found a newline or whether it ran out of space (or data) before encountering a newline.

这篇关于为什么我不能使用`=`复制数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆