我有一个txt,里面有一个这样格式的歌曲列表:
我们会震撼你
皇后
两点零一分
我需要把这些数据放在一个名为“elenco”的列表中,并使用这个结构:
struct elenco{
char titolo[30];
char autore[30];
int durata_in_sec;
int rips;
struct elenco *prossima;
};
我试着用fscanf(fp, "%29[^\n]%*c", elenco->autore);
存储数据(以此类推),用简单的printf("%s\n", elenco->autore);
存储输出,但输出是正确的,直到程序输出两行特殊字符,如下所示:
?w
☻ ☻ ☻ ☻ ☻ ☻h☻(☻(☻(☻(☻ ☻ ☻ ☻ ☻y
这是完整的程序,如果你想检查它
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct elenco{
char titolo[30];
char autore[30];
int durata_in_sec;
int rips;
struct elenco *prossima;
};
int main()
{
FILE *fp;
fp = fopen("musica.txt", "r");
int i=0;
int secondi, minuti;
struct elenco *start = NULL;
struct elenco *elenco = NULL;
struct elenco *prec = NULL;
while (!feof(fp))
{
elenco = malloc(sizeof(struct elenco));
fscanf(fp, "%29[^\n]%*c", elenco->titolo);
fscanf(fp, "%29[^\n]%*c", elenco->autore);
fscanf(fp, "%d:%d", &minuti, &secondi);
elenco->durata_in_sec = minuti*60+secondi;
elenco->rips=1;
elenco->prossima = NULL;
if(i==0)
{
start = elenco;
}
else
{
prec->prossima = elenco;
}
prec = elenco;
i++;
}
// Stampa
elenco = start;
while(elenco!=NULL)
{
printf("%s\n", elenco->titolo);
printf("%s\n", elenco->autore);
printf("%d\n", elenco->durata_in_sec);
printf("%d\n", elenco->rips);
elenco = elenco->prossima;
}
fclose(fp);
// Free memory
elenco = start;
while (elenco != NULL) {
struct elenco* temp = elenco;
elenco = elenco->prossima;
free(temp);
}
return 0;
}
这是txt
我们将摇滚你女王2:01这是我的生活邦乔维3:46我们将摇滚你女王2:01表演必须继续女王4:36
1条答案
按热度按时间daolsyd01#
1.使用符号常量而不是幻数。
1.首选初始化变量。
1.删除未使用的变量。
i
仅用于确定是否设置了start
,因此也可以将其删除。1.检查
fopen()
的返回值。1.使用
str()
宏让编译器生成最大字段宽度。1.“%[^\n]”通常比“%[^\n]%*c”更易读。前者忽略前导白色,而后者只忽略一个尾随字符。
while(!feof())
不工作。在这种情况下,您可以通过一个fscanf()
调用读取整个记录。这也为您提供了一个检查无效输入/EOF
的位置。1.检查
malloc()
的返回值。1.当您预分配每条记录时,您需要释放最后一条记录。
1.确保字符串以“\0”结尾。
fclose()
文件,只要你完成。1.最小化变量的作用域。这使你的代码更容易推理。
1.对于迭代,首选
for
-循环。1.考虑将代码分解为更小的函数(
elenco_load()
,elenco_print()
,elenco_free()
)。它使推理和测试更容易。1.(不固定)考虑使用更具体的类型。是否要允许负
durata_in_sec
?你希望持续时间为INT_MAX
还是更小的类型?secondi < 0 || secondi >= 60
是否为有效输入(unsigned char
)?1.(不固定)当您硬编码
rips=1
时,请考虑将其从struct elenco
中删除,以支持符号常量#define RIPS 1
。打印时,您现在只需执行`print(“%d\n”,RIPS)。示例运行: