2013-07-10 3 views
0

Я пытаюсь прочитать из файла в массив. Мой файл называется Players.txt содержит:Использование fscanf в C

Del Piero|3|Italy|Juventus| 
Ronaldo|0|Portugal|Real Madrit 

Я использовал fscanf, но он не работает правильно, я не делаю прямо преобразование.

может кто-нибудь помочь мне прочитать и сохранить их в массивы. Как имя массива игрока содержать { Del Piero, Ronaldo}

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

#define NUM_PLAYERS 20 
#define NAME_LENGTH 100 
#define COUNTRY_NAME 20 

int main (void) 

{ 
    FILE *Players; 

    char player_name [NUM_PLAYERS][NAME_LENGTH] = {0}; 
    char country_name[NUM_PLAYERS][COUNTRY_NAME] = {0}; 
    char team_name[NUM_PLAYERS][NAME_LENGTH] = {0}; 
    int goals_scored[NUM_PLAYERS] = {0}; 
    int i; 

    Players = fopen("G:\\COP2220\\Project 5\\Players.txt", "r"); 
    if (Players == NULL) 
    { 
     printf("File not found.\n"); 
    } 
    else 

    { 

     while (fscanf(Players, " %[^|]s %[^|]d %[^|]s %[^|]s",player_name[i],&goals_scored[i],country_name[i],team_name[i])) 
     { 
      printf("The player %s, scored %d from %s plays in %s\n", player_name, goals_scored,country_name, team_name); 
     } 
    } 

    fclose(Players); 
    return 0; 
} 
+0

вы, вероятно, следует инициализировать 'i' в '0' – tay10r

+0

@TaylorFlores я сделал это сейчас, но это правильный цикл в то время? – user2512806

+0

ваши вызовы функций немного от – tay10r

ответ

1

Вы никогда не потребляют «|» символы между полями. Вместо этого вы читаете только до "|" персонаж. Попробуйте изменить свой формат строки, чтобы что-то вроде:

"%[^|]|%[^|]d|%[^|]|%[^|]" 
+0

да, я знаю, что это не было после первого имени, ладно, я попробую это – user2512806

+0

Woah, что с downvotes? – Gian

+0

Я не ответил на этот вопрос, но это, вероятно, потому, что у вас нет подробного объяснения. – tay10r

1

Формат %[^|]sscanf читает строку, не являющихся | символов, за которыми следует s характер, который никогда не может соответствовать (со следующего символа после строки, если она существует , должен быть |, а не s). Вы, наверное, хотите что-то больше похоже:

while (4 == fscanf(Players, " %99[^|\n]|%d| %19[^|\n]| %99[^|\n]", player_name[i], &goals_scored[i], country_name[i], team_name[i])) 

Примечание дополнительные ограничения на размер строки, чтобы избежать переполнения массивов, и Newlines в моделях, так что они не могут быть включены в любой из строк (но может появиться между строки).

Отметим также, что это будет соответствовать вашей второй линии, но оставить |Madrit для чтения следующего вызова fscanf, так что вы можете поставить

fscanf(Players, "%*[\n]%*c"); 

в петле, чтобы прочитать остальную часть выстройте линию до новой строки и выбросите ее.

+0

+1 это отвечает на вопрос – tay10r

+0

@ Крис Додд | Madrit не должен быть таким, он должен быть настоящим Мадритом вместе. Моя ошибка, извините – user2512806

+0

Игроки = fopen ("G: \\ COP2220 \\ Project 5 \\ Players.txt", "r"); if (Players == NULL) { printf ("Файл не найден. \ N"); } прочее { i = 0; while (4 == fscanf (Игроки,% 99 [^ | \ n] |% d |% 19 [^ | \ n] |% 99 [^ | \ n] ", player_name [i], & goals_scored [i ], country_name [i], team_name [i])) { printf ("Игрок% s, набравший% d из% s играет в% s \ n", player_name, goals_scored, country_name, team_name); i ++; } printf ("end"); } fclose (Players); ' – user2512806

2

[] тип все в себе, вы не следует добавить s или d в его конце. Все, что вам действительно нужно сделать, это изменить формат для этого:

"%[^|] | %d | %[^|] | %[^|]|\n" 

И попробуйте изменить свой while цикл, чтобы сломаться, когда fscanf не возвращается 4.

Вот некоторые рабочий код:

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

#define NUM_PLAYERS 20 
#define NAME_LENGTH 100 
#define COUNTRY_NAME 20 

int 
main (void) 
{ 
    FILE * Players; 
    char player_name [NUM_PLAYERS][NAME_LENGTH] = {0}; 
    char country_name[NUM_PLAYERS][COUNTRY_NAME] = {0}; 
    char team_name[NUM_PLAYERS][NAME_LENGTH] = {0}; 
    int goals_scored[NUM_PLAYERS] = {0}; 
    int i = 0, ret = 0; 

    Players = fopen("testfile", "r"); 

    if (Players == NULL) 
     { 
      printf("File not found.\n"); 
     } 

    else 
     { 
      for (;;) 
       { 
        ret = fscanf(Players, "%[^|] | %d | %[^|] | %[^|]|\n", 
          player_name[i], 
          &goals_scored[i], 
          country_name[i], 
          team_name[i]); 

        if (ret != 4) 
         { 
          printf ("only %d arguments were matched\n", ret); 
          break; 
         } 

        printf("The player %s, scored %d from %s plays in %s\n", 
          player_name[i], 
          goals_scored[i], 
          country_name[i], 
          team_name[i]); 
        i++; 
       } 
      fclose(Players); 
     } 
    return 0; 
} 
+0

Хорошо, это отображает только первую строку в моем файле и почему for (;;) как пустое, для чего это необходимо. – user2512806

+0

@ user2512806 'for (;;)' обычно используется, когда оценка происходит где-то еще в цикле, который не находится в начале или в конце. Я тестировал это на своем компьютере. весь код не работал или только строка формата? – tay10r

+0

код работал, но он печатал только первую строку не обоих. – user2512806

0

Ваш формат строки сканирования неверно. %[..] сам по себе является спецификатором формата, добавляя s или d после того, как он был принят как буква s или d в строке сканирования, а не %s или %d, как вы ожидаете.

Кроме того, ваш printf() печатает адрес goals_scored, а не сохраненное значение для проигрывателя. Вы забыли индексировать массив.

Возможно, чтобы ваша строка сканирования формата работала, но поскольку последнее поле является необязательным, у вас есть определенная сложность в этом случае. В приведенном ниже коде мы имеем дело с этим, явно указав, что новая строка не должна быть частью последнего поля.Затем %*c отбросит либо |, либо \n в конце. Пространство в конце строки сканирования позволяет fscanf() перейти к следующей строке в случае, если | был отброшен.

while (fscanf(Players, " %[^|]|%d|%[^|]|%[^|\n]%*c ", 
       player_name[i], &goals_scored[i], country_name[i], team_name[i]) == 4) 
    { 
     printf("The player %s, scored %d from %s plays in %s\n", 
       player_name, goals_scored[i], country_name, team_name); 
    } 

Однако эта проблема, кажется, идеально подходит для strtok(). Преимущество заключается в том, что у вас есть больше контроля над тем, как обращаться с каждым полем, и вы можете получить дополнительную информацию о том, где ошибки происходят во время разбора строки.

int parse_line (char *buffer, 
       char *name, int *goals, char *country, char *team, 
       char **rest) 
{ 
    char *tok = strtok(buffer, "|"); 
    int count = 0; 
    while (tok && count < 4) { 
     ++count; 
     switch (count) { 
     case 1: strcpy(name, tok); break; 
     case 2: *goals = atoi(tok); break; 
     case 3: strcpy(country, tok); break; 
     case 4: strcpy(team, tok); break; 
     default: break; 
     } 
     tok = strtok(0, "|"); 
    } 
    *rest = tok; 
    return count; 
} 

Вы могли бы изменить свой код для чтения в строке данных, а затем кормить эту строку в функции parse_line().

char buf[MAX_LINE_LENGTH]; 
char *rest; 
while (fgets(buf, sizeof(buf), Players) != 0) { 
    parse_line(buf, 
       player_name[i], &goals_scored[i], country_name[i], team_name[i], 
       &rest); 
    printf("The player %s, scored %d from %s plays in %s\n", 
      player_name, goals_scored[i], country_name, team_name); 
} 
+0

@ user2512806: Работает ли какое-либо из моих предложений? – jxh

+0

Я не знаю, я новичок в C, и я не видел всего этого, что вы разместили, и я не очень хорошо понимаю. Я больше искал помощи в программе, которую у меня уже есть. Однако, большое спасибо за вашу помощь. – user2512806

+0

@ user2512806: Посмотрите на первое предложение. Он просто исправляет вашу текущую строку сканирования и 'fscanf()' call и ваш оператор печати. – jxh

Смежные вопросы