【问题标题】:fscanf can't read the first integer of my file input in C but reads the restfscanf 无法读取我在 C 中输入的文件的第一个整数,但可以读取其余部分
【发布时间】:2013-07-08 22:14:13
【问题描述】:

我的程序需要从文件中读取输入。该文件的格式为“int int int”,然后是一些星号,表示您需要在此处停止阅读。我想将它们存储在一个结构数组中,我做到了。但似乎我的程序无法读取输入文件的第一个整数。我用 printf 检查了它,但我对此无能为力。请帮忙。代码如下:

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


struct points{
    int i;
    int x;
    int y;
};
int main(){
    int lines = 0;
    char c, e;
    int i, j, x ,y, a, b, temp ;
    FILE *fp;
    fp = fopen("input.txt", "r");
    if (fp != NULL){
        while ((e = fgetc(fp)) != '*'){                     
            if (c == '\n'){
                lines++;
            }
            fscanf(fp, "%d%d%d", &i, &x, &y);
            struct points pt[lines];
            for (j = 0; j <= lines; j++){
                pt[j].i = i;
                pt[j].x = x;
                pt[j].y = y;
                printf("%d ", pt[j].i);
            }
            for (a = 0; a<=lines; a++){
                for (b = a + 1; b <= lines; b++){
                    if (pt[a].x > pt[b].x){
                        temp = pt[a].x;
                        pt[a].x = pt[b].x;
                        pt[b].x = temp;
                    } 
                }
            }
        }           
    }
    else{
        printf("Cannot open File!\n");      
    }
    printf("lines = %d\n", lines);
    return 0;
}

【问题讨论】:

  • for (j = 0; j &lt;= lines; j++){ 应该是 for (j = 0; j &lt; lines; j++){ 恕我直言。 2)顺便说一句:你打算先计算 '\n' ,然后倒带并阅读实际行吗?

标签: c file-io scanf


【解决方案1】:

您的代码:

        while ((e = fgetc(fp)) != '*') {                             
            if (c == '\n'){
                lines++;
            }
            fscanf(fp, "%d%d%d", &i, &x, &y);

将读取第一个字符并将其丢弃,如果它不是星号,然后将尝试在它丢弃的第一个字符之后读取 3 个整数。如果第一个字符是数字,那么看起来您“丢失”(部分)第一个数字。

您还有一个问题,您似乎试图将值读入一个块本地数组pt,该数组存在于while 循环的单次迭代中(因此重新创建它时每个都没有(垃圾)内容迭代),然后你想在它超出范围的循环之后使用它(所以这段代码不会编译)。

你想要的可能更像是:

#define MAX_POINTS  100
struct points pt[MAX_POINTS];
int i = 0;
while (i < MAX_POINTS && 3 == fscanf(fp, "%d%d%d", &pt[i].i, &pt[i].x, &pt[i].y)) {
    printf("%d ", pt[i].i);
    i++;
}
for (int a = 0; a <= i; a++) {
    for (int b = a+1; b <= i; b++) {
        :

请注意,这会向上读取整数,直到找到看起来不像整数的东西(例如星号,但可以是其他任何东西,包括文件结尾),而不是在找到星号之前读取.如果您想在看到星号之前一直阅读,您需要决定如何处理既不是星号也不是整数的任何内容。

编辑

对于如何读取直到*** 的数字,然后在它们之后读取更多数字(可能还有更多星号)的替代问题,您可以使用以下内容:

int val;
char buffer[20];
do {
    /* start of a group */
    while (1 == fscanf(fp, "%d", &val)) {
        /* read an integer within a group */
    }
    /* fp is at EOF or something not an integer. */
    /* so read it and loop if its '***' */
} while (1 == fscanf(" %19[*]", &buf) && !strcmp(buf, "***"));

【讨论】:

  • 假设我的 input.txt 是这样的:1 2 3 2 3 4 5 6 7 *** 1 3 4 2 3 5 3 4 7 输入结束 我想对 *** 之前的整数做一些事情,我也会对之后的整数做一些事情。简而言之,*** 将输入分为几种情况。我将如何实现循环?
【解决方案2】:

您是否尝试过使用格式字符串"%d %d %d" 而不是"%d%d%d"(即带空格)?

此外,我还看到了其他几个问题:

  1. 您使用while 循环来查找行中的第一个'*',但随后您要求fscanf 从该位置开始解析3 个ints。通过查看'*' 可能无法找到int...
  2. 您还可以在块的中间声明变量struct points pt[lines];;这不是有效的 C 语法。

一旦你解决了这些问题,问题可能就解决了。

【讨论】:

  • 空格没有任何区别 -- %d 隐含地自动跳过空格。
  • 不要用问题来回答问题。另外,指出所有错误。例如:ec的使用; fgetc 的返回值为 int;应该检查EOF 返回值fgetc 而不是*;如果字符不是换行符,则需要调用ungetc;在解析星星时需要检查fscanf 的结果; pt 如何在 while 循环中是本地的;循环如何在pt 数组的末尾写入一个。您可能还可以找到其他人。
  • @jxh 也可以,你可以写一个答案:)
  • @feralin:我只是想帮助你。通常,单行问题的答案将被标记为不是答案。而且,我当天的积分已经用完了。
猜你喜欢
  • 2013-02-15
  • 2017-06-15
  • 2021-12-22
  • 2021-04-21
  • 2019-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-10
相关资源
最近更新 更多