【问题标题】:C Initialize Character Array from Character PointerC从字符指针初始化字符数组
【发布时间】:2014-09-26 10:22:28
【问题描述】:

我的问题应该很简单。

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

代码如下:

#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....."

在我的记忆中?

对不起,如果这太愚蠢了,但我现在似乎找不到解决方案。

【问题讨论】:

  • 你为什么不用std::string
  • 使用旧的 C 库
  • @user2334932 谁告诉你的,你不能使用std::string 在别处传递const char* 参数?听说过std::string::c_str()吗?
  • 标题说 C,海报说 C,代码看起来像 C 什么给出了 C++ 答案? ;)

标签: c arrays pointers char initialization


【解决方案1】:

首先,对固定大小的数组进行零初始化:

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

【讨论】:

  • 为什么memset 而不仅仅是char person[SIZE_MAX_PERSON_NAME] = {'\0'};
  • @40two 这也有效,但仅在初始化时,使用 memset(甚至 bzero),没有这样的限制。
  • memset(而不是更短、更简单和更安全的 C++ 花括号初始化)jar 使用 strncopy 作为“更安全的版本”。这里极度不和谐。我的耳朵!
  • 非常感谢 Chnossos。我知道 C++ 的标准有所改进。您有时仍然需要处理旧图书馆并回到旧标准。这似乎是最好的方法。已回答的问题
  • 永远不要将strncpy用作更安全的 strcpy不是!另外,sizeof(char)读作“我不知道任何 C...”
【解决方案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 在a comment elsewhere 中声明

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

因此,显然这完全是一种误解。

唯一有意义的方法是如果数组被函数修改,那么std::string::c_str() 不是解决方案。但是 std::string 仍然可以使用,如果它的长度设置为足以满足 C 函数的长度。可以这样走:

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

【讨论】:

    【解决方案3】:

    使用文字,你可以这样做:

    char person[SIZE_MAX_PERSON_NAME] = "John";
    

    如果 c-string 不是文字,则必须使用 strcpy 进行复制

    strcpy(person, currentPerson);
    

    【讨论】:

      【解决方案4】:

      这是strncpy存在的唯一原因:

      将一个字符串(直到 0 终止符或缓冲区末尾)放入一个固定长度的数组并将其余部分归零。
      这不能确保 0 终止,因此 避免其他任何事情。

      7.24.2.4 strncpy 函数

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

      2 strncpy 函数复制的字符不超过 n 字符不会被复制)从s2 指向的数组到s1 指向的数组。308) 如果复制发生在重叠的对象之间,则行为未定义。
      3 如果s2 指向的数组是一个短于n 字符的字符串,则将空字符附加到s1 指向的数组的副本中,直到n 字符全部写入。
      4 strncpy函数返回s1的值。

      【讨论】:

        猜你喜欢
        • 2010-12-12
        • 2015-08-03
        • 2017-11-03
        • 1970-01-01
        • 1970-01-01
        • 2016-06-27
        • 2011-06-17
        • 2015-08-12
        相关资源
        最近更新 更多