2012-04-19 66 views
1

你能说我在我的下面的代码中有什么错误吗?使用scanf的错误

char* line=""; 

printf("Write the line.\n"); 
scanf("%s",line); 
printf(line,"\n"); 

我试图从控制台得到一行作为输入。但每次使用“scanf”时程序崩溃。我不想使用任何std,我完全想避免使用cin或cout。我只是想学习如何使用scanf()完成一行输入。

谢谢。

回答

6

你需要为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); 
+0

其实我知道你在说什么,但我只是想避免使用std。 – 2012-04-19 11:52:34

+0

那么为什么这个标记为C++? – chris 2012-04-19 12:01:59

+0

在C中,您可以设置一个限制。 scanf(“%1023s”,line); 你可以用C++来做到这一点吗? – 2012-04-19 12:05:44

3

空间不是分配给line你需要做的是这样

char *line = malloc(); 

Char line[SOME_VALUE]; 

目前line是一个字符串字面量差的指针指向。并且覆盖字符串文字可能导致未定义的行为

+2

是的,即使是char * line =“VERY_LONG_STRING_HERE”;会失败,与'line'指向一个空字符串无关。 – amit 2012-04-19 11:47:03

+0

我还在更新@amit :) – 2012-04-19 11:48:52

+0

是的..这是更好的。谢谢。:) – 2012-04-19 12:00:37

1

您正试图改变一个string literal,这在C酶切未定义行为,并在C++试图写到一个const内存。

为了克服它,你可能想分配char[]并将其分配给line - 或者如果它是C++ - 使用std::string,避免了很多痛苦。

1

你应该为line分配足够的内存:

char line[100]; 

例如。

+0

看起来像Java语法?!? – trojanfoe 2012-04-19 11:47:12

+0

哦,对不起!更正它。 – 2012-04-19 11:47:49

0

指针line它应该指向字符数组的起始位置,它将容纳字符串读取,实际上是指向其内容不可修改的字符串文字(空字符串)。这导致了一个未定义的行为,表现为您的案例中的崩溃。

要修复这种变化的定义:

char line[MAX]; // set suitable value for MAX 

和atmost读MAX-1个字符的进入line

0

变化:

char* line=""; 

char line[max_length_of_line_you_expect]; 
-1

scanf试图写入大于预留更多的字符d通过line。尝试保留比您期望的行更多的字符,正如上面的答案所指出的那样。

+3

它与它无关。即使分配给'line'的字符串文字中有足够的字符,它仍然会失败,因为'line'指向字符串文字。 – amit 2012-04-19 11:50:59

+0

这是真的@amit。尝试分配给字符串文字是导致此代码失败的主要原因。但是解决这个问题之后,还应该检查数组是否至少具有与'scanf'相同的大小。 – 2012-04-19 13:33:52

3

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; 
} 
1

scanf呼叫的%s转换指定期望其相应的参数为指向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()