gpt4 book ai didi

c - 我是否需要在 for 循环中使用 strcat 检查目标字符串长度

转载 作者:太空宇宙 更新时间:2023-11-04 04:35:09 27 4
gpt4 key购买 nike

char command [][12] = {
{"Attention!!"},
{"About Turn!"},
{"Left Turn!"},
{"right Turn!"},
{"Dismiss!"}
};

int i;
for (i=1; i<5; i++)
{
strcat (command [0], command [i]);
}
printf ("length of command[0]:%ld\nNew string:%s\n", strlen(command[0]), command[0]);

在上面的代码块中,我是否需要检查目标字符串 command[0] 是否有足够的空间容纳其他 4 个字符串?

我没有那样做,但事实证明编译器没有报告任何错误并打印出连接的字符串。

这样用for循环可以吗?

最佳答案

是的,您确实需要考虑目标字符串中的可用空间使用 strcat() 时。事实上,你需要考虑可用的所有字符串操作的空间。如果你不知道有足够的空间,你不安全。

考虑数组:

char command[][12] =
{
{"Attention!!"},
{"About Turn!"},
{"Left Turn!"},
{"Right Turn!"},
{"Dismiss!"}
};

数组的内存是这样的,用$来表示'\0'

+---+---+---+---+---+---+---+---+---+---+---+---+
| A | t | t | e | n | t | i | o | n | ! | ! | $ |
+---+---+---+---+---+---+---+---+---+---+---+---+
| A | b | o | u | t | | T | u | r | n | ! | $ |
+---+---+---+---+---+---+---+---+---+---+---+---+
| L | e | f | t | | T | u | r | n | ! | $ | $ |
+---+---+---+---+---+---+---+---+---+---+---+---+
| R | i | g | h | t | | T | u | r | n | ! | $ |
+---+---+---+---+---+---+---+---+---+---+---+---+
| D | i | s | m | i | s | s | ! | $ | $ | $ | $ |
+---+---+---+---+---+---+---+---+---+---+---+---+

strcat() 的规范说:

The strcat function appends a copy of the string pointed to by s2 (including the terminating null character) to the end of the string pointed to by s1. The initial character of s2 overwrites the null character at the end of s1. If copying takes place between objects that overlap, the behavior is undefined.

你的处理循环是:

for (int i = 1; i < 5; i++)
{
strcat(command[0], command[i]);
}

很明显,您正在调用未定义的行为,因为command[0] 中的扩展 Material 覆盖了 command[1] 的内容。尽管如此,一些常见的实现实际上会表现得明智,但不能保证每次实现都会。

确实,当在带有 GCC 6.3.0 的 macOS Sierra 10.12.2 上运行时,第一个循环的迭代生成一个 Abort trap: 6 错误。这是一个“未定义行为”的完全合法结果。

但是,如果我们“重新实现”strcat() 以达到您预期的行为,你最终得到的是:

+---+---+---+---+---+---+---+---+---+---+---+---+
| A | t | t | e | n | t | i | o | n | ! | ! | A |
+---+---+---+---+---+---+---+---+---+---+---+---+
| b | o | u | t | | T | u | r | n | ! | L | e |
+---+---+---+---+---+---+---+---+---+---+---+---+
| f | t | | T | u | r | n | ! | R | i | g | h |
+---+---+---+---+---+---+---+---+---+---+---+---+
| t | | T | u | r | n | ! | D | i | s | m | i |
+---+---+---+---+---+---+---+---+---+---+---+---+
| s | s | ! | $ | i | s | s | ! | $ | $ | $ | $ |
+---+---+---+---+---+---+---+---+---+---+---+---+

演示代码

#include <ctype.h>
#include <stdio.h>
#include <string.h>

static inline void n_strcat(char *s1, char *s2)
{
memmove(s1 + strlen(s1), s2, strlen(s2) + 1);
}

#ifndef USE_REAL_STRCAT
#undef strcat
#define strcat(s1, s2) n_strcat(s1, s2)
#endif /* USE_REAL_STRCAT */

static void print_bar(int cols)
{
printf(" +");
for (int i = 0; i < cols; i++)
printf("---+");
putchar('\n');
}

static void print_cmd(int rows, int cols, char cmd[rows][cols])
{
print_bar(cols);
for (int i = 0; i < rows; i++)
{
printf(" |");
for (int j = 0; j < cols; j++)
{
unsigned char u = cmd[i][j];
if (!isprint(u))
u = '$';
printf(" %c |", u);
}
putchar('\n');
print_bar(cols);
}
}

int main(void)
{
char command[][12] =
{
{ "Attention!!" },
{ "About Turn!" },
{ "Left Turn!" },
{ "Right Turn!" },
{ "Dismiss!" },
};
enum { CMD_ROWS = sizeof(command) / sizeof(command[0]) };
enum { CMD_COLS = sizeof(command[0]) / sizeof(command[0][0]) };

print_cmd(CMD_ROWS, CMD_COLS, command);

for (int i = 1; i < 5; i++)
strcat(command[0], command[i]);
printf("\nLength of command[0]: %zu\nNew string: [%s]\n\n", strlen(command[0]), command[0]);

print_cmd(CMD_ROWS, CMD_COLS, command);
return 0;
}

程序的输出是上面显示的两个表,中间有以下信息:

Length of command[0]: 51
New string: [Attention!!About Turn!Left Turn!Right Turn!Dismiss!]

关于c - 我是否需要在 for 循环中使用 strcat 检查目标字符串长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31390320/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com