简体   繁体   English

如何在 txt 文件中的字符串上正确限制 fscanf? (需要读取用空格和“-”分隔的字符串和整数)

[英]How to restrict fscanf properly on a string from a txt file? (need to read strings and integers seperated with whitespace AND “-”)

I really hope someone is up for the task of helping, or pointing me to ressources that can, because I've been struggling with this for hours now.我真的希望有人能够提供帮助,或者将我指向可以的资源,因为我已经为此苦苦挣扎了几个小时。

I do not have a lot of experience in C yet, or coding in general,and I have this assignment where I need to read a txt file with soccer/football match results into an array, and I can't get the "fscanf" part to work.我在 C 或一般编码方面没有很多经验,我有这个任务,我需要将带有足球/足球比赛结果的 txt 文件读入数组,但我无法获得“fscanf”部分工作。

I've created a struct with the details I need to save and work with later.我创建了一个结构,其中包含我需要保存和稍后使用的详细信息。 (right now the date is just saved as a string, alternatively I could save that information as 2 integers DD MM). (现在日期只是保存为字符串,或者我可以将该信息保存为 2 个整数 DD MM)。

I'm calling my "file_read" from main (int function, as I need to know how many lines read later on for qsort), and passing my "struct type" array and.txt file as parameter to that function.我从main(int function,因为我需要知道稍后为qsort读取多少行)调用我的“file_read”,并将我的“struct type”数组和.txt文件作为参数传递给该function。

In the "file_read" function I have an int variable for counting, and opening the file specified in main, checking for NULL, and then "getting to it" by calling the function "read_match" and passing my file pointer as parameter. In the "file_read" function I have an int variable for counting, and opening the file specified in main, checking for NULL, and then "getting to it" by calling the function "read_match" and passing my file pointer as parameter.

THIS IS WHERE I'M HAVING TROUBLE (maybe earlier according to the more code savvy)!这是我遇到麻烦的地方(根据更精通代码的情况可能更早)!

I can't figure out how to distinguish the various segments(?) of the textfile, using the %s and whatnot, to be able to properly save it in the various struct types.我不知道如何区分文本文件的各个段(?),使用 %s 和诸如此类的东西,以便能够正确地将其保存在各种结构类型中。

The data in the txt file looks like this: txt 文件中的数据如下所示:

  (day)   (date)(time)   (teamA)(teamB) (goalsA)(goalsB)  (spectators)
    Son     28/07 18.00     BIF - OB      3 - 2     13689  
    Man     29/07 19.00     AaB - SIF     3 - 1     5885   
    Fre     02/08 19.00     SIF - HOB     2 - 3     3468 

(added struct names to the data above) (在上面的数据中添加了结构名称)

And my entire code, so far, looks like this: (scroll to bottom)到目前为止,我的整个代码如下所示:(滚动到底部)

(I tried various approaches like %[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ] %[0123456789] and what you see below, but it always seems to go bad after the first "-" in the txt file. There's a print function added for troubleshooting) (I tried various approaches like %[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ] %[0123456789] and what you see below, but it always seems to go bad after the first "-" in the txt file. There's a print function added for troubleshooting)

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

#define STR_SHORT 10
#define STR_LONG 70
#define MATCHES 300

typedef struct {
    char day[STR_SHORT];
    char date[STR_SHORT];
    char time[STR_SHORT];
    char team_A[STR_SHORT];
    char team_B[STR_SHORT];
    int goals_A;
    int goals_B;
    int spectators;
} Match;

int file_read(char *file_input, Match arr_matches[]);
Match read_match(FILE *file_ptr);

/*MAIN*/
int main(void) {
    Match arr_matches[MATCHES];
    int n;
    n = file_read("data.txt", arr_matches);
    printf(" %d", n);
    
    return 0;
}

/*FUNCTIONS*/

int file_read(char *file_input, Match arr_matches[]) {
    int r = 0;
    FILE *file_ptr = fopen(file_input, "r");

    if (file_ptr == NULL) {
        printf("Error! Can't open file!");
        return 1;
    }

    while(!(feof(file_ptr))){
       arr_matches[r] = read_match(file_ptr);
       ++r;
    }
    fclose(file_ptr);
    return r;
}

Match read_match(FILE *file_ptr) {
    Match input;

    fscanf(file_ptr,    " %s %s %s"
                        " %s  %7s"
                        " %2d %*[-] %2d"
                        " %d",
                   input.day, input.date, input.time, 
                   input.team_A, input.team_B,
                   &input.goals_A, &input.goals_B,
                   &input.spectators);
  printf("(day) %s (date) %s (time) %s (teamA) %s (teamB) %s (scoreA) %d (scoreB) %d (spect) %d\n", 
  input.day, input.date, input.time, input.team_A, input.team_B, input.goals_A, input.goals_B, input.spectators);
  return input;
}

Usable feedback would be much appreciated, and ofc, let me know if I need to elaborate on something.非常感谢有用的反馈,如果我需要详细说明,请告诉我。

Thanks!谢谢!


Edited: Been trying out STRTOK, I might be able to combine this somehow...编辑:一直在尝试STRTOK,我也许可以以某种方式结合它......

#include <string.h>
#include <stdio.h>

int main () {
   char str[80] = "Fre     12/07 19.00     FCM - EFB     1 - 0     7310   ";
   const char s[] = "-' '";
   char *token;
   
   /* get the first token */
   token = strtok(str, s);
   
   /* walk through other tokens */
   while( token != NULL ) {
      printf( " %s\n", token );
    
      token = strtok(NULL, s);
   }
   
   return(0);
}

How to restrict fscanf properly on a string from a txt file?如何在 txt 文件中的字符串上正确限制fscanf (need to read strings and integers separated with white-space AND "-")? (需要读取用空格和“-”分隔的字符串和整数)?

The key part missing in OP's format is the 1st '-' and failure to test the return value. OP 格式中缺少的关键部分是第一个'-'和未能测试返回值。

 // Son     28/07 18.00     BIF - OB      3 - 2     13689  
 // fscanf(file_ptr,    " %s %s %s" " %s  %7s" " %2d %*[-] %2d" " %d", ...
 int cnt = fscanf(file_ptr, "%s%s%s" "%s -%7s" "%2d -%2d" "%d", 
 //                                      ^
 if (cnt == 8) Success();

Also review Why is “while (?feof (file) )” always wrong?另请查看为什么“while (?feof (file))”总是错误的?


Tip: Rather than reading the line of data with fscanf() , use fgets() .提示:不要使用fscanf()读取数据,而是使用fgets()

char buf[100];
if fgets(buf, sizeof buf, file_ptr) == NULL) {

Then parse the line of input with sscanf() , strtol() , etc.然后使用sscanf()strtol()等解析输入


Better to use width limits with "%s"最好将宽度限制与"%s"一起使用

int cnt = fscanf(file_ptr, "%9s%9s%9s" "%9s -%9s" "%2d -%2d" "%d", 

Decide how to 1) handle no more input, 2) errant input.决定如何 1) 不再处理输入,2) 错误输入。


Some untested code that puts together these ideas:一些未经测试的代码将这些想法结合在一起:

It also uses " %n" to detect junk after the good portion of an input line.它还使用" %n"在输入行的大部分之后检测垃圾。

Match* read_match(FILE *file_ptr, Match *input) {
  char buf[100];
  if (fgets(buf, sizeof buf, file_ptr) == NULL) {
    return NULL;
  }
  int n = 0;
  if (sscanf(buf,
      "%9s%9s%9s" "%9s -%9s" "%2d -%2d" "%d" " %n", //
      input->day, input->date, input->time, //
      input->team_A, input->team_B, //
      &input->goals_A, &input->goals_B, //
      &input->spectators, //
      &n) != 8 || buf[n]) {
    fprintf(stderr, "Invalid input \"%s\"\n", buf);
    return NULL;
  }
  return input;
}

int file_read(char *file_input, int n, Match *arr_matches) {
  int r = 0;
  FILE *file_ptr = fopen(file_input, "r");

  if (file_ptr == NULL) {
    printf("Error! Can't open file!");
    return -1;
  }

  int i;
  for (i = 0; i < n; i++) {
    if (read_match(file_ptr, &arr_matches[i]) == NULL) {
      break;
    }
  }
  fclose(file_ptr);
  return i;
}

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

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