关于C#:为什么scanf把字符串放到char数组中,直接输入不行?

Why does scanf put a string into a char array while directly inputting it does not work?

这个问题很难命名。

基本上我有一个具有自己结构的数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
typedef struct Video
{
    unsigned id;
    char title[90];
    char producer[60];
}Video;

Video arrayVideo[7];

int main()
{
    scanf("%s", arrayVideo[0].title);
    printf("%s", arrayVideo[0].title);
}

此代码将打印出我在 scanf 过程中编写的任何内容。

这个对 int main 的小改动;

1
2
3
4
5
 int main()
{
    arrayVideo[0].title[90] = ("Hello");
    printf("%s", arrayVideo[0].title);
}

什么都没有。控制台只是输出执行时间和正常业务。不输出"Hello"


第二个给你两个警告,告诉你出了什么问题:

1
2
3
4
5
6
7
t.c: In function ‘main’:
t.c:14:29: warning: assignment makes integer from pointer without a cast [enabled by default]
     arrayVideo[0].title[90] = ("Hello");
                             ^
t.c:14:24: warning: array subscript is above array bounds [-Warray-bounds]
     arrayVideo[0].title[90] = ("Hello");
                        ^

第一个警告告诉您,您正在尝试将一个指针(指向字符串 "hello")存储到 title 数组的单个 char 中,第二个警告告诉您它无论如何都超出了范围, 所以几乎可以做任何事情,尽管在这种情况下它可能只是写入 producer 数组的第一个字符。

道德:始终启用编译器可以发出的所有警告,并注意它们。


这个问题实际上源于对指针对字符串的作用的混淆。 char title[90] 是一个存储 90 个 char 的字符数组。 title 是指向该数组的第一个元素的指针,而 title[90] 是指向数组末尾之后的一个元素的指针(因为数组索引从 0 开始,title[89] 是最后一个元素)

因此,如果我们分解这一行中发生的事情:

1
    arrayVideo[0].title[90] = ("Hello");

左边是指针类型,它指向arrayVideo中的第一个元素,它是一个结构,然后在该结构中指向字符,该字符在title的第一个元素之后的90个元素中,请注意,这是 91 年代元素。右侧是 const char* 类型的字符串文字。目前,这段代码只是在数组末尾分配一个指针,以指向 "hello" 字符串文字的开头地址。它不会像您希望的那样将字符串的内容复制到您的数据结构中。我有点惊讶您在编译时没有收到编译器的警告,请尝试在启用所有警告的情况下进行编译。

要正确复制字符串的内容,您需要像这样使用 strcpy

1
strcpy(arrayVideo[0].title,"hello")

这里 strcpy 的目标是 title 数组的开头,源来自 const char* 字符串文字 "hello".