【问题标题】:fscanf() writing only some not all of the content from the input filefscanf() 仅写入输入文件中的部分而非全部内容
【发布时间】:2017-06-28 06:32:35
【问题描述】:

我正在编写将文本文件转换为二进制文件的代码。它不返回任何错误并且运行良好,除了在这个特定示例中它不打印名字的事实。我的输入文件包含john doe 1 4.0。预期的输出是johndoe@▒,但我的输出是doe@▒。我尝试使用 fseek 来移动偏移量。我尝试以不同的方式关闭文件。我尝试重命名我的变量并更改 if 语句。

我不完全确定,但我觉得错误可能来自循环。如果我交换名字和姓氏,会发生同样的事情但相反,这意味着我的代码忽略了首先使用 fwrite 读取的任何内容。我的代码有什么问题导致这种情况发生?

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

void textToBinary(char *inputFile, char *outputFile){

    FILE *ifp, *ofp;

    char firstName[256], lastName[256];
    int sID; 
    float gpa;

    unsigned char firstNameLen = strlen(firstName);
    unsigned char lastNameLen = strlen(lastName);

    if(((ifp = fopen(inputFile, "r")) != NULL)&&((ofp = fopen(outputFile, "w")) != NULL)){
        while((fscanf(ifp, "%s %s %d %f\n", firstName, lastName, &sID, &gpa)) != EOF){
            fwrite(&firstNameLen, sizeof(firstNameLen), 1, ofp);
            fwrite(firstName, sizeof(char), firstNameLen, ofp);
            fwrite(&lastNameLen, sizeof(lastNameLen), 1, ofp);
            fwrite(lastName, sizeof(char), lastNameLen, ofp);
            fwrite(&sID, sizeof(int), 1, ofp);
            fwrite(&gpa, sizeof(float), 1, ofp);
        }
        fclose(ifp);
        fclose(ofp);
    }else{
        fprintf(stderr, "Couldn't open: %s\n", ifp);
    }   
}

【问题讨论】:

  • 您正在计算垃圾缓冲区值上的 firstNameLenlastNameLen。这些属于循环内部。
  • 您的fscanf() 支票应该是== 4 而不是!= EOF。您可能会得到数字 0、1、2 或 3 以及 EOF,它们都表示存在问题。
  • char firstName[256], ... unsigned char firstNameLen = strlen(firstName); 是 UB
  • 从风格上讲,您最好将打开的文件拆分为更多行。使用if ((ifp = fopen(inputFile, "r")) == NULL) { …report error opening inputFIle… } else if ((ofp = fopen(outputFile, "w")) == NULL) { fclose(ifp); …report error opening outputFile… } else { …while loop and fcloses… }。这为您提供更准确的错误报告,并且在适当间隔时更具可读性。请注意,printf("Couldn't open: %s\n", ifp); 将报告文件名为(null),如果你很幸运,或者如果输入文件无法打开则崩溃,如果输出文件无法打开,则会出现乱码。
  • 感谢@Gene 工作。我明白现在发生了什么

标签: c file while-loop fwrite scanf


【解决方案1】:

建议使用上述 cmets 重写代码

//unsigned char firstNameLen = strlen(firstName);
//unsigned char lastNameLen = strlen(lastName);

if(((ifp = fopen(inputFile, "r")) != NULL)&&((ofp = fopen(outputFile, "w")) != NULL)){
    while((fscanf(ifp, "%255s %255s %d %f", firstName, lastName, &sID, &gpa)) == 4){
        unsigned char firstNameLen = strlen(firstName);
        unsigned char lastNameLen = strlen(lastName);
        fwrite(&firstNameLen, sizeof firstNameLen, 1, ofp);
        fwrite(firstName, sizeof *firstName, firstNameLen, ofp);
        fwrite(&lastNameLen, sizeof lastNameLen, 1, ofp);
        fwrite(lastName, sizeof *lastName, lastNameLen, ofp);
        fwrite(&sID, sizeof sID, 1, ofp);
        fwrite(&gpa, sizeof gpa, 1, ofp);
    }
    fclose(ifp);
    fclose(ofp);
}else{

【讨论】:

  • 变量类型声明不应在循环内。
  • @JoeDF:你什么意思?在任何版本的 C 中,任何语句块顶部的变量声明都没有错。在现代 C(C99 或更高版本)中,您可以在语句块中的任何位置声明变量——它们不必在顶部.
  • @JoeDF 这只是一种编程风格。这没有错。
  • C99+,我明白了。明白了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-16
  • 1970-01-01
  • 2014-03-22
相关资源
最近更新 更多