你能说我下面的代码有什么错误吗?
char* line="";
printf("Write the line.\n");
scanf("%s",line);
printf(line,"\n");
我试图从控制台获取一行作为输入。但是每次使用“scanf”时程序都会崩溃。我不想使用任何标准,我完全想避免使用 cin 或 cout。我只是想学习如何使用 scanf() 将整行作为输入。
谢谢你。
您需要为输入字符串分配空间,因为sscanf()
它本身不能这样做:
char line[1024];
printf("Write the line.\n");
scanf("%s",line);
printf(line,"\n");
然而,这是危险的,因为它可能会溢出缓冲区,因此是一个安全问题。改用std::string
:
std::string line;
std::cout << "Write the line." << std::endl;
std::cin >> line;
std::cout << line << std::endl;
或者:
std::getline (std::cin, line);
未分配空间line
您需要执行以下操作
char *line = malloc();
或者
Char line[SOME_VALUE];
当前line
是指向字符串文字的不良指针。覆盖字符串文字可能会导致未定义的行为。
scanf() 与行不匹配。%s 匹配一个单词。
#include <stdio.h>
int main() {
char word[101];
scanf("%100s", word);
printf("word <%s>\n", word);
return 0;
}
输入:
this is a test
输出:
word <this>
匹配行使用%100[^\n"]
,这意味着 100 个字符不是换行符。
#include <stdio.h>
int main() {
char word[101];
scanf("%100[^\n]", word);
printf("word <%s>\n", word);
return 0;
}
您正在尝试更改字符串文字,这在 C 中会导致未定义的行为,而在 C++ 中则试图写入 const 内存。
为了克服它,您可能想要分配 achar[]
并将其分配给line
- 或者如果它是 C++ - 使用std::string
并避免很多痛苦。
您应该为以下内容分配足够的内存line
:
char line[100];
例如。
调用中的%s
转换说明符scanf
期望其对应的参数指向一个类型的可写缓冲区,该缓冲区大到足以容纳输入。char [N]
N
您已初始化line
为指向字符串字面量""
。这有两个问题。首先是尝试修改字符串文字的内容会导致未定义的行为。语言定义没有指定字符串文字的存储方式;它只指定它们的生命周期和可见性,一些平台将它们放在只读内存段中,而另一些平台将它们放在可写数据段中。因此,尝试在一个平台上修改字符串文字的内容可能会由于访问冲突而彻底崩溃,而在另一个平台上可能会正常工作。语言定义没有规定应该做什么当您尝试修改字符串文字时发生;事实上,它明确地保留了这种行为undefined,因此编译器可以自由地以任何它想要的方式处理这种情况。一般来说,最好总是假设字符串文字是不可写的。
另一个问题是包含字符串文字的数组的大小只能容纳 1 个字符,即 0 终止符。请记住,C 风格的字符串存储为 的简单数组char
,并且当您添加更多字符时,数组不会自动增长。
您将需要声明line
为数组char
或动态分配内存:
char line[MAX_INPUT_LEN];
或者
char *line = malloc(INITIAL_INPUT_LEN);
动态分配内存的优点是您可以根据需要调整缓冲区的大小。
为了安全起见,您应该指定要读取的最大字符数;如果您的缓冲区大小可容纳 21 个字符,则将您的scanf
调用写为
scanf("%20s", line);
如果输入流中的字符多于line
可以容纳的字符,scanf
则会将这些额外的字符写入后面的内存中line
,这可能会破坏一些重要的东西。缓冲区溢出是一种常见的恶意软件利用,应该避免。
另外,%s
不会让你完整;即使使用字段宽度说明符,它也会读取到下一个空格字符。您要么需要使用不同的转换说明符,%[^\n]
要么fgets()
改为使用。
应该指向将保存读取的字符串的字符数组的开头的指针line
实际上指向其内容不可修改的字符串文字(空字符串)。这会导致未定义的行为,在您的情况下表现为崩溃。
要解决此问题,请将定义更改为:
char line[MAX]; // set suitable value for MAX
并将最多 MAX-1 个字符读入line
.
改变:
char* line="";
到
char line[max_length_of_line_you_expect];
scanf
正在尝试写入比 . 保留的字符更多的字符line
。正如上面的答案所指出的,尝试保留比您期望的行更多的字符。