fscanf() 不适用于输入

发布于 2024-12-27 16:48:40 字数 1743 浏览 2 评论 0原文

我的函数写入文件:

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;

我的 main:

#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 是我的主要

My Function That writes to the file:

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;
}

where Record_t is defined as:

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

My main:

#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 after being written to file:

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

Terminal output:

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

now my fgets function is wrong! For some reason, the title is being saved inappropriately

i am compiling with the following flags:
gcc -ansi -std=c89 -pedantic -Wmissing-prototypes -Wall test.c Record.c -o test

where test.c is my main

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

半仙 2025-01-03 16:48:40
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(尤其,当返回的字符串大小不可预测时)就像 fscanf 一样)。

char * medium;

This should be

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

So that you actually have medium pointing to some memory you own. As it is now, your pointer is pointing to garbage and you're expecting fscanf to save a string in the memory it points to.

If a function ever appears to return a pointer to some magically created memory, you better check the documentation twice (unless that function happens to be the stupid strdup). The function either actually expects a pointer to some already-allocated memory, or returns a pointer that points to a block of memory allocated with someone from malloc's family, in which case you need to take responsibility for deallocating it.

Only in very rare circumstances do functions return a pointer to memory without taking a preallocated buffer in and without having mallocd it (especially when the string that is returned is of unpredictable size like it is for fscanf).

嘿咻 2025-01-03 16:48:40

您还没有为 media 分配缓冲区:

char * medium;  

这只是创建了一个指向名为 media 的字符的指针,您没有保留任何要读入的内存空间。这将为介质分配 256 个字节(允许您读取最多 256 个字符):

medium = malloc(256);

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

char medium[256];

鉴于您遇到的问题,我建议在堆栈上使用分配,然后只需读取和写入结构到文件中 - 它使您不必自己解析字段等,从而以磁盘空间为代价(您可能会写出大量空白字符),但在这种情况下这种浪费可以忽略不计。

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

You've not allocated a buffer for medium:

char * medium;  

That just creates a pointer to a char called medium, you've not reserved any memory space to read into. This would allocate 256 bytes (allowing you to read up to 256 characters) for medium:

medium = malloc(256);

Or you can allocate on the stack:

char medium[256];

Given the issues you're having, I would suggest using allocation on the stack, then just read and write the struct to the file — it saves you from having to parse the fields yourself etc. at expense of disk space (you could be writing out a lot of blank characters) but this wastage would be negligible in this scenario.

fwrite(t, sizeof(Record_t), 1, pFile);
fread(t, sizeof(Record_t), 1, pFile);
靑春怀旧 2025-01-03 16:48:40

几种方法:

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

    字符介质[100];
    
  2. 您没有正确检查错误:

    if (!(fscanf(infile,"%d: %s %d", &ID, 中等, &评级)
    

    应该是:

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

    您需要显式测试是否获得了预期读取的所有值。

如果没有对所有代码进行深入分析,这只是停留在表面。请注意,您需要确保您没有尝试将 medium 返回给调用代码。如果create_record() 完成了合理的工作,这应该没问题。奇怪的是 create_record() 没有被告知记录 ID。

Several ways:

  1. You've not allocated the space for it to read the string into. You need:

    char medium[100];
    
  2. You don't check for errors properly:

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

    should be:

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

    You need to explicitly test that you got all the values you expected to read.

That's scratching the surface without a deep analysis of all the code. Note that you'll need to be sure that you are not trying to return medium to the calling code. This should be OK if create_record() does a reasonable job. It is odd that create_record() isn't told the record ID.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文