从字符指针初始化字符数组

3

我的问题应该相当简单。

我需要给一个函数传递一个预定义长度的字符数组,但是我只有一个变长的字符指针,但不超过我的数组长度。

这里是代码:

#define SIZE_MAX_PERSON_NAME 50
char person[SIZE_MAX_PERSON_NAME];
char* currentPerson = "John";

现在我该如何将John添加到person数组中,同时将数组的其余部分设置为0(/NUL)?

这样我就会有:

BINARY DATA: "John/NUL/NUL/NUL/NUL/NUL/NUL/NUL/NUL/NUL/NUL/NUL/NUL/NUL/NUL....."

在我的记忆中?

如果这个问题太傻了,那我很抱歉,但是我现在似乎找不到解决方案。


3
为什么不使用 std::string - Cheers and hth. - Alf
使用旧的C库 - Vinz
2
重复?使用strcpy函数。http://en.cppreference.com/w/c/string/byte/strcpy - Casper Beyer
1
@user2334932 谁告诉你不能使用std::stringconst char*参数传递到其他地方?你听说过std::string::c_str()吗? - πάντα ῥεῖ
3
标题显示 C,海报显示 C,代码看起来也像是 C,为什么回答却是 C++ 呢? ;) - Casper Beyer
显示剩余5条评论
4个回答

4
首先,对固定大小的数组进行零初始化:
// Using memset here because I don't know if the whole copy operation can or will be used
// multiple times. We want to be sure that the array is properly zero-initialized if the next
// string to copy is shorter than the previous.
memset(person, '\0', SIZE_MAX_PERSON_NAME);

然后,将变长字符串复制到其中:
strcpy(person, currentPerson);

如果您不确定currentPerson是否适合person
strncpy(person, currentPerson, SIZE_MAX_PERSON_NAME - 1);

请注意,strncpy在拷贝完字符串后也会将数组中剩余的字节清零。
strlen(currentPerson) < SIZE_MAX_PERSON_NAME - 1

所以您基本上有这两个选择:
memset(person, '\0', SIZE_MAX_PERSON_NAME);
strcpy(person, currentPerson);

或者:
strncpy(person, currentPerson, SIZE_MAX_PERSON_NAME - 1);
person[SIZE_MAX_PERSON_NAME - 1] = '\0';

2
为什么要使用 memset 而不是只使用 char person[SIZE_MAX_PERSON_NAME] = {'\0'}; - 101010
@40two 这也可以,但只能在初始化时使用,在使用memset(甚至bzero)时,没有这样的限制。 - Chnossos
使用 memset(而不是更短、更简单、更安全的 C++ 大括号初始化)与将 strncopy 用作“更安全的版本”极其不协调。这里存在极大的不和谐。我的耳朵! - Cheers and hth. - Alf
2
永远不要使用strncpy作为更安全的strcpy它并不是! 另外,sizeof(char)读作“我不知道任何C语言…” - Deduplicator
在我的回答中,我并不是说strncpy本身更安全,只有在调用memset之后,这种特定的使用才更安全,因为我们现在可以确定缓冲区已经被初始化为零。但我明白你的想法,也感谢你让我更了解sizeof。我会编辑我的回答。 - Chnossos
显示剩余3条评论

2

在发布此回答后,问题的标签已从C++更改为C。

使用std::string,如下所示:

// "using namespace std;" or "using std::string;", then:

string const person = currentPerson;
old_c_function( person.c_str() );

如果你要在 C 语言级别上进行操作(我建议你不要这样做),首先应该用一个类型常量替换掉不必要的 #define

int const max_person_name_size = 50;

然后将数组进行零初始化:

char person[max_person_name_size] = {};

(注意:这里没有愚蠢的memset。) (还要注意:这个清零只是一种预防措施。你想要它,但并不是真正必要的,因为strcpy会确保一个尾随的零字节。)
然后只需复制字符串即可:
assert( strlen( current_person ) < max_person_name_size );
strcpy( person, current_person );

但不要这样做。使用std::string代替。
更新: 做其他事情几分钟后,我意识到这个答案和其他所有答案一样,都完全不正确。OP在其他地方的评论中表示:

"我在库中有一个只接受字符数组而不是字符指针的函数。

因此,显然这是一个误解。

唯一有意义的方式是如果该数组由函数修改,那么std::string::c_str()就不是一个解决方案。但是,如果将其长度设置为足够满足C函数的长度,则仍然可以使用std::string。可以这样做:

person.resize( max_person_name_size );
foo( &person[0] );                // Assuming foo modifies the array.
person.resize( strlen( person.c_str() ) );

0
使用字面值,您可以执行以下操作:
char person[SIZE_MAX_PERSON_NAME] = "John";

如果C字符串不是字面值,你必须使用strcpy进行复制。
strcpy(person, currentPerson);

0

这是 strncpy 存在的唯一原因:

将一个字符串(最长到 0 终止符或缓冲区结尾)放入固定长度的数组中,然后清空剩余部分。
这并不保证 0 终止符,所以避免将其用于其他任何操作。

7.24.2.4 The strncpy function

#include <string.h>
char *strncpy(char * restrict s1, const char * restrict s2, size_t n);

2 The strncpy function copies not more than n characters (characters that follow a null character are not copied) from the array pointed to by s2 to the array pointed to by s1.308) If copying takes place between objects that overlap, the behavior is undefined.
3 If the array pointed to by s2 is a string that is shorter than n characters, null characters are appended to the copy in the array pointed to by s1, until n characters in all have been written.
4 The strncpy function returns the value of s1.


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接