【问题标题】:fgetc fails to load last character of filefgetc 无法加载文件的最后一个字符
【发布时间】:2016-04-16 01:24:19
【问题描述】:

我正在尝试将文件加载到我的程序中,以便我可以单独处理字节,但是当我加载文件时,它会过早地停止加载;总是 1 个字符。如果文件中只有一个字符,则不会加载它。是我读取文件的方式有问题还是位于不同的位置?

#include <stdio.h>
#include <stdlib.h>

typedef struct node {//linked list structure, I use this because I am working with files of vastly varying length
    char val;
    struct node *next;
} data;

void printdata(data *head);
void freeData(data **head);
data* readFile(FILE *f);

void main(int argc, char *argv[]) {//set this up so it is easier to test
    if(argc == 2) {
        FILE *f = fopen(argv[1], "r");
        data *d = readFile(f);
        fclose(f);
        printdata(d);
        freeData(&d);
    }
}

data* readFile(FILE *f) {//This is the function containing the problem
    data *retVal = malloc(sizeof(data));
    data *cur = retVal;
    int c = fgetc(f);
    if(c != EOF) {
        retVal->val = (char) c;
        while((c = fgetc(f)) != EOF) {
            cur->next = malloc(sizeof(data));
            cur->next->val = (char) c;
            cur = cur->next;
        }
    } else return NULL;//EDIT: was in a rush and forgot to add this.
    cur->next = NULL;
    return retVal;
}

void freeData(data **head) {
    if((*head)->next != NULL) freeData(&((*head)->next));
    free(*head);
}

void printdata(data *head) {
    data *cur = head;
    do {
        printf("%c", cur->val);
        cur = cur->next;
    } while(cur->next != NULL);//EDIT: I changed this because there was a small "problem" that was not the real problem
    printf("\n");
}

【问题讨论】:

  • 问题出在您的printdata 函数中,它不会打印列表中的最后一个元素。
  • 您的设计不适用于空文件。它将返回在val 中具有未初始化值的单个节点。
  • 有没有报错?
  • 不,这没有产生任何错误。它只是提前停止阅读。这是一个可编译的例子。

标签: c file-io linked-list fgetc


【解决方案1】:

printdata() 过早停止。 @Barmar

cur-&gt;next == NULL 时不要停止。当cur == NULL时停止

void printdata(data *head) {
  data *cur = head;
  while (cur) {
    printf(" <%hhx>", cur->val);  // Changed format for debugging
    fflush(stdout);               // Useful for debugging
    cur = cur->next;
  }
  printf("\n");
}

还包括一个简化的readFile()

data* readFile(FILE *f) { //This is the function containing the problem
  data head; // Only next field used
  data *cur = &head;
  int c;
  while ((c = fgetc(f)) != EOF) {
      cur->next = malloc(sizeof *(cur->next));
      cur = cur->next;
      assert(cur);
      cur->val = (char) c;
    }
  cur->next = NULL;
  return head.next;
}

【讨论】:

    【解决方案2】:

    我们来看看函数 printdata()

    void printdata(data *head) {
        data *cur = head;
        while(cur->next != NULL) {
            printf("%c", cur->val);
            cur = cur->next;
        }
        printf("\n");
    }
    

    注意当

    cur->next == NULL
    

    while里面的命令将被执行。

    还要注意,这总是发生在最后一个元素上。所以你的代码不会打印最后的数据。

    在其他解决方案中,您可以使用 do-while 循环:

    do{
      printf("%c", cur->val)
      cur = cur->next;
    } while (cur->next != NULL);
    

    这将保证打印最后一个元素,因为 while 将停止 AFTER 循环内部是为最后一个元素执行的。

    希望这会有所帮助。

    【讨论】:

    • 这不是问题,我尝试了更改,但问题仍然以完全相同的方式存在。不过还是谢谢
    • 这很不幸。我确实相信“do while”是一种改进,但我理解它是否不是问题的根源。我今晚筋疲力尽,但如果明天你的问题仍然存在,我会再看看!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-26
    • 1970-01-01
    • 2016-09-09
    • 1970-01-01
    • 2012-07-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多