【问题标题】:String unwanted character in cc中的字符串不需要的字符
【发布时间】:2022-01-12 14:43:32
【问题描述】:

我正在尝试将整数添加到字符串中。当我调试我的代码时,一切正常,但是当我正常运行它时,在字符串的开头会打印两个不需要的字符。我该如何避免这种情况?

    int number_of_ints = 5;
    char s[number_of_ints*2];
    char suffix[4];
    for(int i = 1; i <= number_of_ints; i++){
        snprintf(suffix, number_of_ints, "%d*", i);
        strncat(s, suffix, 2);
        printf("%s\n", s);
    }

这是正常构建和运行代码时的输出。

`û1*
`û1*2*
`û1*2*3*
`û1*2*3*4*
`û1*2*3*4*5*

【问题讨论】:

  • 您必须初始化s。您必须为空终止符分配空间。
  • snprintf 的长度参数没有意义。 suffix 只能保存长度为 3 的字符串。

标签: arrays c string char concatenation


【解决方案1】:

C 中的Strings 是一系列非零字节,后跟一个值为 0 的终止字节(空终止字节,'\0')。

您必须调整缓冲区的大小以获得额外的空间,以保证此空终止字节的空间。

您还必须确保缓冲区的内容包含有效的字符串。为此,您可以将缓冲区的第一个元素设置为以空值结尾的字节,从而创建一个长度为零的字符串。

未能初始化缓冲区的内容意味着它将包含不确定的值,并且将此类缓冲区传递给期望有效string 的函数将调用Undefined Behavior

snprintf 的第二个参数最多应该是目标缓冲区的大小。

最后,考虑在适用时使用size_t,因为它是处理内存大小的合适类型(例如,调整variable-length arrayssizeof 运算符解析为这种类型;snprintf 期望这种类型作为它的第二个参数)。

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

int main(void) {
    size_t number_of_ints = 5;
    char s[number_of_ints * 2 + 1];
    char suffix[4];

    s[0] = '\0';

    for (size_t i = 1; i <= number_of_ints; i++) {
        snprintf(suffix, sizeof suffix, "%zu*", i);
        strncat(s, suffix, 2);
        printf("%s\n", s);
    }
}

【讨论】:

    【解决方案2】:

    您的缓冲区的初始化和大小存在一些问题。

    • 缓冲区的大小太短了 1 个字节,这是 0 终止所需的。添加最后一个数字会导致缓冲区溢出和未定义的行为。
    • 此外,计算出的大小只要number_of_ints&lt;10 就足够了,因为它只允许单个数字。
    • 该缓冲区未初始化,我们很可能没有保存空字符串。访问它(通过strcat 等)会调用未定义的行为。
    • 您提供给snprintf 的大小与缓冲区的大小无关。

    您应该应用这些更改:

    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
        int number_of_ints = 5;
        char s[number_of_ints*2+1];
        char suffix[4];
        s[0] = 0;
        for (int i = 1; i <= number_of_ints; i++)
        {
            snprintf(suffix, sizeof(suffix), "%d*", i);
            strncat(s, suffix, 2);
            printf("%s\n", s);
        }
    }
    

    【讨论】:

    • number_of_ints 不是constant(不同于const),因此s 实际上是VLA,并且无法初始化VLA。这个code 不会(不应该)编译,即使你修复了语法错误。
    • @Oka 你是对的。感谢您指出。
    猜你喜欢
    • 2016-06-29
    • 1970-01-01
    • 1970-01-01
    • 2016-08-22
    • 2011-12-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多