在 C 语言中,我有两个字符数组:
char array1[18] = "abcdefg";
char array2[18];
如何将array1
的值复制到array2
中?我可以这样做吗:array2 = array1
?
直接使用 array2 = array1
是不行的,因为这种情况下你操作的是数组 (char *
) 的地址而不是它们内部值 (char
) 的地址。
从概念上讲,你想要做的是遍历源数组 (array1) 中的所有字符并将它们复制到目标数组 (array2)。有多种方式可以实现这一点。例如,你可以编写一个简单的 for 循环,或者使用 memcpy
。
话虽如此,对于字符串来说,推荐使用 strncpy
。它可以防止常见的错误,比如缓冲区溢出(特别是当 array1
来自用户输入:键盘、网络等时,这种错误尤其危险)。使用方法如下:
// Will copy 18 characters from array1 to array2
strncpy(array2, array1, 18);
正如@Prof. Falken在评论中提到的,strncpy
可能有害。确保您的目标缓冲区足够大,可以容纳源缓冲区(包括字符串末尾的\0
)。
array1=array2
,这意味着array1会得到新值,但你的代码实际上却相反。以防其他人也会犯同样的错误。 - lucidbrotmemcpy(array2,array1,sizeof(array2));
sizeof()
来确定数组的大小。否则,sizeof()
可以很好地完成这个任务。 - user6214440char 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()的manpage中都声明了:"警告:如果src的前n个字节中没有null byte,则放入dest的字符串将不以null结尾。"
strncpy()表现出这种有点奇怪的方式的原因是,它实际上最初并不是用作安全复制字符串的方法。
另一种方法是使用snprintf()作为strcpy()的安全替代品:
snprintf(array2, destination_size, "%s", array1);
(感谢 jxh 的提示。)
snprintf()
没有 strncpy()
存在的问题。 - jxh正如其他人所指出的那样,使用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 */
为什么引入了“衰减为指针值”的语义,是为了实现与C的前身源代码兼容。您可以阅读The Development of the C Language获取详细信息。
array2 = array1;
不起作用的答案。点赞。 - Miljen Mikic您不能分配数组,这些名称是无法更改的常量。
您可以使用以下方式复制内容:
strcpy(array2, array1);
void cstringcpy(char *src, char * dest)
{
while (*src) {
*(dest++) = *(src++);
}
*dest = '\0';
}
.....
char src[6] = "Hello";
char dest[6];
cstringcpy(src, dest);
cstringcpy
函数没有在目标数组中添加空字符。 - chqrliecstringcpy
函数和 strcpy
函数几乎在语义上完全等效,具有相同的缺陷,即没有检查缓冲区溢出。 - chqrlie我建议使用memcpy()来复制数据。
此外,如果我们将一个缓冲区分配给另一个缓冲区,如array2 = array1
,那么两个数组具有相同的内存,并且在arrary1中的任何更改也会反映在array2中。但是如果我们使用memcpy,则两个缓冲区具有不同的数组。我建议使用memcpy(),因为strcpy和相关函数不会复制NULL字符。
#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;
}
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" */
是的,上述代码始终有效,且具有可移植性。
strcpy
或memcpy
。 - Alok Savechar array1[18] = {"abcdefg"};
不是一个正确的字符数组。 - aragaerchar array1[18] = "abcdefg";
或char array1[18] = {'a','b','c','d','e','f','g','\0'};
。 - aragaerchar array1[18] = {"abcdefg"};
是不寻常的,但是完全正确的。 - Daniel Fischer