繁体   English   中英

带有指针的C结构认为我没有正确分配内存

[英]C struct with pointer think I'm not allocating memory correctly

  typedef struct Data* DATAS;

  struct Data {
      char *name;
      char *city;
      DATAS next;
  };
  typedef struct Data DATA;

  int main(void){
     DATAS tmp;

     tmp=(DATAS) malloc(sizeof(DATA));   
     printf("please enter name:\n");
     scanf("%s",&tmp->name);
     printf("%s\n",&tmp->name);
     printf("please enter city:\n");
     scanf("%s",&tmp->city);
     printf("%s\n",&tmp->name);
     printf("%s\n",&tmp->city);

  return 0;
  }

这是家庭作业的一部分。 或者更确切地说是这个概念。 我需要使用“ typedef struct Data * DATAS;” 这让我失望。 当我运行它时,我用部分城市覆盖了名称,因此我得到了它。

please enter name:
name
name
please enter city:
city
namecity
city

任何帮助都会很棒。 谢谢。 我已经尝试过使用malloc的不同变体

tmp=(DATAS) malloc(sizeof(DATA));
tmp=(DATA) malloc(sizeof(DATA));

分配struct Data的最佳方法是:

struct Data *tmp;
tmp = malloc(sizeof *tmp);
if (tmp == NULL) {
    /* malloc failed, abort or take corrective action */
}

不建议为指针类型定义typedef(至少在我看来); 显式使用struct Data *可以使读者更清楚地知道您正在处理指针。

也不必为结构类型定义typedef。 typedef只是为现有类型声明一个新名称; 您的类型已经有一个非常好的名字struct Data 诚然,您必须重复输入struct关键字,但这并不是真正的问题。

无需malloc的结果; malloc返回void*结果,可以将其隐式转换为指针类型。 强制转换可以隐藏错误,例如忘记必需的#include <stdlib.h>

但这是样式问题。 您当前的代码:

tmp=(DATAS) malloc(sizeof(DATA));

可以,应该可以。 问题稍后在您的代码中。

具有"%s"格式的scanf需要一个char* argument. You're giving it the *address* of a char* argument. You're giving it the *address* of a char *对象char* argument. You're giving it the *address* of a ,即char**类型的值。 编译器不一定会对此发出警告。 所以这:

scanf("%s",&tmp->name);

应该:

scanf("%s", tmp->name);

但这仍然是一个问题,因为tmp->name是未初始化的指针。 它可能指向内存中的某个随机位置,并且该调用尝试在该位置存储数据。 否则它可能包含无效地址,从而导致崩溃。 该行为是不确定的。

您需要分配空间来容纳名称,并使tmp->name指向它。 您可能需要在此处再次调用malloc()

那么,您需要分配多少空间? 嗯,这没有很好的答案,因为scanf("%s", ...)对其读取的字节数没有限制。 无论分配的空间有多大,如果输入足够的数据,都可能会溢出它。

您可能现在不需要担心这一点。 记住未来。 现在,您可以分配“足够的”空间(例如100字节),请注意不要输入太多数据。 这应该足以使您的程序正常工作。 (查看scanf的文档,并考虑使用类似"100s"东西。)

并记住scanf("%s", ...")读取以空格分隔的输入字符串;如果键入“ John Doe”,它将仅读取“ John”,而将“ Doe”留作下一个输入操作。

(我希望这不会太令人压倒。)

您正在将未初始化的指针传递给scanf ,它使用它们来执行写操作。 这是未定义的行为。 您还将传递一个字符串指针的地址到scanfprintf C中的字符串已经是指针,您不应将指向它们的指针传递给I / O例程。

如果您知道名称/城市名称中的字符数限制,则可以读取如下字符串:

char buf[128]; // 127 is the limit; buffer needs an extra character
printf("please enter name:\n");
scanf("%127s", buf);
size_t len = strlen(buf)+1; // plus one for null terminator
tmp->name = malloc(len);
strcpy(tmp->name, buf);
printf("%s\n", tmp->name); // No ampersand

您已经为包含三个指针的结构分配了空间。 您还需要为两个字符串分配空间。 您还应该确保适当地初始化了next字段-可能为NULL。

就个人而言,我不会理会DATAS typedef,最好保留所有大写的宏名称(尽管使用FILE *类型)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM