Чтение из файла на C

#c

#c

Вопрос:

Мне нужно прочитать из файла с помощью C.

  #include <stdio.h>

struct record{
    char name[2];
    int arrival_time;
    int job_length;
    int job_priority;
};

const int MAX = 40;

main(){

struct record jobs[MAX];
FILE *f;
fopen("data.dat","rb");
int count =0;
while(fscanf(f, "%c%c %d %d %d", amp;jobs[count].name, amp;jobs[count].arrival_time, amp;jobs[count].job_length, amp;jobs[count].job_priority) != EOF){
count  ;
}
int i;
for(i =0;i<count;i  ){
printf("%c%c %d %d %d", amp;jobs[count].name, amp;jobs[count].arrival_time, amp;jobs[count].job_length, amp;jobs[count].job_priority);
}


}
  

Формат файла данных следующий:

      A1 3 3 3
     B1 4 4 4
     C1 5 5 5
  

Первый — это char[2], а остальные три — int . Я не могу получить правильный код для чтения до конца файла.

Кто-нибудь сталкивался с этим раньше?

Обновленный код.

Комментарии:

1. Половина вопросов на C здесь почти идентичны этому — за исключением того, что большинство из них также содержат некоторый исходный код. Это невозможно отладить без исходного кода…

2. Я не могу получить правильный код… Покажите этот код.

Ответ №1:

Необходимо внести несколько изменений — в первую очередь, вам нужно ссылаться на jobs массив структур:

 #include <stdio.h>

struct record{
    char name[2];
    int arrival_time;
    int job_length;
    int job_priority;
};

const int MAX = 40;

int main(void)
{
    struct record jobs[MAX];
    int i = 0;
    int j;
    FILE *f = fopen("data.dat","rb");

    while (fscanf(f, "%c %d %d %d", amp;jobs[i].name[0], amp;jobs[i].arrival_time,
                  amp;jobs[i].job_length, amp;jobs[i].job_priority) == 4 amp;amp; i < MAX)
        i  :

    for (j = 0; j < i; j  )
        printf("%c %d %d %dn", jobs[j].name[0], jobs[j].arrival_time,
               jobs[j].job_length, jobs[j].job_priority);

    return(0);
}
  

Я слежу за тем, чтобы цикл не переполнял массив. Я распечатываю данные (это самая простая форма проверки того, что вы прочитали то, что ожидали). Самой тонкой проблемой является использование jobs[i].name[0] ; это необходимо для чтения и печати одного символа. Нет никакой гарантии, что в нем есть какое-либо конкретное значение jobs[i].name[1] ; в частности, вполне вероятно, что это не NUL '' , и поэтому имя не завершается нулем. Кажется немного странным использовать односимвольное имя; возможно, вам захочется иметь более длинную строку в структуре:

 char name[MAX];  // Lazy reuse of MAX for two different purposes!

fscanf(f, "%.39s ...", jobs[i].name, ...

printf("%s ...", jobs[i].name, ...
  

Теперь amp; он не нужен. %.39s Обозначение is используется для чтения строки с ограниченной длиной до первого пробела. Обратите внимание, что размер в строке на единицу меньше размера массива. Часто бывает проще просто создать строку формата sprintf() , чтобы получить правильный размер.

Код не проверяет fopen() инструкцию на ошибку.


Ваш код выводит 1 3 3 вместо A1 3 3 3. Я попытался добавить к нему второй%c, и это не разрешило проблему.

Я обсуждал имена длиной более одного символа…

Если вам нужно прочитать «A1», вам нужно, чтобы name член был больше, чтобы вы могли завершать строку нулевым значением, и вам нужно использовать %s вместо %c чтения значения, и вам нужно потерять индекс amp; и, и вам нужно защитить свой код от переполнения буфера (потому что там, где выожидайте ‘A1’, кто-то неизбежно введет ‘A1B2C3D4D5F6G7H8I9J10K11L12M13’ и нанесет ущерб вашему коду, если вы не защитите от переполнения буфера. Кстати, изменение в тестировании результата fscanf() (от == EOF до != 4 также было защитой от неправильного ввода; вы можете получить нулевые успешные преобразования без чтения каких-либо символов, в целом — хотя ваш %c будет потреблять один символ за итерацию).

 #include <stdio.h>

struct record{
    char name[4];
    int arrival_time;
    int job_length;
    int job_priority;
};

const int MAX = 40;

int main(void)
{
    struct record jobs[MAX];
    int i = 0;
    int j;
    FILE *f = fopen("data.dat","rb");

    while (fscanf(f, "%.3s %d %d %d", jobs[i].name, amp;jobs[i].arrival_time,
                  amp;jobs[i].job_length, amp;jobs[i].job_priority) == 4 amp;amp; i < MAX)
        i  :

    for (j = 0; j < i; j  )
        printf("%s %d %d %dn", jobs[j].name, jobs[j].arrival_time,
               jobs[j].job_length, jobs[j].job_priority);

    return(0);
}
  

Комментарии:

1. Ваш код выводит 1 3 3 вместо A1 3 3 3. Я попытался добавить к нему второй%c, и это не разрешило проблему.

Ответ №2:

Вам нужно получить строку и проанализировать ее в соответствии с типом, который вы хотите прочитать.

    while(fgets(line, 80, fr) != NULL)
   {
     /* get a line, up to 80 chars from fr.  done if NULL */
     sscanf (line, "%s %d %d %d", amp;myText, amp;int1, amp;int2, amp;int3);
   }
  

Смотрите пример здесь:
http://www.phanderson.com/files/file_read.html

Комментарии:

1. Я бы использовал "%2s" , или (если тип myText char [2] соответствует тому, что указано в OP) "%c%c" и myText, myText 1 в качестве аргументов.

Ответ №3:

Примечание: это не лучший способ, кто-то другой ответил гораздо более простым решением, используя строки формата и fgets, которые в основном будут делать то, что я хотел сделать, в одной простой строке.

Я предполагаю, что вы хотите что-то вроде этого. Обратите внимание, что я вообще не тестировал это, так как я просто написал это довольно быстро.

 #include <stdio.h>
FILE *fileInput;

main()
{
    char* path="whatever.txt";
    fileInput = fopen(path, "r");
    int i=0;

    while (fgets(line,100,fi)!=NULL)
    {
         token[0] = strtok(line, " ");
         //now you can do whatever you wanna do with token[0]
         //in your example, token[0] is A1 on the first iteration, then B1, then C1
         while(token[i]!= NULL)
         {
             //now token[i] can be converted into an int, probably using atoi
             //in your example, token[i] will reference 3 (3 times) then 4, etc
         }
    }

}
  

Надеюсь, это поможет!

Комментарии:

1. Что token в этом коде? Кроме того, почему fileInput глобальный?

2. токен — это «токен», возвращаемый методом strtok. по сути, он будет повторно отображать каждую «ячейку» вашего кода. если вам нужна дополнительная информация, просто погуглите strtok, и вы должны получить там то, что вам нужно.

3. черт. я забыл там i . извините, lol ….. пожалуйста, просто посмотрите один из других ответов, somoene, вероятно, уже придумал более подробное решение. Я немного устал от стандартного c, поскольку уже много лет не делаю ничего, кроме c #. извини, приятель

4. Я знаю, как strtok это работает, проблема не в этом. Вы нигде не объявляли ничего с именем token .

Ответ №4:

Нет, строки не содержат целых чисел. Каждая строка представляет собой строку, которую можно легко разобрать на четыре более короткие строки. Затем каждая из строк может быть либо извлечена и сохранена в вашей структуре, либо преобразована в целые числа, которые вы можете сохранить в своей структуре.

scanf Функция — это обычный способ, которым люди выполняют такого рода синтаксический анализ входных строк, когда формат данных прост и понятен.