【问题标题】:How to copy a char array in C?如何在C中复制char数组?
【发布时间】:2013-05-14 18:41:21
【问题描述】:

在 C 中,我有两个 char 数组:

char array1[18] = "abcdefg";
char array2[18];

如何将array1的值复制到array2?我可以这样做吗:array2 = array1

【问题讨论】:

  • strcpymemcpy
  • char array1[18] = {"abcdefg"}; 不是正确的字符数组。
  • 使用 strcpy(array2,array1) 函数
  • 虽然它确实可以作为 char 数组工作(恰好可以工作),但它应该被声明为 char array1[18] = "abcdefg";char array1[18] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', '\0'};
  • @aragaer 6.7.9 (14):“字符类型的数组可以由字符串文字或 UTF-8 字符串文字初始化,可选用大括号括起来。 " char array1[18] = {"abcdefg"}; 是不寻常的,但 100% pukka。

标签: c arrays char copy


【解决方案1】:

您不能直接执行array2 = array1,因为在这种情况下您操作的是数组的地址 (char *) 而不是它们的内部值 (char)。

从概念上讲,您要做的是遍历源 (array1) 的所有字符并将它们复制到目标 (array2)。有几种方法可以做到这一点。例如,您可以编写一个简单的 for 循环,或使用 memcpy

话虽如此,字符串的推荐方法是使用strncpy。它可以防止导致例如buffer overflows 的常见错误(如果array1 由用户输入填充:键盘、网络等,则尤其危险)。像这样:

// Will copy 18 characters from array1 to array2
strncpy(array2, array1, 18);

作为@Prof。 Falken 在评论中提到,strncpycan be evil。确保您的目标缓冲区足够大以包含源缓冲区(包括字符串末尾的\0)。

【讨论】:

  • 为什么我们不能只做array2 = array1?
  • @user2131316:这是因为数组名称在语义上转换为指针值的方式。我在回答中解释了这一点。
  • 你提到array1=array2 让我很困惑,这意味着array1 获得了新值,但你的代码却反过来。以防万一其他人为此而堕落。
  • strncat 将始终提供一个 nul 终止的结果,而不会出现缓冲区溢出。见this
【解决方案2】:

如果您的数组不是字符串数组,请使用: memcpy(array2, array1, sizeof(array2));

【讨论】:

  • 不会 sizeof() 返回指针的大小(即您机器上的字大小)?
  • @Wecherowski:当您将数组传递给函数时,它会降级为指针。在该函数中,您不能使用sizeof() 来确定数组的大小。否则sizeof() 可以很好地完成该任务。
【解决方案3】:

如果您想防止可能导致各种问题的非终止字符串,请像这样复制您的字符串:

char array1[18] = {"abcdefg"};
char array2[18];

size_t destination_size = sizeof (array2);

strncpy(array2, array1, destination_size);
array2[destination_size - 1] = '\0';

最后一行实际上很重要,因为strncpy() 并不总是null terminate 字符串。 (如果目标缓冲区太小而无法包含整个源字符串,sntrcpy() 将不会终止目标字符串。)

strncpy() 的手册页甚至声明“警告:如果 src 的前 n 个字节中没有空字节,则放在 dest 中的字符串将不会以空值结尾。”

strncpy() 之所以会出现这种奇怪的行为,是因为它最初并不是一种安全的复制字符串的方式。

另一种方法是使用 snprintf() 作为 strcpy() 的安全替代:

snprintf(array2, destination_size, "%s", array1);

(感谢jxh 的提示。)

【讨论】:

  • 注意snprintf()没有strncpy()的问题。
  • 这不会产生警告吗? strncpy 接受 const char 作为源。
  • @konpsych 不应生成警告。
【解决方案4】:

正如其他人所指出的,字符串是用strcpy() 或其变体复制的。在某些情况下,您也可以使用snprintf()

作为结构分配的一部分,您只能以您想要的方式分配数组:

typedef struct { char a[18]; } array;
array array1 = { "abcdefg" };
array array2;

array2 = array1;

如果你的数组被传递给一个函数,看起来你可以分配它们,但这只是语义上的意外。在 C 中,数组将衰减为具有数组第一个成员的地址值的指针类型,而这个指针就是传递的内容。因此,函数中的数组参数实际上只是一个指针。赋值只是一个指针赋值:

void foo (char x[10], char y[10]) {
    x = y;    /* pointer assignment! */
    puts(x);
}

从函数返回后,数组本身保持不变。

数组的这种“衰减到指针值”语义是赋值不起作用的原因。左值是数组类型,而右值是衰减的指针类型,所以赋值是在不兼容的类型之间。

char array1[18] = "abcdefg";
char array2[18];
array2 = array1; /* fails because array1 becomes a pointer type,
                    but array2 is still an array type */

至于为什么要引入“decay to pointer value”语义,这是为了实现与C前身的源代码兼容。详情可以阅读The Development of the C Language

【讨论】:

  • 解释为什么array2 = array1; 不起作用的唯一答案。点赞。
【解决方案5】:

您不能分配数组,名称是不能更改的常量。

您可以复制内容,其中:

strcpy(array2, array1);

假设源是一个有效的字符串,并且目标足够大,如您的示例所示。

【讨论】:

    【解决方案6】:

    应该是这样的:

    void cstringcpy(char *src, char * dest)
    {
        while (*src) {
            *(dest++) = *(src++);
        }
        *dest = '\0';
    }
    .....
    
    char src[6] = "Hello";
    char dest[6];
    cstringcpy(src, dest);
    

    【讨论】:

    • 您的cstringcpy 函数不会终止目标数组。
    • 没明白。请提供您的“修复”。
    • @zett42:请注意,这个cstringcpy 函数在语义上几乎完全等同于strcpy,具有相同的缺点,即不检查缓冲区溢出。
    【解决方案7】:

    我建议使用 memcpy() 来复制数据。 此外,如果我们将缓冲区分配给另一个 array2 = array1 ,则两个数组都具有相同的内存,并且 arrary1 中的任何更改也会在 array2 中偏转。但是我们使用 memcpy,两个缓冲区都有不同的数组。我推荐 memcpy() 因为 strcpy 和相关函数不复制 NULL 字符。

    【讨论】:

      【解决方案8】:
      array2 = array1;
      

      在 c 中不受支持。您必须使用 strcpy() 之类的函数来执行此操作。

      【讨论】:

        【解决方案9】:

        只有下面的c函数...c++你必须做char数组然后使用字符串复制然后使用字符串tokenizor函数...c++让做任何事情变得更加困难

        #include <iostream>
        #include <fstream>
        #include <cstring>
        #define TRUE 1
        #define FALSE 0
        typedef int Bool;
        using namespace std;
        Bool PalTrueFalse(char str[]);
        int main(void)
        {
        char string[1000], ch;
        int i = 0;
        cout<<"Enter a message: ";
        
        while((ch = getchar()) != '\n') //grab users input string untill 
        {                               //Enter is pressed
            if (!isspace(ch) && !ispunct(ch)) //Cstring functions checking for
            {                                //spaces and punctuations of all kinds
                string[i] = tolower(ch); 
                i++;
            }
        }
        string[i] = '\0';  //hitting null deliminator once users input
        cout<<"Your string: "<<string<<endl; 
        if(PalTrueFalse(string)) //the string[i] user input is passed after
                                //being cleaned into the null function.
            cout<<"is a "<<"Palindrome\n"<<endl;
        else
           cout<<"Not a palindrome\n"<<endl;
        return 0;
        }
        
        Bool PalTrueFalse(char str[])
        {
        int left = 0;
        int right = strlen(str)-1;
        while (left<right)
        {
           if(str[left] != str[right]) //comparing most outer values of string
               return FALSE;          //to inner values.
           left++;
           right--;
        }
        return TRUE;
        }
        

        【讨论】:

          【解决方案10】:

          对于整数类型

          #include <string.h>    
          
          int array1[10] = {0,1,2,3,4,5,6,7,8,9};
          int array2[10];
          
          
          memcpy(array2,array1,sizeof(array1)); // memcpy("destination","source","size")
          

          【讨论】:

          • 那不会编译。请改用int array1[10] = {0,1,2,3,4,5,6,7,8,9};
          【解决方案11】:

          您不能分配数组来复制它们。如何将一个内容复制到另一个取决于多个因素:

          对于char 数组,如果您知道源数组是空终止的,并且目标数组对于源数组中的字符串(包括空终止符)足够大,请使用strcpy()

          #include <string.h>
          
          char array1[18] = "abcdefg";
          char array2[18];
          
          ...
          
          strcpy(array2, array1);
          

          如果您不知道目标数组是否足够大,但源是 C 字符串,并且您希望目标是正确的 C 字符串,请使用snprinf()

          #include <stdio.h>
          
          char array1[] = "a longer string that might not fit";
          char array2[18];
          
          ...
          
          snprintf(array2, sizeof array2, "%s", array1);
          

          如果源数组不一定以 null 结尾,但您知道两个数组的大小相同,则可以使用 memcpy

          #include <string.h>
          
          char array1[28] = "a non null terminated string";
          char array2[28];
          
          ...
          
          memcpy(array2, array1, sizeof array2);
          

          【讨论】:

            【解决方案12】:

            嗯,从技术上讲,你可以……

            typedef struct { char xx[18]; } arr_wrap;
            
            char array1[18] = "abcdefg";
            char array2[18];
            
            *((arr_wrap *) array2) = *((arr_wrap *) array1);
            
            printf("%s\n", array2);     /* "abcdefg" */
            

            但它看起来不会很漂亮。

            …除非你使用 C 预处理器…

            #define CC_MEMCPY(DESTARR, SRCARR, ARRSIZE) \
                { struct _tmparrwrap_ { char xx[ARRSIZE]; }; *((struct _tmparrwrap_ *) DESTARR) = *((struct _tmparrwrap_ *) SRCARR); }
            

            你可以这样做:

            char array1[18] = "abcdefg";
            char array2[18];
            
            CC_MEMCPY(array2, array1, sizeof(array1));
            
            printf("%s\n", array2);     /* "abcdefg" */
            

            它适用于任何数据类型,而不仅仅是char

            int numbers1[3] = { 1, 2, 3 };
            int numbers2[3];
            
            CC_MEMCPY(numbers2, numbers1, sizeof(numbers1));
            
            printf("%d - %d - %d\n", numbers2[0], numbers2[1], numbers2[2]);     /* "abcdefg" */
            

            (是的,上面的代码是granted 可以一直工作并且它是可移植的)

            【讨论】:

            • 这是否记录在任何地方?
            【解决方案13】:

            以上都不适合我.. 这完美地工作 name 这里是char *name 是通过函数传递的

            1. 使用strlen(name) 获取char *name 的长度
            2. 将其存储在 const 变量中很重要
            3. 创建相同长度大小的char数组
            4. 使用strcpy(temp, name);name的内容复制到temp

            如果您想恢复原始内容,请随意使用。 strcpy(name, temp); 将 temp 复制回 name,瞧,完美运行

                const int size = strlen(name);
                char temp[size];
                cout << size << endl;
                strcpy(temp, name);
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2012-04-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2010-12-03
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多