C:如何以更简洁的方式将空终止符复制到结构成员?

发布于 2024-11-05 04:32:00 字数 446 浏览 6 评论 0原文

本质上,我对一个字符串进行标记,并将找到的字符串strncpy转换为结构成员,即 stringid。它当然存在缺乏终止的问题,我为它添加了一个额外的数组空间,我不知道如何正确添加它。

我是这样做的:

my_struct[iteration].stringID[ID_SIZE-1] = '\0' //updated

我不确定这是否真的有效,在我看来,它看起来很糟糕。

Str(n) 复制空字符或 0 会导致 GCC 和 MinGW 生成警告:

warning: null argument where non-null required (arg 2)

我是否不知道如何以干净的方式执行此操作?我正在考虑将成员数组设置为全零,然后复制字符串以很好地适应空终止。您有什么建议或做法吗?

Essentially I am tokenizing a string and strncpying the string found to a structure member, i.e. stringid. It of course suffers from the problem of lack of termination, I have added an extra array space for it, I've no clue how to add it properly.

I had done it like so:

my_struct[iteration].stringID[ID_SIZE-1] = '\0' //updated

I am unsure if that really works, it looks horrible IMO.

Str(n)cpying a null character, or 0, results in a warning generated by GCC and MinGW:

warning: null argument where non-null required (arg 2)

Am I blind on how to do this in a clean manner? I was thinking of memsetting the member array to all zeros, and then copying the string in to nicely fit with null termination. Do you have any suggestions or practises?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

樱娆 2024-11-12 04:32:00

有两件事:

  1. 请注意 strncpy() 具有非常意外的语义,如果字符串未完全填充,它将始终填充 0 缓冲区,如果字符串完全填充缓冲区,则不会终止字符串。这两个都很奇怪,我建议不要使用它。
  2. 永远不要用数组的大小来索引数组,就像 stringID[ID_SIZE] 似乎正在做的那样;这是越界的。

最好的解决方案是编写一个不太奇怪的自定义版本的 strncpy() ,或者(如果您知道输入的长度)只需使用 strcpy()

更新:如果输入标记的长度是静态的,但由于标记化过程,它们在源缓冲区中不是以 0 结尾,则只需使用 memcpy()和手动终止:

const char * token = ...; /* Extract from tokenization somehow. Not 0-terminated. */
const size_t token_length = ... /* Perhaps from tokenization step. */
memcpy(my_struct[iteration].stringID, token, token_length);
my_struct[iteration].stringID[token_length] = '\0';

我认为没有必要将上面的内容“包装”在宏中。

Two things:

  1. Beware that strncpy() has very unexpected semantics, it will always 0-fill the buffer if not totally filled by the string, and it will not terminate the string if it completely fills the buffer. Both of these are weird enough that I recommend against using it.
  2. Never index an array with it's size, like stringID[ID_SIZE] seems to be doing; that is out of bounds.

The best solution is to write a custom version of strncpy() that is less weird, or (if you know the length of the input) just use strcpy().

UPDATE: If the length of your input tokens is static, but they're not 0-terminated in the source buffer due to your tokenization process, then just use memcpy() and manual termination:

const char * token = ...; /* Extract from tokenization somehow. Not 0-terminated. */
const size_t token_length = ... /* Perhaps from tokenization step. */
memcpy(my_struct[iteration].stringID, token, token_length);
my_struct[iteration].stringID[token_length] = '\0';

I don't see a need to "wrap" the above in a macro.

我不在是我 2024-11-12 04:32:00

实际上,按照您建议的方式进行 null 终止一点也不可怕,我个人非常喜欢它。

在我看来,最好的方法是以类似的方式将其定义为宏:

// for char* blah;
#define TERMINATE_DYNAMIC_STRING(str, len) str[len] = '\0';
// for char mytext[] = "hello";
#define TERMINATE_STRING(str) str[sizeof(str)/sizeof(str[0]) - 1] = '\0';

然后您可以在代码中随心所欲地使用它。

在 Windows 上,Microsoft 为您提供了以下在复制字符串时以 null 终止的函数: StringCchCopy

Actually, null terminating the way you suggested isn't horrible at all and I personally very much like it.

The best way, in my opinion, would be to define it as a macro in similar fashion:

// for char* blah;
#define TERMINATE_DYNAMIC_STRING(str, len) str[len] = '\0';
// for char mytext[] = "hello";
#define TERMINATE_STRING(str) str[sizeof(str)/sizeof(str[0]) - 1] = '\0';

Then you can use it all around your code as much as you want.

On Windows Microsoft gives you the following functions which null terminate when copying string: StringCchCopy

陌伤浅笑 2024-11-12 04:32:00

正如其他人所指出的,strncpy 具有奇怪的语义。进行有界字符串复制的惯用方法是 strncat 到一个空字符串上:

my_struct[iteration].stringID[0] = '\0';
strncat(my_struct[iteration].stringID, src, ID_SIZE-1);

这总是附加一个终止 NUL(并且最多填充 ID_SIZE 字符,包括 NUL)。

As others have noted, strncpy has odd semantics. The idiomatic way to do a bounded string copy is to strncat onto an empty string:

my_struct[iteration].stringID[0] = '\0';
strncat(my_struct[iteration].stringID, src, ID_SIZE-1);

This always appends a terminating NUL, (and fills at most ID_SIZE characters including the NUL).

佞臣 2024-11-12 04:32:00

我最终编写了一个 strncpyz(char* pszTo, char* pszTo, size_t lSize) 函数来强制 NULL 终止。如果您有一个库可以放入它,那么这会非常有效。使用它还需要最少的代码更改。

我不热衷于宏方法,因为有人会传递指向错误宏的指针。

I ended-up writing a strncpyz(char* pszTo, char* pszTo, size_t lSize) function that forces the NULL termination. This works pretty-well if you have a library to put it in. Using it also requires minimal code changes.

I'm not keen on the macro approach because somebody will pass a pointer to the wrong macro.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文