【问题标题】:In C: Reading integers from a file在 C 中:从文件中读取整数
【发布时间】:2013-06-01 00:17:15
【问题描述】:

我有一个基本上从文件中读取整数的函数:

FILE *file;

file = fopen("filename.txt", "r");
fscanf(file, "%d", &(*pn));
fscanf(file, "%d", &(*pm));
fscanf(file, "%d", &(*pmax));

printf("*pm = %d\n", *pm);
printf("*pn = %d\n", *pn);
printf("*pmax = %d\n", *pmax);

首先我尝试了以下文件:

5 4

128

如我所愿,我的输出是正确的:

*pm = 4
*pn = 5
*pmax = 128

但真正的文件是:

P2

5 4

128

我希望我的输出与以前一样,但后来我得到了:

*pm = 0
*pn = 0
*pmax = 0

出了什么问题?

【问题讨论】:

  • 您需要跳过开头的“P2”。在读取整数之前尝试使用fscanf(file, "\n")
  • 你应该真正展示你对pnpmpmax的声明和初始化。使用&(*pn) 是一种晦涩难懂的写法pn
  • 这就是你不测试 fscanf 的返回值得到的结果,它给出了成功转换的项目数。

标签: c file output


【解决方案1】:

文件开始

P2

用字母,而不是数字。因此,fscanf 调用都无法将输入转换为整数,不消耗任何输入。

您应始终检查 scanf 系列函数的返回值,以发现由于输入格式错误或流损坏而导致的转换失败。

您可以跳过第一行,例如,

fscanf(file, "%*[^\n]");

【讨论】:

  • @ThiG。您还可以声明一个足够大的缓冲区并调用fgets(buffer, sizeof buffer, file);。或者,如果您知道第一行有多长,fseek(file, line_length, SEEK_SET);。可能还有很多其他方法,但不知何故,您必须越过第一行才能从第二行开始扫描。
  • +1 这是一个相当可靠的答案。当fscanf 因读取失败而失败时,停止处理。当fscanf 因转换失败而失败时,使用此答案末尾的代码丢弃一行,打印一条消息,指示“输入无效。重试...”并重试。
【解决方案2】:

它试图读取int,但得到P。由于它无法转换为int,因此它留在了流中,并且转换失败。第二个和第三个数字也是如此。

重新读取您的输入,您可能想做一些事情,例如读取一个字符串,然后尝试将其转换为一个 int。您可以使用%s 阅读,然后使用strtol 进行转换。如果没有转换,请忽略它并重试。

【讨论】:

    【解决方案3】:
    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    
    char *inputString(FILE* fp, size_t size){
    //The size is extended by the input with the value of the provisional
        char *str;
        int ch;
        size_t len = 0;
        str = realloc(NULL, sizeof(char)*size);//size is start size
        if(!str)return str;
        while(EOF!=(ch=fgetc(fp)) && isspace(ch));//skip space chars
        ungetc(ch, fp);
        while(EOF!=(ch=fgetc(fp)) && !isspace(ch)){
            str[len++]=ch;
            if(len==size){
                str = realloc(str, sizeof(char)*(size+=16));
                if(!str)return str;
            }
        }
        str[len++]='\0';
    
        return realloc(str, sizeof(char)*len);
    }
    
    enum {false, true };
    
    int readInt(FILE *fp, int *n){
        char *token, *endp;
        long wk;
    
        for(;;){
            token = inputString(fp, 16);//separated by space character
            if(!*token){//EOF
                free(token);
                return false;
            }
            wk = strtol(token, &endp, 0);
            if(*endp=='\0')break;//success read int
            free(token);
        }
        *n = (int)wk;
        free(token);
        return true;
    }
    
    int main(void){
        FILE *file;
        int n, m, max,i;
    
        n = m = max = 0;
        file = fopen("filename.txt", "r");
        readInt(file, &n);
        readInt(file, &m);
        readInt(file, &max);
    /*
        printf("debug:");
        if(readInt(file, &i)==false){
            printf("false\n");
        }
    */
        fclose(file);
    
        printf("m = %d\n", m);
        printf("n = %d\n", n);
        printf("max = %d\n", max);
        return 0;
    }
    

    【讨论】:

    • 可能有点荒谬。
    • 自 C99 以来,将标识符 true/false 重新定义为枚举是一个坏主意。
    猜你喜欢
    • 2014-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-23
    • 1970-01-01
    相关资源
    最近更新 更多