fscanf не может прочитать первое целое число моего файла, введенного в C, но читает остальные

Моя программа должна прочитать ввод из файла. Файл имеет формат «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;
}

person James Reynald Mase    schedule 10.07.2013    source источник
comment
for (j = 0; j <= lines; j++){ должно быть for (j = 0; j < lines; j++){ ИМХО. 2) Кстати: вы собираетесь сначала подсчитать '\n', а затем перемотать и прочитать фактические строки?   -  person wildplasser    schedule 11.07.2013


Ответы (2)


Ваш код:

        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, "***"));
person Chris Dodd    schedule 10.07.2013
comment
Допустим, мой файл input.txt выглядит примерно так: 1 2 3 2 3 4 5 6 7 *** 1 3 4 2 3 5 3 4 7 конец ввода Я хочу что-то сделать с целыми числами до ***, и я бы сделал то же самое с целыми числами после этого. Короче говоря, *** разделяет ввод на несколько случаев. Как мне реализовать цикл? - person James Reynald Mase; 11.07.2013

Пробовали ли вы использовать строку формата "%d %d %d" вместо "%d%d%d" (т.е. с пробелами)?

Кроме того, есть несколько других проблем, которые я вижу:

  1. Вы используете цикл while, чтобы найти первые '*' в строке, но затем вы просите fscanf проанализировать 3 int, начиная с этого места. Возможно, он не сможет найти int, взглянув на '*'...
  2. Вы также объявляете переменную struct points pt[lines]; в середине блока; это недопустимый синтаксис C.

Как только вы исправите эти вещи, проблема может быть устранена.

person feralin    schedule 10.07.2013
comment
пробелы не будут иметь значения - %d неявно автоматически пропускает пробелы. - person Chris Dodd; 11.07.2013
comment
Не отвечайте вопросом на вопрос. Также укажите на все ошибки. Например: использование e против c; возвращаемое значение fgetc равно int; следует проверять, что EOF возвращает значение fgetc вместо *; необходимость вызывать ungetc, если символ не является новой строкой; необходимость проверки результата fscanf при разборе звезд; как pt является локальным для цикла while; как циклы записывают единицу за конец массива pt. Там могут быть другие, которые вы можете найти. - person jxh; 11.07.2013
comment
@jxh также, вы могли бы просто написать ответ :) - person feralin; 11.07.2013
comment
@feralin: я просто пытаюсь тебе помочь. Как правило, ответы, состоящие из вопроса в одну строку, будут помечены как неответ. И у меня максимум очков за день. - person jxh; 11.07.2013