Malloc和scanf

Bac*_*kus 4 c heap malloc

我在一些脚本语言方面相当称职,但我终于强迫自己学习原始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;
}
Run Code Online (Sandbox Code Playgroud)

目前我得到的奇怪的输出就像'8'\'.

Jer*_*fin 9

您需要提供scanf转换格式,以便它知道您想要读取字符串 - 现在,您只是显示您分配的内存中发生的任何垃圾.而不是试图描述所有问题,这里的一些代码至少应该接近工作:

char *toParseStr = malloc(10);
printf("Enter a string: ");
scanf("%9s", toParseStr);
printf("\n%s\n", toParsestr);
/* Edit, added: */ 
free(toParseStr);
return 0;
Run Code Online (Sandbox Code Playgroud)

编辑:在这种情况下,free字符串没有任何真正的区别,但正如其他人所指出的,尽管如此,培养一种好习惯.


Jac*_*cob 8

  char *toParseStr = (char*)malloc(10);
  printf("Enter string here: ");
  scanf("%s",toParseStr);
  printf("%s",toParseStr);
  free(toParseStr);
Run Code Online (Sandbox Code Playgroud)

首先,字符串in scanf指定它将要接收的输入.要在接受键盘输入之前显示字符串,请使用printf如图所示.

其次,您不需要取消引用,toParseStr因为它指向了您分配的大小为10的字符数组malloc.如果您使用的功能会将其指向另一个内存位置, &toParseStr需要.

例如,假设您要编写一个函数来分配内存.那么你需要&toParseStr因为你正在改变指针变量的内容(这是内存中的一个地址---你可以通过打印它的内容来亲眼看到).

void AllocateString(char ** ptr_string, const int n)
{
    *ptr_string = (char*)malloc(sizeof(char) * n);
}
Run Code Online (Sandbox Code Playgroud)

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

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;
}
Run Code Online (Sandbox Code Playgroud)

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

  • 即使在一个小程序中也可以释放+1.让我想起"小水滴造海洋".;-) (2认同)

pax*_*blo 5

使用scanf()(或fscanf()在您无法控制的数据上)与标准的“%s”说明符是一种近乎确定的方法,可以让您陷入缓冲区溢出的麻烦。

典型的例子是,如果我在你的程序中输入字符串“这个字符串超过 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;
}
Run Code Online (Sandbox Code Playgroud)

  • 另一个有趣的可能性是 `scanf("%9[^\n]", your_string);` -- 从 `scanf` 输入的面向行的字符串,无论值多少钱。 (2认同)