繁体   English   中英

在C中使用fscanf

[英]Using fscanf in C

我正在尝试从文件读取到数组。 我的文件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;
}

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

"%[^|] | %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;
}

您从未真正消耗过“ |” 您的字段之间的字符。 相反,您只能读到“ |” 字符。 尝试将格式字符串调整为以下形式:

"%[^|]|%[^|]d|%[^|]|%[^|]"

所述scanf格式%[^|]s读取的非字符串| 字符后跟一个永远不会匹配的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]))

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

还请注意,这将与第二行匹配,但将使|Madrit可以在下一次调用fscanf时读取,因此您可能需要输入

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

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

您的格式扫描字符串不正确。 %[..]是本身的格式说明,添加sd后,它只是采取的是文字sd在扫描串,而不是%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);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM