在 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 数组的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章
从 int 获取单个数字以在 C/C++ 中进行基数排序的最佳方法