C strcpy 字符串指针数组
C strcpy array of string pointers
我有一个这样声明的数组:
char *array[4];
由带字符串的不同函数填充,即 ["one"、"two"、"three"、"four"].
我的目标是将这个数组复制到一个新数组中,不包括最后两个元素,因此 new_array 将包含 ["one"、"two"].
这是我目前尝试过的方法:
int *new_array[2];
for (int i = 0; i < 2; i++){
strncpy(new_array[i], array[i], strlen(array[i]));
}
但收到以下警告:
warning: passing argument 1 of ‘strncpy’ from incompatible pointer type [-Wincompatible-pointer-types]
note: expected ‘char * restrict’ but argument is of type ‘int *’
extern char *strncpy (char *__restrict __dest,
您的代码存在一些问题
首先它声明了一个整数指针数组(因此警告)然后这些指针没有被初始化。 strncpy
不是要调用的正确函数(即使内存已初始化,它也不会以 null 终止字符串),您需要 strdup
进行正确的分配和复制:
char *new_array[2];
for (int i = 0; i < 2; i++){
new_array[i] = strdup(array[i]);
}
(在某些旧系统上,strdup
可能不可用。如果您遇到这种情况,只需使用 new_array[i] = malloc(strlen(array[i]+1));
然后 strcpy(new_array[i],array[i]);
)
这两种方法都分配动态内存,并且在不再使用时需要 free
。
但是如果你只是想存储指针,例如因为 array
包含 文字 而你不打算修改你的字符串,你可以只复制指针:
new_array[i] = array[i];
源和目标不兼容。
字符*数组[4];
整数 *new_array[2];
希望你打错了?
除了让-弗朗索瓦·法布尔 (Jean-François Fabre) 给出的精彩回答之外,我还要指出,即使是已知的大小也会随着程序的发展而改变,因此,以已知的终止符(即 NULL)结束列表很有用或 NaN)。
我假设您刚开始使用 C,但这是一个很好的习惯(将所有事物都视为瞬态并尽量减少代码中的先入之见的习惯)。
虽然人们指出 strdup
不是标准的 C,但它被广泛使用。我会避免它只是为了踢球。我希望你注意到错误检查(过度?也许......但真正的代码应该充满这些东西)。
考虑以下代码(但不要使用它,它可能会稍微损坏):
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char **string_array_dup(char *const *ary) {
int count = 0;
char **copy;
if (!ary)
return NULL;
/* count string items - this is unsafe */
while (ary[count++])
;
if (!count)
return NULL;
/* allocate memory for array and set terminator. */
copy = malloc(sizeof(*copy) * (count + 1));
if (!copy)
perror("ERROR"), exit(errno);
copy[count - 1] = NULL;
/* itterate over array, allocate and copy strings. */
count = 0;
while (ary[count]) {
int register len = (int)strlen(ary[count]);
copy[count] = malloc(len + 1); /* remember NUL byte */
if (!ary[count])
perror("ERROR"), exit(errno);
memcpy(copy[count], ary[count], len + 1); /* copy NUL byte */
count += 1;
}
return copy;
}
void string_array_print(char **ary) {
int count = 0;
while (ary[count]) {
printf("%s ", ary[count++]);
}
printf("\n");
}
void string_array_free(char **ary) {
int count = 0;
/* free each string */
while (ary[count]) {
free(ary[count++]);
}
/* free container */
free(ary);
}
int main(void) {
char *array[] = {
"String", "array", "is", "always", "terminated", "with", NULL,
};
char **copy = string_array_dup(array);
if (!copy)
perror("ERROR"), exit(errno);
string_array_print(copy);
string_array_free(copy);
return 0;
}
顺便说一句,可以优化此代码以仅使用单个 malloc
(或使用 realloc
)和单个 free
- 代价是更复杂的副本过程(并改进数据的局部性和数据访问时间)。
我有一个这样声明的数组:
char *array[4];
由带字符串的不同函数填充,即 ["one"、"two"、"three"、"four"].
我的目标是将这个数组复制到一个新数组中,不包括最后两个元素,因此 new_array 将包含 ["one"、"two"].
这是我目前尝试过的方法:
int *new_array[2];
for (int i = 0; i < 2; i++){
strncpy(new_array[i], array[i], strlen(array[i]));
}
但收到以下警告:
warning: passing argument 1 of ‘strncpy’ from incompatible pointer type [-Wincompatible-pointer-types]
note: expected ‘char * restrict’ but argument is of type ‘int *’
extern char *strncpy (char *__restrict __dest,
您的代码存在一些问题
首先它声明了一个整数指针数组(因此警告)然后这些指针没有被初始化。 strncpy
不是要调用的正确函数(即使内存已初始化,它也不会以 null 终止字符串),您需要 strdup
进行正确的分配和复制:
char *new_array[2];
for (int i = 0; i < 2; i++){
new_array[i] = strdup(array[i]);
}
(在某些旧系统上,strdup
可能不可用。如果您遇到这种情况,只需使用 new_array[i] = malloc(strlen(array[i]+1));
然后 strcpy(new_array[i],array[i]);
)
这两种方法都分配动态内存,并且在不再使用时需要 free
。
但是如果你只是想存储指针,例如因为 array
包含 文字 而你不打算修改你的字符串,你可以只复制指针:
new_array[i] = array[i];
源和目标不兼容。
字符*数组[4];
整数 *new_array[2];
希望你打错了?
除了让-弗朗索瓦·法布尔 (Jean-François Fabre) 给出的精彩回答之外,我还要指出,即使是已知的大小也会随着程序的发展而改变,因此,以已知的终止符(即 NULL)结束列表很有用或 NaN)。
我假设您刚开始使用 C,但这是一个很好的习惯(将所有事物都视为瞬态并尽量减少代码中的先入之见的习惯)。
虽然人们指出 strdup
不是标准的 C,但它被广泛使用。我会避免它只是为了踢球。我希望你注意到错误检查(过度?也许......但真正的代码应该充满这些东西)。
考虑以下代码(但不要使用它,它可能会稍微损坏):
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char **string_array_dup(char *const *ary) {
int count = 0;
char **copy;
if (!ary)
return NULL;
/* count string items - this is unsafe */
while (ary[count++])
;
if (!count)
return NULL;
/* allocate memory for array and set terminator. */
copy = malloc(sizeof(*copy) * (count + 1));
if (!copy)
perror("ERROR"), exit(errno);
copy[count - 1] = NULL;
/* itterate over array, allocate and copy strings. */
count = 0;
while (ary[count]) {
int register len = (int)strlen(ary[count]);
copy[count] = malloc(len + 1); /* remember NUL byte */
if (!ary[count])
perror("ERROR"), exit(errno);
memcpy(copy[count], ary[count], len + 1); /* copy NUL byte */
count += 1;
}
return copy;
}
void string_array_print(char **ary) {
int count = 0;
while (ary[count]) {
printf("%s ", ary[count++]);
}
printf("\n");
}
void string_array_free(char **ary) {
int count = 0;
/* free each string */
while (ary[count]) {
free(ary[count++]);
}
/* free container */
free(ary);
}
int main(void) {
char *array[] = {
"String", "array", "is", "always", "terminated", "with", NULL,
};
char **copy = string_array_dup(array);
if (!copy)
perror("ERROR"), exit(errno);
string_array_print(copy);
string_array_free(copy);
return 0;
}
顺便说一句,可以优化此代码以仅使用单个 malloc
(或使用 realloc
)和单个 free
- 代价是更复杂的副本过程(并改进数据的局部性和数据访问时间)。