fscanf()不使用输入

时间:2012-01-18 02:08:35

标签: c file-io scanf

我写入文件的函数:

Record_t * load_Record(FILE * infile)
{
    Record_t *r;
    char title[TITLE_SIZE];
    char [MEDIUM_SIZE];  
    int ID, rating;
    if ((fscanf(infile,"%d: %s %d", &ID, medium, &rating) != 3 && fgets(title, TITLE_SIZE, infile))){
            return NULL;
    }
    printf("medium is: %s title is: %s\n", medium, title);
    r = create_Record(medium, title);
    set_Record_rating(r, rating);   
    return r;
}

其中Record_t定义为:

typedef struct Record {
    int ID;
    char * title;
    char * medium;
    int rating;
} Record_t;

我的主要人物:

#include "Record.h"

#include <stdlib.h>

int main()
{

    char * title = "The Queen";
    char * medium = "DVD";
    FILE * pfile ;
    struct Record *t = create_Record(medium, title);  //creates a record
    struct Record *s;
    set_Record_rating (t, 3);
    print_Record(t);
    pfile = fopen("output.txt", "w");
    save_Record(t, pfile);
    fclose(pfile);
    destroy_Record(t);  //de-allocates memory
    pfile = fopen("output.txt", "r");
    if(!(s = load_Record(pfile))){
        return 1;
    }
    print_Record(s);
    fclose(pfile);
    destroy_Record(s);      
    return 0;
}   
写入文件后

output.txt:

1: DVD 3 The Queen    //checked for excess whitespace(has newline however)

终端输出:

1: The Queen DVD 3
medium is: DVD title is: �  //title being saved inappropriately  
                          @
2: �
    @ DVD 3

现在我的 fgets 功能错了!由于某种原因,标题被不当地保存

我正在使用以下标志进行编译: gcc -ansi -std = c89 -pedantic -Wmissing-prototypes -Wall test.c Record.c -o test

其中test.c是我的主要

3 个答案:

答案 0 :(得分:4)

char * medium;

这应该是

char medium[SOME_CONSTANT]; // or char* medium = malloc(x); if you need the
                            // memory to persist after the function returns

这样你实际上medium指向你拥有的一些记忆。就像现在一样,你的指针指向垃圾,你期望fscanf将字符串保存在它指向的内存中。

如果某个函数似乎返回指向某个神奇创建的内存的指针,那么最好检查两次文档(除非该函数碰巧是愚蠢的strdup)。该函数实际上需要指向某个已经分配的内存的指针,或者返回一个指向由malloc的家人分配的内存块的指针,在这种情况下,您需要负责解除分配它。

只有在非常罕见的情况下,函数才会返回指向内存的指针,而不需要使用预分配的缓冲区而不需要malloc d(当返回的字符串具有不可预测的大小时,尤其就像它是fscanf)。

答案 1 :(得分:2)

您没有为媒体分配缓冲区:

char * medium;  

这只是创建一个指向名为medium的char的指针,你没有保留任何内存空间来读入。这将为medium:

分配256个字节(允许您读取最多256个字符)
medium = malloc(256);

或者你可以在堆栈上分配:

char medium[256];

考虑到你遇到的问题,我建议在堆栈上使用分配,然后只需读取和写入文件结构 - 它可以避免你自己解析字段等等以牺牲磁盘空间为代价(你可能会写出很多空白字符)但在这种情况下,这种浪费可以忽略不计。

fwrite(t, sizeof(Record_t), 1, pFile);
fread(t, sizeof(Record_t), 1, pFile);

答案 2 :(得分:1)

有几种方法:

  1. 您没有为其分配空间来读取字符串。你需要:

    char medium[100];
    
  2. 您没有正确检查错误:

    if (!(fscanf(infile,"%d: %s %d", &ID, medium, &rating)
    

    应该是:

    if (fscanf(infile,"%d: %s %d", &ID, medium, &rating) != 3 ...
    

    您需要明确地测试您是否获得了您希望阅读的所有值。

  3. 在没有对所有代码进行深入分析的情况下,这表面很难理解。请注意,您需要确保不要尝试将medium返回到调用代码。如果create_record()做了合理的工作,这应该没问题。奇怪的是create_record()没有被告知记录ID。