使用带有 fscanf() 的 strtok() 标记进行日期分配
using a strtok() token with fscanf() to do a date assignment
我有一个名为 TEAM 的结构,其中包含有关足球队的一些信息。
typedef struct team{
int ID; //1
char Team_name[MAX_LEN]; //2
int Status; //3
int Points; //4
int Score; //5
int Goals; //6
struct tm Date; //7
struct team *next;
}TEAM;
我正在创建团队链接列表,团队信息是从文件中读取的,格式如下:
ID;teamname;status;points;score;goals;day/month/year hour:minute
我从文件中获取数据并完成所需的作业没有问题。但是我对日期部分有疑问。
我使用 strtok() 将一行拆分为标记,并尝试使用以下代码将标记的各个部分分配给它们各自的变量。
fscanf(token, "%d/%d/%d %d:%d", &tmp->Date.tm_mday, &tmp->Date.tm_mon, &tmp->Date.tm_year, &tmp->Date.tm_hour, &tmp->Date.tm_min);
但这给出了这个 return 值
-1073741819 (0xC0000005)
据我所知,这被称为非法内存访问,我用“&”符号或 fscanf() 所做的事情是错误的。
我的代码在没有 fscanf() 的情况下工作正常所以我做错了什么?
编辑:整个代码:
typedef struct team{
int ID; //1
char Team_name[MAX_LEN]; //2
int Status; //3
int Points; //4
int Score; //5
int Goals; //6
struct tm Date; //7
struct team *next;
}TEAM;
TEAM *createNode(void){
TEAM *node;
node = (TEAM *)malloc(sizeof(TEAM));
node->next = NULL;
return node;
}
TEAM *initialiseTeams(void){
FILE *fp;
TEAM *head;
TEAM *tmp;
char line[BUFFER];
char *token;
const char delim[2] = ";";
fp = fopen("Teams.txt","r");
if(fp == NULL){
printf("Failed to open Teams.txt\n");
exit(EXIT_FAILURE);
}
head = createNode();
tmp = head;
while(fgets(line, BUFFER, fp)){
int i;
for(i = 0, token = strtok(line, delim); token != NULL; i++, token = strtok(NULL, delim)){
printf("%s\n", token);
switch(i){
case 0: // ID
tmp->ID = atoi(token);
break;
case 1: // Team name
strcpy(tmp->Team_name, token);
break;
case 2: // Status
if(strcmp(token, "L") == 0){
tmp->Status = 0;
}
if(strcmp(token, "W") == 0){
tmp->Status = 1;
}
if(strcmp(token, "D") == 0){
tmp->Status = 2;
}
break;
case 3: // Points
tmp->Points = atoi(token);
break;
case 4: // Score
tmp->Score = atoi(token);
break;
case 5: // Goals
tmp->Goals = atoi(token);
break;
case 6: // Date
fscanf(token, "%d/%d/%d %d:%d", &tmp->Date.tm_mday, &tmp->Date.tm_mon, &tmp->Date.tm_year, &tmp->Date.tm_hour, &tmp->Date.tm_min);
break;
}
}
tmp->next = createNode();
tmp = tmp->next;
}
free(tmp);
return head;
}
int main(void){
TEAM *head;
head = initialiseTeams();
}
fscanf
将 FILE *
作为其第一个参数,但您将代码描述为通过 token
以某种方式来自 strtok 。你没有说 token
是什么,但是没有办法从 strtok 得到一个 FILE *
,所以它可能不是那个。
也许你想打电话给 sscanf
?
您创建列表的过程过于复杂。这部分是由于试图将所有 I/O 和列表操作卸载到 initialiseTeams()
。通常,您希望将列表操作与程序界面(I/O、它与用户的交互方式等)分开。这样,无论您需要从何处添加节点(文件、用户-输入等),您只需调用 add()
(或 push()
)函数即可将新节点添加到您的列表中。
你把 createnode()
函数分离得很好。您可以通过将指向 TEAM
结构的指针作为参数传递来进一步利用它,该结构可用于在 createnode()
函数中初始化新节点。例如:
TEAM *createNode (TEAM *t)
{
TEAM *node = malloc (sizeof *node); /* allocate */
if (!node) { /* validate */
perror ("malloc-node");
return NULL;
}
if (t) /* assign struct (if not NULL) */
*node = *t;
node->next = NULL;
return node;
}
只需很少的额外努力。在验证要添加的数据之前没有理由调用 createnode()
函数,因此传递 TEAM*
指针允许您处理函数中的所有创建和初始化。
您的 initialiseTeams()
应该将打开的 FILE*
流作为参数读取。如果文件无法打开并在调用者中返回验证——则无需首先调用 initialiseTeams()
函数。
您可以像阅读一样用fgets()
阅读,但不需要用strtok()
标记行。一个简单的精心制作的 sscanf()
格式字符串就可以了。这极大地简化了您的功能,将实现减少到:
/* read all records from fp, return pointer to beginning of list */
TEAM *initialiseTeams (FILE *fp)
{
char line[BUFFER];
TEAM *head = NULL, /* using both head & tail pointer allows O(1) in-order */
*tail = NULL; /* insertions to the list. */
while (fgets (line, BUFFER, fp)) { /* read each line */
TEAM tmp = { .ID = 0 }; /* temporary struct */
/* parse values with sscanf() validating return */
if (sscanf (line, "%d; %127[^;]; %d; %d; %d; %d; %d/%d/%d %d:%d",
&tmp.ID, tmp.Team_name, &tmp.Status, &tmp.Points,
&tmp.Score, &tmp.Goals, &tmp.Date.tm_mday, &tmp.Date.tm_mon,
&tmp.Date.tm_year, &tmp.Date.tm_hour, &tmp.Date.tm_min) == 11) {
TEAM *node; /* node to allocate */
if (!(node = createNode (&tmp))) /* create node passing tmp struct */
break;
tmp.Date.tm_year -= 1900; /* subtract 1900 from year */
*node = tmp; /* assign tmp to allocated node */
if (!head) /* if head NULL, add 1st node */
head = tail = node;
else {
tail->next = node; /* add all subsequent nodes in-order */
tail = node;
}
}
}
return head; /* return pointer to beginning of list */
}
(注意: 您需要将 "%127[^;]"
中的 field-width 修饰符调整为 MAX_LEN - 1
)
切勿对文件名进行硬编码或在代码中使用 MagicNumbers。您不必为了读取不同的文件名而重新编译您的程序。要么将文件名的名称作为参数提供给您的程序(这就是 int argc, char **argv
在 int main (int argc, char **argv)
中的作用,要么提示用户输入文件名。因为您显示 MAX_LEN
和 BUFFER
,这些显然在其他地方被声明为常量——这很好。
将要读取的文件名作为程序的第一个参数,或者如果没有提供参数则默认从 stdin
读取,读取数据文件的程序可能类似于:
int main (int argc, char **argv) {
TEAM *head = NULL; /* initialize pointers NULL */
/*
* keep interface separate from implementation.
* open file/validate and pass open FILE* to initialiseTeams()
* use filename provided as 1st argument (stdin by default)
*/
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
head = initialiseTeams (fp); /* read all records in file into list */
if (fp != stdin) /* close file if not stdin */
fclose (fp);
prn_list (head); /* print list */
del_list (head); /* free all nodes */
}
把它放在一起,快速编写 prn_list()
和 del_list()
函数来输出列表,然后在完成后删除列表中的所有节点,你可以这样做:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_LEN 128
#define BUFFER 1024
typedef struct team {
int ID;
char Team_name[MAX_LEN];
int Status;
int Points;
int Score;
int Goals;
struct tm Date;
struct team *next;
} TEAM;
TEAM *createNode (TEAM *t)
{
TEAM *node = malloc (sizeof *node); /* allocate */
if (!node) { /* validate */
perror ("malloc-node");
return NULL;
}
if (t) /* assign struct (if not NULL) */
*node = *t;
node->next = NULL;
return node;
}
/* read all records from fp, return pointer to beginning of list */
TEAM *initialiseTeams (FILE *fp)
{
char line[BUFFER];
TEAM *head = NULL, /* using both head & tail pointer allows O(1) in-order */
*tail = NULL; /* insertions to the list. */
while (fgets (line, BUFFER, fp)) { /* read each line */
TEAM tmp = { .ID = 0 }; /* temporary struct */
/* parse values with sscanf() validating return */
if (sscanf (line, "%d; %127[^;]; %d; %d; %d; %d; %d/%d/%d %d:%d",
&tmp.ID, tmp.Team_name, &tmp.Status, &tmp.Points,
&tmp.Score, &tmp.Goals, &tmp.Date.tm_mday, &tmp.Date.tm_mon,
&tmp.Date.tm_year, &tmp.Date.tm_hour, &tmp.Date.tm_min) == 11) {
TEAM *node; /* node to allocate */
if (!(node = createNode (&tmp))) /* create node passing tmp struct */
break;
tmp.Date.tm_year -= 1900; /* subtract 1900 from year */
*node = tmp; /* assign tmp to allocated node */
if (!head) /* if head NULL, add 1st node */
head = tail = node;
else {
tail->next = node; /* add all subsequent nodes in-order */
tail = node;
}
}
}
return head; /* return pointer to beginning of list */
}
/* simple print function */
void prn_list (TEAM *list)
{
if (!list) {
puts ("(list empty)");
return;
}
for (TEAM *iter = list; iter; iter = iter->next)
printf ("%4d %s\n"
" Status: %d\n"
" Points: %d\n"
" Score : %d\n"
" Goals : %d\n"
" Date : %d/%d/%d %d:%d\n\n",
iter->ID, iter->Team_name, iter->Status, iter->Points, iter->Score,
iter->Goals, iter->Date.tm_mday, iter->Date.tm_mon,
iter->Date.tm_year + 1900, iter->Date.tm_hour, iter->Date.tm_min);
}
/* function to delete all nodes in list */
void del_list (TEAM *list)
{
while (list) {
TEAM *victim = list;
list = list->next;
free (victim);
}
}
int main (int argc, char **argv) {
TEAM *head = NULL; /* initialize pointers NULL */
/*
* keep interface separate from implementation.
* open file/validate and pass open FILE* to initialiseTeams()
* use filename provided as 1st argument (stdin by default)
*/
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
head = initialiseTeams (fp); /* read all records in file into list */
if (fp != stdin) /* close file if not stdin */
fclose (fp);
prn_list (head); /* print list */
del_list (head); /* free all nodes */
}
正在使用符合以下格式的生成数据文件测试代码:
ID;teamname;status;points;score;goals;day/month/year hour:minute
示例输入文件
例如:
$ cat dat/soccerteams.txt
42;Team42;3;0;0;2;9/2/2020 1:5
97;Team97;6;42;2;2;18/3/2020 2:11
54;Team54;2;35;0;4;9/4/2020 3:17
49;Team49;10;0;2;4;18/5/2020 4:23
46;Team46;7;28;8;1;18/6/2020 5:29
98;Team98;7;0;4;3;27/1/2020 6:35
15;Team15;2;7;6;0;9/2/2020 7:41
8;Team8;8;7;4;3;27/3/2020 8:47
4;Team4;4;28;8;4;18/4/2020 9:53
51;Team51;12;14;6;1;9/5/2020 10:59
例子Use/Output
按如下方式调用程序会产生所示输出:
$ ./bin/ll_soccer dat/soccerteams.txt
42 Team42
Status: 3
Points: 0
Score : 0
Goals : 2
Date : 9/2/2020 1:5
97 Team97
Status: 6
Points: 42
Score : 2
Goals : 2
Date : 18/3/2020 2:11
54 Team54
Status: 2
Points: 35
Score : 0
Goals : 4
Date : 9/4/2020 3:17
49 Team49
Status: 10
Points: 0
Score : 2
Goals : 4
Date : 18/5/2020 4:23
46 Team46
Status: 7
Points: 28
Score : 8
Goals : 1
Date : 18/6/2020 5:29
98 Team98
Status: 7
Points: 0
Score : 4
Goals : 3
Date : 27/1/2020 6:35
15 Team15
Status: 2
Points: 7
Score : 6
Goals : 0
Date : 9/2/2020 7:41
8 Team8
Status: 8
Points: 7
Score : 4
Goals : 3
Date : 27/3/2020 8:47
4 Team4
Status: 4
Points: 28
Score : 8
Goals : 4
Date : 18/4/2020 9:53
51 Team51
Status: 12
Points: 14
Score : 6
Goals : 1
Date : 9/5/2020 10:59
当您将列表操作与程序的其余部分分开时,它会使测试每个单独的组件变得更加容易,并使您的列表代码可重用。如果你把所有东西都放在几个大函数中——那么你最终将不得不在未来为每个列表重写它们。保持函数小且易于测试。
检查一下,如果您还有其他问题,请告诉我。
我有一个名为 TEAM 的结构,其中包含有关足球队的一些信息。
typedef struct team{
int ID; //1
char Team_name[MAX_LEN]; //2
int Status; //3
int Points; //4
int Score; //5
int Goals; //6
struct tm Date; //7
struct team *next;
}TEAM;
我正在创建团队链接列表,团队信息是从文件中读取的,格式如下:
ID;teamname;status;points;score;goals;day/month/year hour:minute
我从文件中获取数据并完成所需的作业没有问题。但是我对日期部分有疑问。
我使用 strtok() 将一行拆分为标记,并尝试使用以下代码将标记的各个部分分配给它们各自的变量。
fscanf(token, "%d/%d/%d %d:%d", &tmp->Date.tm_mday, &tmp->Date.tm_mon, &tmp->Date.tm_year, &tmp->Date.tm_hour, &tmp->Date.tm_min);
但这给出了这个 return 值 -1073741819 (0xC0000005) 据我所知,这被称为非法内存访问,我用“&”符号或 fscanf() 所做的事情是错误的。
我的代码在没有 fscanf() 的情况下工作正常所以我做错了什么?
编辑:整个代码:
typedef struct team{
int ID; //1
char Team_name[MAX_LEN]; //2
int Status; //3
int Points; //4
int Score; //5
int Goals; //6
struct tm Date; //7
struct team *next;
}TEAM;
TEAM *createNode(void){
TEAM *node;
node = (TEAM *)malloc(sizeof(TEAM));
node->next = NULL;
return node;
}
TEAM *initialiseTeams(void){
FILE *fp;
TEAM *head;
TEAM *tmp;
char line[BUFFER];
char *token;
const char delim[2] = ";";
fp = fopen("Teams.txt","r");
if(fp == NULL){
printf("Failed to open Teams.txt\n");
exit(EXIT_FAILURE);
}
head = createNode();
tmp = head;
while(fgets(line, BUFFER, fp)){
int i;
for(i = 0, token = strtok(line, delim); token != NULL; i++, token = strtok(NULL, delim)){
printf("%s\n", token);
switch(i){
case 0: // ID
tmp->ID = atoi(token);
break;
case 1: // Team name
strcpy(tmp->Team_name, token);
break;
case 2: // Status
if(strcmp(token, "L") == 0){
tmp->Status = 0;
}
if(strcmp(token, "W") == 0){
tmp->Status = 1;
}
if(strcmp(token, "D") == 0){
tmp->Status = 2;
}
break;
case 3: // Points
tmp->Points = atoi(token);
break;
case 4: // Score
tmp->Score = atoi(token);
break;
case 5: // Goals
tmp->Goals = atoi(token);
break;
case 6: // Date
fscanf(token, "%d/%d/%d %d:%d", &tmp->Date.tm_mday, &tmp->Date.tm_mon, &tmp->Date.tm_year, &tmp->Date.tm_hour, &tmp->Date.tm_min);
break;
}
}
tmp->next = createNode();
tmp = tmp->next;
}
free(tmp);
return head;
}
int main(void){
TEAM *head;
head = initialiseTeams();
}
fscanf
将 FILE *
作为其第一个参数,但您将代码描述为通过 token
以某种方式来自 strtok 。你没有说 token
是什么,但是没有办法从 strtok 得到一个 FILE *
,所以它可能不是那个。
也许你想打电话给 sscanf
?
您创建列表的过程过于复杂。这部分是由于试图将所有 I/O 和列表操作卸载到 initialiseTeams()
。通常,您希望将列表操作与程序界面(I/O、它与用户的交互方式等)分开。这样,无论您需要从何处添加节点(文件、用户-输入等),您只需调用 add()
(或 push()
)函数即可将新节点添加到您的列表中。
你把 createnode()
函数分离得很好。您可以通过将指向 TEAM
结构的指针作为参数传递来进一步利用它,该结构可用于在 createnode()
函数中初始化新节点。例如:
TEAM *createNode (TEAM *t)
{
TEAM *node = malloc (sizeof *node); /* allocate */
if (!node) { /* validate */
perror ("malloc-node");
return NULL;
}
if (t) /* assign struct (if not NULL) */
*node = *t;
node->next = NULL;
return node;
}
只需很少的额外努力。在验证要添加的数据之前没有理由调用 createnode()
函数,因此传递 TEAM*
指针允许您处理函数中的所有创建和初始化。
您的 initialiseTeams()
应该将打开的 FILE*
流作为参数读取。如果文件无法打开并在调用者中返回验证——则无需首先调用 initialiseTeams()
函数。
您可以像阅读一样用fgets()
阅读,但不需要用strtok()
标记行。一个简单的精心制作的 sscanf()
格式字符串就可以了。这极大地简化了您的功能,将实现减少到:
/* read all records from fp, return pointer to beginning of list */
TEAM *initialiseTeams (FILE *fp)
{
char line[BUFFER];
TEAM *head = NULL, /* using both head & tail pointer allows O(1) in-order */
*tail = NULL; /* insertions to the list. */
while (fgets (line, BUFFER, fp)) { /* read each line */
TEAM tmp = { .ID = 0 }; /* temporary struct */
/* parse values with sscanf() validating return */
if (sscanf (line, "%d; %127[^;]; %d; %d; %d; %d; %d/%d/%d %d:%d",
&tmp.ID, tmp.Team_name, &tmp.Status, &tmp.Points,
&tmp.Score, &tmp.Goals, &tmp.Date.tm_mday, &tmp.Date.tm_mon,
&tmp.Date.tm_year, &tmp.Date.tm_hour, &tmp.Date.tm_min) == 11) {
TEAM *node; /* node to allocate */
if (!(node = createNode (&tmp))) /* create node passing tmp struct */
break;
tmp.Date.tm_year -= 1900; /* subtract 1900 from year */
*node = tmp; /* assign tmp to allocated node */
if (!head) /* if head NULL, add 1st node */
head = tail = node;
else {
tail->next = node; /* add all subsequent nodes in-order */
tail = node;
}
}
}
return head; /* return pointer to beginning of list */
}
(注意: 您需要将 "%127[^;]"
中的 field-width 修饰符调整为 MAX_LEN - 1
)
切勿对文件名进行硬编码或在代码中使用 MagicNumbers。您不必为了读取不同的文件名而重新编译您的程序。要么将文件名的名称作为参数提供给您的程序(这就是 int argc, char **argv
在 int main (int argc, char **argv)
中的作用,要么提示用户输入文件名。因为您显示 MAX_LEN
和 BUFFER
,这些显然在其他地方被声明为常量——这很好。
将要读取的文件名作为程序的第一个参数,或者如果没有提供参数则默认从 stdin
读取,读取数据文件的程序可能类似于:
int main (int argc, char **argv) {
TEAM *head = NULL; /* initialize pointers NULL */
/*
* keep interface separate from implementation.
* open file/validate and pass open FILE* to initialiseTeams()
* use filename provided as 1st argument (stdin by default)
*/
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
head = initialiseTeams (fp); /* read all records in file into list */
if (fp != stdin) /* close file if not stdin */
fclose (fp);
prn_list (head); /* print list */
del_list (head); /* free all nodes */
}
把它放在一起,快速编写 prn_list()
和 del_list()
函数来输出列表,然后在完成后删除列表中的所有节点,你可以这样做:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_LEN 128
#define BUFFER 1024
typedef struct team {
int ID;
char Team_name[MAX_LEN];
int Status;
int Points;
int Score;
int Goals;
struct tm Date;
struct team *next;
} TEAM;
TEAM *createNode (TEAM *t)
{
TEAM *node = malloc (sizeof *node); /* allocate */
if (!node) { /* validate */
perror ("malloc-node");
return NULL;
}
if (t) /* assign struct (if not NULL) */
*node = *t;
node->next = NULL;
return node;
}
/* read all records from fp, return pointer to beginning of list */
TEAM *initialiseTeams (FILE *fp)
{
char line[BUFFER];
TEAM *head = NULL, /* using both head & tail pointer allows O(1) in-order */
*tail = NULL; /* insertions to the list. */
while (fgets (line, BUFFER, fp)) { /* read each line */
TEAM tmp = { .ID = 0 }; /* temporary struct */
/* parse values with sscanf() validating return */
if (sscanf (line, "%d; %127[^;]; %d; %d; %d; %d; %d/%d/%d %d:%d",
&tmp.ID, tmp.Team_name, &tmp.Status, &tmp.Points,
&tmp.Score, &tmp.Goals, &tmp.Date.tm_mday, &tmp.Date.tm_mon,
&tmp.Date.tm_year, &tmp.Date.tm_hour, &tmp.Date.tm_min) == 11) {
TEAM *node; /* node to allocate */
if (!(node = createNode (&tmp))) /* create node passing tmp struct */
break;
tmp.Date.tm_year -= 1900; /* subtract 1900 from year */
*node = tmp; /* assign tmp to allocated node */
if (!head) /* if head NULL, add 1st node */
head = tail = node;
else {
tail->next = node; /* add all subsequent nodes in-order */
tail = node;
}
}
}
return head; /* return pointer to beginning of list */
}
/* simple print function */
void prn_list (TEAM *list)
{
if (!list) {
puts ("(list empty)");
return;
}
for (TEAM *iter = list; iter; iter = iter->next)
printf ("%4d %s\n"
" Status: %d\n"
" Points: %d\n"
" Score : %d\n"
" Goals : %d\n"
" Date : %d/%d/%d %d:%d\n\n",
iter->ID, iter->Team_name, iter->Status, iter->Points, iter->Score,
iter->Goals, iter->Date.tm_mday, iter->Date.tm_mon,
iter->Date.tm_year + 1900, iter->Date.tm_hour, iter->Date.tm_min);
}
/* function to delete all nodes in list */
void del_list (TEAM *list)
{
while (list) {
TEAM *victim = list;
list = list->next;
free (victim);
}
}
int main (int argc, char **argv) {
TEAM *head = NULL; /* initialize pointers NULL */
/*
* keep interface separate from implementation.
* open file/validate and pass open FILE* to initialiseTeams()
* use filename provided as 1st argument (stdin by default)
*/
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
head = initialiseTeams (fp); /* read all records in file into list */
if (fp != stdin) /* close file if not stdin */
fclose (fp);
prn_list (head); /* print list */
del_list (head); /* free all nodes */
}
正在使用符合以下格式的生成数据文件测试代码:
ID;teamname;status;points;score;goals;day/month/year hour:minute
示例输入文件
例如:
$ cat dat/soccerteams.txt
42;Team42;3;0;0;2;9/2/2020 1:5
97;Team97;6;42;2;2;18/3/2020 2:11
54;Team54;2;35;0;4;9/4/2020 3:17
49;Team49;10;0;2;4;18/5/2020 4:23
46;Team46;7;28;8;1;18/6/2020 5:29
98;Team98;7;0;4;3;27/1/2020 6:35
15;Team15;2;7;6;0;9/2/2020 7:41
8;Team8;8;7;4;3;27/3/2020 8:47
4;Team4;4;28;8;4;18/4/2020 9:53
51;Team51;12;14;6;1;9/5/2020 10:59
例子Use/Output
按如下方式调用程序会产生所示输出:
$ ./bin/ll_soccer dat/soccerteams.txt
42 Team42
Status: 3
Points: 0
Score : 0
Goals : 2
Date : 9/2/2020 1:5
97 Team97
Status: 6
Points: 42
Score : 2
Goals : 2
Date : 18/3/2020 2:11
54 Team54
Status: 2
Points: 35
Score : 0
Goals : 4
Date : 9/4/2020 3:17
49 Team49
Status: 10
Points: 0
Score : 2
Goals : 4
Date : 18/5/2020 4:23
46 Team46
Status: 7
Points: 28
Score : 8
Goals : 1
Date : 18/6/2020 5:29
98 Team98
Status: 7
Points: 0
Score : 4
Goals : 3
Date : 27/1/2020 6:35
15 Team15
Status: 2
Points: 7
Score : 6
Goals : 0
Date : 9/2/2020 7:41
8 Team8
Status: 8
Points: 7
Score : 4
Goals : 3
Date : 27/3/2020 8:47
4 Team4
Status: 4
Points: 28
Score : 8
Goals : 4
Date : 18/4/2020 9:53
51 Team51
Status: 12
Points: 14
Score : 6
Goals : 1
Date : 9/5/2020 10:59
当您将列表操作与程序的其余部分分开时,它会使测试每个单独的组件变得更加容易,并使您的列表代码可重用。如果你把所有东西都放在几个大函数中——那么你最终将不得不在未来为每个列表重写它们。保持函数小且易于测试。
检查一下,如果您还有其他问题,请告诉我。