在char指针中获取字符串输入

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

int main(){
    char *s;
    printf("enter the string : ");
    scanf("%s", s);
    printf("you entered %s\n", s);
    return 0;
}
当我提供长度小于或等于 17 个字符的小输入(例如“aaaaaaaaaaaaaaaaa”)时,程序可以正常工作,但是如果提供更大长度的输入,则会出现运行时错误,显示“main.c 已意外停止工作”。
这是我的编译器(codeblocks)或我的计算机(Windows 7)存在问题吗?还是与 C 的输入缓冲区有关?

这被称为缓冲区溢出... 如果需要获取大量输入值,请勿使用scanf()。 - Kevin
我认为下面的回答没有提到Kevin。这是缓冲区溢出吗? - Nikunj Banka
我认为在我发表这个评论时下面的答案并不存在,而且是缓冲区溢出。你的输入超出了缓冲区的边界。 - Kevin
要明确一点:根本没有缓冲区!(指针s并不指向一个太小的缓冲区;它根本就没有指向任何地方。) - Steve Summit
9个回答

21

由于指针未初始化,因此出现了未定义行为。你的编译器没有问题,但你的代码有问题 :)

在存储数据之前,将s指向有效的内存。


为了管理缓冲区溢出,您可以在格式说明符中指定长度:

scanf("%255s", s); // If s holds a memory of 256 bytes
// '255' should be modified as per the memory allocated.

GNU C支持一种非标准扩展,如果指定了%as,则不需要分配内存,因为分配是自动完成的,但必须传递指向指针的指针:

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

int main() {
  char *s,*p;

  s = malloc(256);
  scanf("%255s", s); // Don't read more than 255 chars
  printf("%s", s);

  // No need to malloc `p` here
  scanf("%as", &p); // GNU C library supports this type of allocate and store.
  printf("%s", p);
  free(s);
  free(p); 
  return 0;
}

目前最佳答案 +1,因为具有溢出保护。如果您不介意,我有一个问题:为什么要使用 malloc() 而不是静态分配? - m0skit0
2
OP问为什么要使用指针,并询问为什么它失败了。这只是一个最简示例。对于特定情况,静态数组也可以起作用。 - P.P

8

该字符指针没有被初始化,你需要动态分配内存给它。

char *s = malloc(sizeof(char) * N);

在读取字符串时,N是您可以读取的最大字符串长度,不指定输入字符串的最大长度使用scanf是不安全的,应该像这样使用:

scanf("%Ns",s);

N与malloc相同。


3
不得将malloc()的返回值强制转换。 - Aniket Inge
malloc 返回的是 void *,需要进行强制类型转换吗? - Rami Jarrar
1
@RamiJarrar malloc() 返回 void 指针,所以不需要强制类型转换...这是个不好的习惯...请参考 https://dev59.com/dHRB5IYBdhLWcg3wgHWr - akp

1

你没有为字符数组分配任何内存,首先尝试通过调用malloc()或calloc()来获得内存,然后尝试使用它。

s = malloc(sizeof(char) * YOUR_ARRAY_SIZE);
...do your work...
free(s);

为什么要费心使用malloc()和free()?直接静态分配不就好了。 - m0skit0

1

您需要为指针所指向的缓冲区分配足够的内存:

    s = malloc(sizeof(char) * BUF_LEN);

如果您不再需要这段内存,请释放它:

    free(s);

为什么要费心使用malloc()和free()?直接静态分配不就好了。 - m0skit0
静态存储对于这种情况更好,但问题表明TS不熟悉指针和内存分配。我只是帮助他理解了这些内容。 - oleg_g

1
你没有为字符串分配内存,因此,你试图写入一个未授权的内存地址。这里
char *s;

你只是在声明一个指针,而没有指定为字符串保留多少内存。你可以像这样静态声明:

char s[100];

这将保留100个字符。如果超过100个字符,由于你提到的同样的原因,它仍然会崩溃。


0
问题出在你的代码上...你从来没有为char *分配内存。因为没有分配足够大的内存(使用malloc())来容纳字符串,所以这就成为了未定义行为。
你必须为s分配内存,然后使用scanf()(我更喜欢fgets())。

1
为什么要使用malloc()和free()?为什么不静态地保留空间呢? - m0skit0

0
#include"stdio.h"
#include"malloc.h"

int main(){

        char *str;

        str=(char*)malloc(sizeof(char)*30);

        printf("\nENTER THE STRING : ");
        fgets(str,30,stdin);

        printf("\nSTRING IS : %s",str);

        return 0;
}

-1

用C语言读取字符指针的代码

#include<stdio.h>
 #include<stdlib.h>
 void main()
 {
    char* str1;//a character pointer is created 
    str1 = (char*)malloc(sizeof(char)*100);//allocating memory to pointer
    scanf("%[^\n]s",str1);//hence the memory is allocated now we can store the characters in allocated memory space
    printf("%s",str1);
    free(str1);//free the memory allocated to the pointer
 }

-2

我遇到了这个问题。我尝试了下面的代码,它起作用了:

char *text; 
scanf("%s", *&text); 

我不知道它是如何工作的。我只是觉得想做。


尝试运行代码并打印字符串。 - MrSykkox

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接