在 C/C++ 中清除 char 数组的最佳方法是啥?

Posted

技术标签:

【中文标题】在 C/C++ 中清除 char 数组的最佳方法是啥?【英文标题】:What is the best way of clearing a char array in C/C++?在 C/C++ 中清除 char 数组的最佳方法是什么? 【发布时间】:2018-02-09 16:05:22 【问题描述】:

我一直在寻找在 C/C++ 中清空 char 数组的方法。我想出了这个代码:

char testName[20];   

for(int i = 0; i < sizeof(testName); ++i)

  testName[i] = (char)0;
  

它已经工作了一段时间,但是当我尝试strlen时,结果总是比输入的单词多两个。例如,我输入单词dog,输出将是五个。为什么呢?我的 char 数组没有被清除吗?

这是我的代码:

char testName[20];
void loop()

  if(Serial.available())
  
    Serial.println("Waiting for name...");
    index = 0;
    for(int i = 0; i < sizeof(testName); ++i)
    
        testName[i] = (char)0;
    
    while(Serial.available())
    
      char character = Serial.read();
      testName[index] = character;
      index++;
    
    Serial.print("Name received: ");
    Serial.println(testName);
    Serial.print("The sentence entered is ");
    Serial.print(strlen(testName));
    Serial.println(" long");
    delay(1000);
   
  delay(1000);

输出截图:

输出为文本:

Name received: dog

The sentence entered is 5 characters long

【问题讨论】:

你确定你没有在输入的最后得到\r\n吗? 最好的办法是根本不使用 char 数组。而是使用 std::string. 阅读memset的文档。 @manni66 因为你的建议完全错误。 @manni66,没有。字符数组通常比std::string 更合适。另外,你的语言不好。 【参考方案1】:

不要在现代 C++ 中使用 C 风格的数组。当您需要一个固定大小的数组时,请改用std::array。从内存存储的角度来看,它们是相同的。

然后您可以使用以下命令清除数组:myarray.fill('\0')

【讨论】:

【参考方案2】:

如果您对“清空字符数组”的定义是将数组的所有元素设置为零,则可以使用std::memset

这将允许你写这个而不是你的清晰循环:

const size_t arraySize = 20;  // Avoid magic numbers!
char testName[arraySize];
memset(&(testName[0]), 0, arraySize);

至于strlen()的“奇怪”结果:

strlen(str) 返回"(...) str 指向的字符数组中第一个元素指向的字符数,不包括第一个空字符"。这意味着,它将计数字符,直到找到零为止。

检查您传递给strlen() 的字符串的内容 - 那里可能有从输入流中读取的白色字符(例如\r\n)。

另外,一个建议 - 考虑使用 std::string 而不是普通的 char 数组。


小记:memset() 通常针对高性能进行了优化。如果这不是您的要求,您也可以使用std::fill,这是一种更像 C++ 的方式来填充任何数组:

char testName[arraySize];
std::fill(std::begin(testName), std::end(testName), '\0');

std::begin()(和std::end)适用于编译时大小的数组。


另外,为了回答@SergeyA 的评论,我建议阅读this SO post 和this answer。

【讨论】:

@SergeyA 我已经用std::fill 版本更新了我的答案。但是std::memset由于其优化的实现而经常被使用,所以绝对应该提到它。我建议使用std::string,但由于我们这里有一个带有纯char 数组的代码,所以恕我直言,memset 的错误使用是最不值得关注的。 std::fill 不能被优化掉; memset 可以。我很确定 memset 也被允许一次写入大于一个字节的块;而 std::fill 不是。 @SergeyA 当任务是设置 C 风格 char 数组的内容时,我绝不会责怪提出 memset 的人。 @SergeyA 因为允许和“这个编译器做或不做”是不同的;尤其是当它没有 @MichaelWalz 和 std::fill 要么专门将 memset 用于 POD 类型,要么优化器在识别模式时动态生成优化代码。【参考方案3】:

另一种用零填充数组的快速方法,仅在初始化时:

char testName[20] = ;

一样

char testName[20] = 0;

由于它是 C99 功能,编译器可能会抱怨以下内容

warning: ISO C forbids empty initializer braces

更多here.

不管怎样,看 OP 代码,根本不需要初始化/填充数组,最好这样:

#define MAX_LENGTH 20
char testName[MAX_LENGTH];
void loop()

  if(Serial.available())
  
    Serial.println("Waiting for name...");
    index = 0;
    while(Serial.available())
    
      if(index < MAX_LENGTH) 
          testName[index++] = Serial.read();
    
    if(index < MAX_LENGTH)
    
      testName[index] = 0;
      Serial.print("Name received: ");
      Serial.println(testName);
      Serial.print("The sentence entered is ");
      Serial.print(strlen(testName));
      Serial.println(" long");
    
    else
      Serial.print("Name too long ...");

    delay(1000);
   
  delay(1000);
 

【讨论】:

只擅长定义。不能在其他地方使用。 您不能以这种方式“清除”现有的零数组。 我会删除这个答案,这真的毫无意义,因为 OP 显然想在他的循环中填充数组。 问题说:emptying a char array in C++,代码明确表明需要对已经存在的数组执行clear,这个答案的第一句话是:"(...) 用零填充数组的快速方法,仅在初始化时"... 我认为我的答案符合 OP 的需要,因为发布的代码,而不是问题。

以上是关于在 C/C++ 中清除 char 数组的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 memset 清除 char 数组 [重复]

从 int 获取单个数字以在 C/C++ 中进行基数排序的最佳方法

C / C ++如何复制没有嵌套循环的多维char数组?

C语言 unsigned short 如何相互转 signed char

在 C 中将字符串数组转换为 Int 数组的最佳方法

用另一个数组替换部分数组的最佳方法[重复]