C编程中的RPG库存

时间:2013-08-03 01:02:11

标签: c struct inventory

我是C的新手,对于我的班级,我们有一个项目,我们必须编写一个函数来读取文件中的所有项目,并按动态创建的列表以文件顺序返回它们。 该文件的每一行都是一个项目,格式为:

'<description>' <damage> <cost> <weight>

它应该按文件顺序返回文件中的项目的基本指针,如果文件不存在则返回NULL。

到目前为止,这是我的代码:

item_t *ReadItemsFromFile(char *file)
{
typedef struct item item_t;
struct item
{
   char name[32];
   float cost, weight;
   int dam;
};FILE *fpin = fopen(file, "r");

if(fpin != NULL)
{
  item_t i[20];
  int n = 0;
  char line[sizeof(file)];
  while(fgets(line, sizeof(line), fpin) != NULL){
      (fscanf(fpin, " '%[^']' %d %f %f", i[n].name, &i[n].dam, &i[n].cost, &i[n].weight));
  fputs(i[n].name, stdout);
  n++;
}
} else {
  return NULL;
} 
  return(0);
}

我一直在使用fputs来尝试测试代码,但它一直让我对第一个和最后一个项目进行乱码。 此外,当我尝试把

fputs(&i[n].dam, stdout);

所以我可以测试结构的其他变量,我不断收到错误说&#34;传递&#39; fputs&#39;的参数1来自不兼容的指针类型。

我不确定我是否准确地使用fscanf传递给struct变量,或者它是否是其他东西。

4 个答案:

答案 0 :(得分:2)

您需要将struct定义移到函数之外。

您对该行应该多长时间的说明是错误的。您需要指定一个足够长的字节数,以便占用整行。

使用fgets()获取一行时,不应使用fscanf()来读取文件。您已使用fgets()从文件中读取。您使用sscanf()line中包含的字符串中读取数据。

以上内容足以让你的程序做一些名义上有用的事情。

要返回项目列表,您需要实际调用malloc()(或其他类似函数)来为您指定为需求的“动态创建列表”创建内存。由于您不知道自己拥有多少项目,因此您需要一种方法来发现有多少项目,或者使用一种机制来让您的列表动态增长。

答案 1 :(得分:1)

一个问题是,您使用fgets从文件中读取一行到line,但您忽略该行并使用fscanf从下一行读取。您应该使用sscanf来解析您刚读过的行。或者,根本不要使用fgets,而只是fscanf直接使用while条件:

while(4 == fscanf(fpin, " '%[^']'%d%f%f", i[n].name, &i[n].dam, &i[n].cost, &i[n].weight)) {
    fputs(i[n].name, stdout);
    n++; }

另一个问题是你声明line足够大以容纳sizeof(char *)个字符 - 可能只有4或8个字符,这对于整行来说都不够大,所以你只会能够阅读部分内容。你需要声明它足够大,以保持文件中最长的一行。

第三个问题是您将struct itemitem_t声明为函数的本地,这意味着当您尝试在函数外部使用item_t时,您的代码甚至无法编译作为其返回类型的一部分。您需要在函数声明之前将delcarations移动到全局范围。

第四个问题是你将正在读入的项目数组(i)声明为局部变量,因此你将无法从函数中返回它 - 如果你这样做,你返回的指针将指向垃圾。但是因为你总是返回NULL,所以你不会看到这个问题。

答案 2 :(得分:0)

fputs()的问题是该功能专门用于打印 char *字符串的结果。要打印其他内容,您需要使用fprintf(),或者更好的是,如果要打印到标准输出,只需使用printf()

要消除乱码,请确保以正确的编码保存文件。当我将测试库存文件保存为ANSI或UTF-8而没有BOM(ANSI作为UTF-8)时一切正常,但每当我保存为UTF-8时,它在我的文件前面插入3个字节,程序无法处理,并为我的第一个项目吐出胡言乱语。

我还修改了ReadItemsFromFile(),如你所见,接受指向int的指针,int指向读取的元素数量malloc(),这样我就可以测试我的代码,如果它不符合你班级的规范,你可以删除它。此外,它非常粗糙,但我在代码中添加了使用memcpy()stdlib.h重新调整存储块的大小,即使用string.hrealloc()即可存储项目数组(需要realloc()\0分别)因为struct item { char name[32]; float cost, weight; int dam; }; typedef struct item item_t; item_t *ReadItemsFromFile(char *file, int *count) { FILE *fpin = fopen(file, "r"); int n = 0; item_t *items = NULL; if(fpin != NULL) { char line[128]; while(fgets(line, 128, fpin) != NULL){ item_t *newptr = (item_t *)malloc((n + 1) * sizeof(item_t)); memcpy(newptr, items, n * sizeof(item_t)); free(items); items = newptr; if (4 == sscanf(line, "'%[^']' %d %f %f\n", items[n].name, &items[n].dam, &items[n].cost, &items[n].weight)) { n++; } } fclose(fpin) } else { *count = 0; return NULL; } *count = n; return items; } 在环境中无法运行可执行文件,但如果{{1}}适用于您,我建议使用它。

另请注意,我设置了128个字符的任意缓冲区长度,包括每行的{{1}} null终止符。这可以调整为适合你的任何东西。

以下是我一直在讨论的代码:

{{1}}

答案 3 :(得分:0)

好的,我停止使用fgets()并将结构移到函数之外,但是我仍然在返回指针时遇到问题。在mallocing之后我一直试图返回指针,但它告诉我“从不兼容的指针类型返回”。到目前为止,这是我的代码:

struct items_t
{
   char name[32];
   float cost, weight;
   int dam;
};
typedef struct items_t items_t;

item_t *ReadItemsFromFile(char *file)
{

  FILE *fpin = fopen(file, "r");

if(fpin)
{   
  items_t i[50];
  int n = 0;

   while(4 == (fscanf(fpin, " '%[^']' %d %f %f", i[n].name, &i[n].dam, &i[n].cost, &i[n].weight)))
{
  n++;
  items_t *a = (items_t*)malloc(sizeof(items_t));
  return(&a);

}
} else {
  return NULL; 
}
return(0);

}