0

我正在尝试从文件读入数组。我的名为 Players.txt 的文件包含:

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;
}
4

4 回答 4

2

[]本身就是一种类型,您不应该在其末尾附加s或附加。d您真正需要做的就是将格式更改为:

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

并考虑将循环更改为在不返回while时中断。fscanf4

这是一些工作代码:

#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;
}
于 2013-07-10T03:07:17.347 回答
1

你从来没有真正消费过“|” 字段之间的字符。相反,您只阅读到“|” 特点。尝试将格式字符串调整为:

"%[^|]|%[^|]d|%[^|]|%[^|]"
于 2013-07-10T02:25:54.717 回答
1

scanf格式%[^|]s读取一串非|字符后跟一个s字符,该字符永远不会匹配(因为字符串后面的下一个字符,如果存在,必须是 a |,而不是 a s)。您可能想要更多类似的东西:

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

请注意额外的字符串大小限制以避免数组溢出,以及模式中的换行符,以便它们不能包含在任何字符串中(但可以出现在字符串之间)。

另请注意,这将与您的第二行匹配,但将留待|Madrit下次调用 fscanf 时读取,因此您可能需要输入

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

在循环中读取该行的其余部分到换行符并将其丢弃。

于 2013-07-10T02:57:36.160 回答
0

您的格式扫描字符串不正确。the%[..]本身就是格式说明符,在它被视为文字或扫描字符串之后添加sor ,而不是您期望的or 。dsd%s%d

此外,您printf()打印出goals_scored地址而不是播放器的存储值。您忘记为数组编制索引。

可以让您的格式扫描字符串起作用,但由于最后一个字段显示为可选,因此您在处理这种情况时会遇到一些复杂性。在下面的代码中,我们通过明确指出换行符不应该是最后一个字段的一部分来处理这个问题。然后%*c将丢弃最后的 the|或 the \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);
}
于 2013-07-10T03:09:58.193 回答