CS50 IDE:printf返回额外字符

CS50 IDE:printf返回额外字符,c,string,cs50,C,String,Cs50,我对CS50 IDE中的printf函数有问题。当我使用printf打印字符串(在这段代码中是salt)时,会输出原始参数(argv)中不存在的额外字符 下面是我的代码。任何帮助都将不胜感激。多谢各位 #include <cs50.h> #include <stdio.h> #include <string.h> #include <ctype.h> #include <stdlib.h> int main(int argc, str

我对CS50 IDE中的printf函数有问题。当我使用printf打印字符串(在这段代码中是salt)时,会输出原始参数(argv)中不存在的额外字符

下面是我的代码。任何帮助都将不胜感激。多谢各位

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

int main(int argc, string argv[])
{
    // ensuring that only 1 command-line argument is inputted
    if (argc != 2)
    {
        return 1;
    }
    char salt[2];
    for (int i = 0; i < 2; i++)
    {
        char c = argv[1][i];
        salt[i] = c;
    } 

    printf("the first 2 characters of the argument is %s\n", salt);

}
#包括
#包括
#包括
#包括
#包括
int main(int argc,字符串argv[])
{
//确保只输入1个命令行参数
如果(argc!=2)
{
返回1;
}
焦盐[2];
对于(int i=0;i<2;i++)
{
字符c=argv[1][i];
盐[i]=c;
} 
printf(“参数的前两个字符是%s\n”,salt);
}

在您的例子中,
salt
至少比字符串少一个元素,除非
argv[1]
只是一个元素,否则它不包含空终止符

您需要分配空间来容纳空终止符,并实际放置一个空终止符,以便能够使用
salt
作为字符串,这与
%s
转换说明符的参数在
printf()情况下的预期一样

否则,与字符串相关的函数和操作(本质上依赖于将有一个空终止符来标记
char
数组的结束(即,标记可访问的有效内存的结束))将尝试访问超出导致错误的有效内存。一旦你击中了UB,什么都不能保证

因此,考虑到您想要使用

“…参数的前2个字符…”


您需要将
salt
设置为3元素
char
数组,并确保
salt[2]
包含空终止符,如
'\0'

在您的情况下,
salt
至少比字符串少一个元素,除非
argv[1]
仅包含一个元素,否则它不包含空终止符

您需要分配空间来容纳空终止符,并实际放置一个空终止符,以便能够使用
salt
作为字符串,这与
%s
转换说明符的参数在
printf()情况下的预期一样

否则,与字符串相关的函数和操作(本质上依赖于将有一个空终止符来标记
char
数组的结束(即,标记可访问的有效内存的结束))将尝试访问超出导致错误的有效内存。一旦你击中了UB,什么都不能保证

因此,考虑到您想要使用

“…参数的前2个字符…”


您需要将
salt
设置为3元素
char
数组,并确保
salt[2]
包含空终止符,如
'\0'

您在
salt
中缺少字符串终止符

不知何故,计算机需要知道字符串在内存中的结束位置。它通过读取直到遇到NUL字节(值为零的字节)来执行此操作

您的数组
salt
正好有2个字节的空间,在它们之后,随机垃圾就存在了,它恰好是数组之后内存中的下一个垃圾。由于没有字符串终止符,计算机也将读取此垃圾,直到遇到NUL字节

您只需在数组中包含这样一个字节,如下所示:

char salt[3] = {0};

这将使
salt
长一个字节,而
{0}
{0,0,0}
的缩写,它将用全零初始化数组的内容。(或者,您可以使用
char salt[3];
,然后使用
salt[2]=0;
手动将最后一个字节设置为零)

您在
salt
中缺少字符串终止符

不知何故,计算机需要知道字符串在内存中的结束位置。它通过读取直到遇到NUL字节(值为零的字节)来执行此操作

您的数组
salt
正好有2个字节的空间,在它们之后,随机垃圾就存在了,它恰好是数组之后内存中的下一个垃圾。由于没有字符串终止符,计算机也将读取此垃圾,直到遇到NUL字节

您只需在数组中包含这样一个字节,如下所示:

char salt[3] = {0};

这将使
salt
长一个字节,而
{0}
{0,0,0}
的缩写,它将用全零初始化数组的内容。(或者,您可以使用
char-salt[3];
然后使用
salt[2]=0;
手动将最后一个字节设置为零)

C字符串必须以null结尾,但您的字符串不是。显示原始参数(argv)。
printf(“参数的前两个字符是%s\n”,salt)
-->
printf(“参数的前两个字符是%.2s\n”,salt)C字符串必须以null结尾,但您的字符串不是。请显示原始参数(argv)。
printf(“参数的前两个字符是%s\n”,salt)
-->
printf(“参数的前两个字符是%.2s\n”,salt)谢谢你的回复。简单的问题只是为了清楚的理解:为什么在初始化
char salt[3]={0}之后我要执行
printf(%s\n,salt)
salt[2]
中的
0
不是字符“0”,而是字符串的空终止符?因为字符
0
将在此上下文中写入
'0'
,该值等于
48
。尝试
chartest[6]={'1',0',49,48,1,0};sprintf(“%s\n”,test)以了解我的意思。(提示:笑脸的值为
1
)。明白了,非常感谢。然而,在那个示例中,您的意思是
printf(“%s\n”,test)
,而不是
sprintf
,对吗?如果我错了,请纠正我:
sprintf
需要为其分配一个缓冲区,在该示例中没有分配缓冲区。