如何使用C从键盘读取字符串?

mai*_*ved 51 c string scanf

我想读取用户输入的字符串.我不知道字符串的长度.由于CI中没有字符串声明指针:

char * word;
Run Code Online (Sandbox Code Playgroud)

并用于scanf从键盘读取输入:

scanf("%s" , word) ;
Run Code Online (Sandbox Code Playgroud)

但是我遇到了分段错误.

当长度未知时,如何从C中读取键盘输入?

Pau*_*l R 54

你没有分配存储空间word- 它只是一个悬空指针.

更改:

char * word;
Run Code Online (Sandbox Code Playgroud)

至:

char word[256];
Run Code Online (Sandbox Code Playgroud)

请注意,256是一个任意选择 - 此缓冲区的大小需要大于您可能遇到的最大可能字符串.

另请注意,fgets是一个更好(更安全)的选项,然后scanf用于读取任意长度的字符串,因为它接受一个size参数,这反过来有助于防止缓冲区溢出:

 fgets(word, sizeof(word), stdin);
Run Code Online (Sandbox Code Playgroud)

  • -1:他说长度是未知的,你选择的"256"完全是任意的,所以你(两年半前)就教他如何写缓冲区溢出和巨大的安全漏洞.恭喜. (22认同)
  • 感谢你(有些迟来的)批评 - 我现在更新了答案,不仅涵盖了悬空指针,还包括建议使用`fgets`而不是`scanf`来进行任意长度的字符串输入. (8认同)
  • 啊,太好了.:) +1.至于它是迟来的,公平地说,glglgl在下面说了,就在你发布答案后的三十四分钟!;) (4认同)

glg*_*lgl 19

我不明白为什么有建议在scanf()这里使用.scanf()只有在格式字符串中添加限制参数时才是安全的 - 例如%64s左右.

更好的方法是使用char * fgets ( char * str, int num, FILE * stream );.

int main()
{
    char data[64];
    if (fgets(data, sizeof data, stdin)) {
        // input has worked, do something with data
    }
}
Run Code Online (Sandbox Code Playgroud)

(另)

  • 做那个`stdin`,而不是'STDIN`. (4认同)

Dav*_*ica 15

当从任何不知道长度的文件(包括stdin)读取输入时,通常最好使用getline而不是scanffgets因为getline将自动处理字符串的内存分配,只要您提供空指针来接收输入的字符串.这个例子将说明:

#include <stdio.h>
#include <stdlib.h>

int main (int argc, char *argv[]) {

    char *line = NULL;  /* forces getline to allocate with malloc */
    size_t len = 0;     /* ignored when line = NULL */
    ssize_t read;

    printf ("\nEnter string below [ctrl + d] to quit\n");

    while ((read = getline(&line, &len, stdin)) != -1) {

        if (read > 0)
            printf ("\n  read %zd chars from stdin, allocated %zd bytes for line : %s\n", read, len, line);

        printf ("Enter string below [ctrl + d] to quit\n");
    }

    free (line);  /* free memory allocated by getline */

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

相关部分是:

char *line = NULL;  /* forces getline to allocate with malloc */
size_t len = 0;     /* ignored when line = NULL */
/* snip */
read = getline (&line, &len, stdin);
Run Code Online (Sandbox Code Playgroud)

设置lineNULL使getline自动分配内存.示例输出:

$ ./getline_example

Enter string below [ctrl + d] to quit
A short string to test getline!

  read 32 chars from stdin, allocated 120 bytes for line : A short string to test getline!

Enter string below [ctrl + d] to quit
A little bit longer string to show that getline will allocated again without resetting line = NULL

  read 99 chars from stdin, allocated 120 bytes for line : A little bit longer string to show that getline will allocated again without resetting line = NULL

Enter string below [ctrl + d] to quit
Run Code Online (Sandbox Code Playgroud)

因此,getline您无需猜测用户字符串的长度.