Malloc和scanf

Malloc和scanf,c,malloc,heap,C,Malloc,Heap,我在一些脚本语言方面相当有能力,但我最终还是强迫自己学习原始C语言。我只是在玩一些基本的东西(现在的I/O)。如何分配堆内存,在分配的内存中存储一个字符串,然后再将其吐出?这就是我现在所拥有的,我如何才能使它正常工作 #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { char *toParseStr = (char*)malloc(10); scanf("Enter

我在一些脚本语言方面相当有能力,但我最终还是强迫自己学习原始C语言。我只是在玩一些基本的东西(现在的I/O)。如何分配堆内存,在分配的内存中存储一个字符串,然后再将其吐出?这就是我现在所拥有的,我如何才能使它正常工作

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

int main(int argc, char *argv[])
{
  char *toParseStr = (char*)malloc(10);
  scanf("Enter a string",&toParseStr);
  printf("%s",toParseStr);
  return 0;
}
#包括
#包括
int main(int argc,char*argv[])
{
char*toparsest=(char*)malloc(10);
scanf(“输入字符串”、&toparsest);
printf(“%s”,toparsest);
返回0;
}

目前我得到了奇怪的输出,比如“8”\。

scanf
中的
toparsest
之前不需要
&
,因为它已经是一个指针了


之后也可以调用
free(toparsest)
你需要给
scanf
一个转换格式,这样它就知道你想读取一个字符串——现在,你只需要显示你分配的内存中发生的任何垃圾。与其试图描述所有的问题,这里有一些代码至少应该可以工作:

char *toParseStr = malloc(10);
printf("Enter a string: ");
scanf("%9s", toParseStr);
printf("\n%s\n", toParsestr);
/* Edit, added: */ 
free(toParseStr);
return 0;
编辑:在这种情况下,
free
ing字符串不会产生任何真正的区别,但正如其他人所指出的,这是一个很好的习惯

  char *toParseStr = (char*)malloc(10);
  printf("Enter string here: ");
  scanf("%s",toParseStr);
  printf("%s",toParseStr);
  free(toParseStr);
首先,
scanf
中的字符串指定要接收的输入。要在接受键盘输入之前显示字符串,请使用
printf
,如图所示

其次,您不需要取消对
toparsest
的引用,因为它指向一个大小为10的字符数组,正如您使用
malloc
分配的那样如果您使用的函数会将其指向另一个内存位置,则需要
&toparsest

例如,假设您想编写一个函数来分配内存。然后您需要
&toParseStr
,因为您正在更改指针变量的内容(这是内存中的一个地址,您可以通过打印其内容自行查看)

如您所见,它接受
char**ptr_string
,该字符串作为一个指针读取,该指针存储一个指针的内存位置,该指针将存储分配的
n
字节块的第一个字节的内存地址(在
malloc
操作之后)(现在它有一些垃圾内存地址,因为它未初始化)


第三,建议您释放分配的内存。即使这是您的整个程序,并且当程序退出时,此内存将被释放,这仍然是一个良好的做法。

首先,使您的程序无法工作的错误:
scanf(3)
采用格式字符串,就像
printf(3)
,不是要为用户打印的字符串。其次,您传递的是指针
toparsest
的地址,而不是指针
toparsest

我还删除了您对
malloc(3)
的调用中不必要的强制转换

程序仍然需要改进的一点是使用scanf(3)的
a
选项为您分配内存,这样一些在字符串中放入十个字符的小丑就不会开始在不相关的内存上跺脚了。(是的,C将允许某人用这个程序覆盖几乎整个地址空间,如所写。巨大的安全漏洞。:)

#包括
#包括
int main(int argc,char*argv[])
{
char*toparsest=malloc(10);
printf(“输入一个短字符串:”);
scanf(“%s”,toparsest);
printf(“%s\n”,toparsest);
返回0;
}
使用标准“%s”说明符对不受控制的数据使用
scanf()
(或
fscanf()
)几乎肯定会导致缓冲区溢出

经典的例子是,如果我在你的程序中输入字符串“这个字符串超过10个字符”,混乱就会接踵而至,猫和狗会开始睡在一起,一个赤裸的奇点很可能出现并吞噬地球(大多数人只是说“未定义的行为”,但我认为我的描述更好)

我极力反对使用不能提供保护的函数。我建议您(尤其是作为C的新手)使用
fgets()
来读取输入,因为您可以更轻松地控制缓冲区溢出,而且它比
scanf()
更适合于简单的行输入

一旦你有了一行,你就可以随心所欲地调用
sscanf()
,顺便说一句,在这种特殊情况下,你不需要这样做,因为你只得到了一个原始字符串

我将使用:

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

#define BUFFSZ 10

int main(int argc, char *argv[]) {
  char *toParseStr = malloc(BUFFSZ+2);
  if (toParseStr == NULL) {
      printf ("Could not allocate memory!\n");
      return 1;
  }
  printf ("Enter a string: ");
  if (fgets (toParseStr, BUFFSZ+2, stdin) == NULL) {
      printf ("\nGot end of file!\n");
      return 1;
  }
  printf("Your string was: %s",toParseStr);
  if (toParseStr[strlen (toParseStr) - 1] != '\n') {
      printf ("\nIn addition, your string was too long!\n");
  }
  free (toParseStr);
  return 0;
}
#包括
#包括
#包括
#定义BUFFSZ 10
int main(int argc,char*argv[]){
char*toparsest=malloc(BUFFSZ+2);
if(toparsest==NULL){
printf(“无法分配内存!\n”);
返回1;
}
printf(“输入字符串:”);
如果(fgets(toparsest,BUFFSZ+2,stdin)=NULL){
printf(“\n文件结尾!\n”);
返回1;
}
printf(“您的字符串是:%s”,toparsest);
if(toparsest[strlen(toparsest)-1]!='\n'){
printf(“\n此外,您的字符串太长!\n”);
}
免费(托帕赛斯特);
返回0;
}

您不需要在包含
的ISO C中从
malloc(3)
强制转换返回类型。值得指出的是,您可能应该在此处使用堆栈。根据bball的系统,可能需要添加“\n”在该printf中,可以正确显示内容。此外,10个字符是一个非常短的字符串。虽然是真的,但这并不是问题的根源(在这种情况下,
&
是不必要的,但无害的)@Jerry这是无害的,因为格式说明符没有指定任何参数,但一旦他将其修复为在您的答案中有一个%s,它将导致segfault@Michael:是的,但它只指出了一个相对较小的问题,其中还有许多更严重的问题。特别是,改变了这一点(同时保留代码的其余部分
int main(int argc, char *argv[])
{
  char *toParseStr;
  const int n = 10;
  printf("Garbage: %p\n",toParseStr);
  AllocateString(&toParseStr,n);
  printf("Address of the first element of a contiguous array of %d bytes: %p\n",n,toParseStr);

  printf("Enter string here: ");
  scanf("%s",toParseStr);
  printf("%s\n",toParseStr);
  free(toParseStr);

  return 0;
}
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
  char *toParseStr = malloc(10);
  printf("Enter a short string: ");
  scanf("%s",toParseStr);
  printf("%s\n",toParseStr);
  return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUFFSZ 10

int main(int argc, char *argv[]) {
  char *toParseStr = malloc(BUFFSZ+2);
  if (toParseStr == NULL) {
      printf ("Could not allocate memory!\n");
      return 1;
  }
  printf ("Enter a string: ");
  if (fgets (toParseStr, BUFFSZ+2, stdin) == NULL) {
      printf ("\nGot end of file!\n");
      return 1;
  }
  printf("Your string was: %s",toParseStr);
  if (toParseStr[strlen (toParseStr) - 1] != '\n') {
      printf ("\nIn addition, your string was too long!\n");
  }
  free (toParseStr);
  return 0;
}