与fgets()的fscanf后不工作() [英] fgets() not working after fscanf()

查看:191
本文介绍了与fgets()的fscanf后不工作()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的fscanf的日期来阅读并随后FGETS阅读笔记。
第一次迭代后然而,的fscanf返回值-1。

我用GDB调试一步的程序步骤。它工作正常,直到第一次使用与fgets的。当我尝试打印出通过对第一次迭代与fgets读行了,它给了我这样的:

 (GDB)打印行
$ 6 = \"\\rtest\\r18/04/2010\\rtest2\\r03/05/2010\\rtest3\\r05/08/2009\\rtest4\\r\
\\000\\000\\000\\000q\\352\\261\\a\\370\\366\\377\\267.N=\\366\\000\\000\\000\\000\\003\\000\\000\\000\\370xC\\000\\000\\000\\000\\000\\000\\000\\000\\000\\001\\000\\000\\000\\227\\b\\000\\000\\070\\367\\377\\267H\\364\\377\\267\\362\\202\\004\\bdoD\\000\\354\\201\\004\\b\\001\\000\\000\\000\\304oC\\000p\\363\\377\\277\\260zC\\000D\\363\\377\\277\
!B\\000\\064\\363\\377\\277\\354\\201\\004\\b(\\363\\377\\277TzC\\000\\000\\000\\000\\000\\070\\367\\377\\267\\001\\000\\000\\000\\000\\000\\000\\000\\001\\000\\000\\000\\370xC\\000\\001\\000\\000\\000\\000\\000\\312\\000\\000\\000\\000\\000\\377\\260\\360\\000\\001\\000\\000\\000\\277\\000\\000\\000\\364\\317\\000\\000\\344\\261\\\\\\000\\000\\000\\000\\000p\\363\\377\\277|\\233\\004\\b\\350\\362\\377\\277 \\ 204 \\ 004 \\ B \\ 005 \\ 000 \\ 000 \\ 000 | \\ 233 \\ 004 \\ B \\ 030 \\ 363 \\ 377 \\ 277

看起来与fgets读取剩余的条目,然后将它们存储在一个单一的字符串。

我不知道它为什么是这样做的。

下面是主要的code:

  INT主(INT ARGC,CHAR *的argv []){
    FILE *文件;
    INT numEntries,I = 0;
    INT指数=的atoi(ARGV [1]);
    焦线[SIZE]
    JournalEntry的*进入;    / *提供的参数是入门用户想要显示* /
    如果(argc个→2){
        PERROR(错误:提供的参数过多);
    }
    文件= FOPEN(journalentries.txt,R);
    如果(文件== NULL){
        PERROR(错误打开文件);
    }    如果(的fscanf(文件,%d个,&放大器;!numEntries)= 1){
        PERROR(无法读取的条目数);
    }    进入=(JournalEntry的*)malloc的(numEntries *的sizeof(JournalEntry的));
    如果(入门== NULL){
        PERROR(malloc的失败);
    }    对于(i = 0; I< numEntries;我++){
        如果(的fscanf(文件%D /%D /%D,&安培;进入[I]·天,和放大器;入门[I] .month,和放大器;!入门[I] .year)= 3){
            PERROR(无法读取入境日期);
        }        如果(与fgets(线,的sizeof(线),文件)== NULL){
            PERROR(无法读取入境文字);
        }
    }    的printf(%D-%02d-%02D%S:进入[指数] .year,进入[指数] .month,进入[指数]·天,进入[指数]的.text);    如果(FERROR(文件)){
        PERROR(错误与文件);
    }    FCLOSE(文件);
    免费入场);    返回0;
}

这是我要读文件:
的第一行包含要读取的条目数

  4
12/04/2010
测试
18/04/2010
TEST2
03/05/2010
TEST3
05/08/2009
TEST4

位于头文件中的结构JournalEntry的:

  typedef结构{
    日整型;
    INT月;
    INT年;
    字符文本[250];
} JournalEntry的;


解决方案

  

看起来与fgets读取剩余的条目,然后将它们存储在一个单一的字符串。


'\\ r'未行终止。因此,当的fscanf 停止在第一个无效字符解析和使他们在缓冲区中,然后与fgets 会读他们,直到行尾。而且,由于有该文件中没有有效的行结束符,即至文件末尾。

您或许应该修正文件具有有效的(Unix的?)行结尾,例如用合适的文本编辑器,可以做到这一点。但是,这是另外一个问题,这之前已经要求(如<一个href=\"http://stackoverflow.com/questions/3773649/how-to-find-fix-files-with-mixed-line-endings-0x0d-0x0d-0x0a\">here),并且依赖于不包含在你的问题的细节。

此外,你需要为的fscanf 返回值双重检查。使用 PERROR 仅在返回值为-1,否则错误信息将无法在所有相关的错误。如果返回值为&GT; = 0 但你想要的东西,然后打印自定义错误消息无效的输入语法还是有所不同的任何(也可能是使用与fgets 读该行其余出缓冲器)。

此外,为了可靠地混合。 scanf函数与fgets ,我需要在<$ C $添加空间C>的fscanf 格式字符串,所以它会读了在该行的末尾任何空白(也是在下一行,所有空行的开始,所以要小心,如果该事项),就像这样:

INT items_read = scanf函数(%d个,&安培;的intValue);

作为另一个答案所述,它可能是最好的阅读与线与fgets 只,然后用的sscanf 解析它们线由行

I am using fscanf to read in the date and then fgets to read the note. However after the first iteration, fscanf returns a value of -1.

I used GDB to debug the program step by step. It works fine until the first use of fgets. When I try print out the line read by fgets on the first iteration, it gives me this:

(gdb) print line
$6 = "\rtest\r18/04/2010\rtest2\r03/05/2010\rtest3\r05/08/2009\rtest4\r\n\000\000\000\000q\352\261\a\370\366\377\267.N=\366\000\000\000\000\003\000\000\000\370xC\000\000\000\000\000\000\000\000\000\001\000\000\000\227\b\000\000\070\367\377\267H\364\377\267\362\202\004\bdoD\000\354\201\004\b\001\000\000\000\304oC\000p\363\377\277\260zC\000D\363\377\277\n!B\000\064\363\377\277\354\201\004\b(\363\377\277TzC\000\000\000\000\000\070\367\377\267\001\000\000\000\000\000\000\000\001\000\000\000\370xC\000\001\000\000\000\000\000\312\000\000\000\000\000\377\260\360\000\001\000\000\000\277\000\000\000\364\317\000\000\344\261\\\000\000\000\000\000p\363\377\277|\233\004\b\350\362\377\277 \204\004\b\005\000\000\000|\233\004\b\030\363\377\277"

It looks like fgets reads the remaining entries and then stores them all in a single string.

I am not sure why it is doing this.

Here is the main code:

int main(int argc, char* argv[]) {
    FILE* file;
    int numEntries, i = 0;
    int index = atoi(argv[1]);
    char line[SIZE];
    JournalEntry *entry;

    /*argument provided is the entry user wants to be displayed*/
    if (argc > 2) {
        perror("Error: Too many arguments provided");
    }
    file = fopen("journalentries.txt", "r");
    if (file == NULL) {
        perror("Error in opening file");
    }

    if (fscanf(file, "%d", &numEntries) != 1) {
        perror("Unable to read number of entries");
    }

    entry = (JournalEntry*)malloc(numEntries  * sizeof(JournalEntry));
    if (entry == NULL) {
        perror("Malloc failed");
    }

    for (i = 0; i < numEntries; i++) {
        if (fscanf(file, "%d/%d/%d", &entry[i].day, &entry[i].month, &entry[i].year) != 3) {
            perror("Unable to read date of entry");
        }

        if (fgets(line, sizeof(line), file) == NULL) {
            perror("Unable to read text of entry");
        }
    }

    printf("%d-%02d-%02d %s: ", entry[index].year, entry[index].month, entry[index].day, entry[index].text);

    if(ferror(file)) {
        perror("Error with file");
    }

    fclose(file);
    free(entry);

    return 0;
}

The file that I have to read: The very first line contains the number of entries to be read

4
12/04/2010
test
18/04/2010
test2
03/05/2010
test3
05/08/2009
test4

The struct JournalEntry located in the header file:

typedef struct {
    int day;
    int month;
    int year;
    char text[250];
} JournalEntry;

解决方案

It looks like fgets reads the remaining entries and then stores them all in a single string.

Yes, '\r' is not line terminator. So when fscanf stops parsing at the first invalid character, and leaves them in the buffer, then fgets will read them until end of line. And since there are no valid line terminators in the file, that is until end of file.

You should probably fix the file to have valid (Unix?) line endings, for example with suitable text editor which can do it. But that is another question, which has been asked before (like here), and depends on details not included in your question.

Additionally, you need dual check for fscanf return value. Use perror only if return value is -1, otherwise error message will not be related to the error at all. If return value is >=0 but different from what you wanted, then print custom error message "invalid input syntax" or whatever (and possibly use fgets to read rest of the line out of the buffer).

Also, to reliably mix scanf and fgets, I you need to add space in the fscanf format string, so it will read up any whitespace at the end of the line (also at the start of next line and any empty lines, so be careful if that matters), like this:

int items_read = scanf("%d ", &intvalue);

As stated in another answer, it's probably best to read lines with fgets only, then parse them with sscanf line-by-line.

这篇关于与fgets()的fscanf后不工作()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆