#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
Функция — это обычный способ, которым люди выполняют такого рода синтаксический анализ входных строк, когда формат данных прост и понятен.