我有一个headers.h
文件,其中有一个这样定义的结构:
#ifndef HEADERS
#define HEADERS
#define FILE_ERR -10
#define OK 0
#define TRUE 0
#define FALSE -1
#define SONGS 4
struct song {
char title[31];
char author[31];
int duration_in_sec;
int reps;
};
int load_music_from_file(char*, struct song*);
int write_music_on_file(char*, struct song*);
#endif
我有一个这样写的输入文件:
we will rock you
queen
2:01
it's my life
bon jovi
3:46
we will rock you
queen
2:01
the show must go on
queen
4:36
我必须读取文件并将其写入输出文件,以秒为单位修改持续时间并在输入文件中添加每首歌曲的重复。这些是我的功能:
#include "headers.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int check_reps(struct song* list, char* title, int n) {
for (int i=0; i<n; i++) {
if (strcmp(list[i].title, title) == 0) {
list[i].reps++;
return TRUE;
}
}
return FALSE;
}
int min_to_sec(int min, int sec) {
return (min * 60) + sec;
}
int load_music_from_file(char* filename, struct song* list) {
FILE* fp = fopen(filename, "r");
if (fp == NULL) return FILE_ERR;
int i = 0;
int min, sec;
char buf_title[31], buf_author[31], buf[6];
while (fgets(buf_title, 31, fp) != NULL && fgets(buf_author, 31, fp) != NULL) {
if (check_reps(list, buf_title, i) == FALSE) {
strncpy(list[i].title, buf_title, 31);
strncpy(list[i].author, buf_author, 31);
if (fgets(buf, 6, fp) != NULL && sscanf(buf, "%d:%d", &min, &sec) == 2) list[i].duration_in_sec = min_to_sec(min, sec);
else return FILE_ERR;
list[i].reps = 1;
printf("%s%s%d\n%d\n\n", list[i].title, list[i].author, list[i].duration_in_sec, list[i].reps);
}
i++;
}
fclose(fp);
return OK;
}
int write_music_on_file(char* filename, struct song* list) {
FILE* fp = fopen(filename, "w");
if (fp == NULL) return FILE_ERR;
for (int i=0; i<SONGS; i++) {
fprintf(fp, "%s%s%d\n%d\n\n", list[i].title, list[i].author, list[i].duration_in_sec, list[i].reps);
}
return OK;
}
这是我的主要功能:
#include "headers.h"
#include <stdio.h>
#include <stdlib.h>
int main() {
struct song* list = (struct song*) malloc(sizeof(struct song) * 4);
char* input = "songs.txt";
printf("loading songs from %s\n", input);
load_music_from_file(input, list);
char* output = "output.txt";
printf("songs written to %s\n\n", output);
write_music_on_file(output, list);
free(list);
return 0;
}
如果我cat output.txt
我看到:
we will rock you
queen
121
2
it's my life
bon jovi
226
1
0
0
2:01
the show must go on
0
0
我认为,load_music_from_file()
函数有一个问题,让我不爽的是,它只适用于循环的一定次数的迭代。
旁注:
- 我正在准备考试,但我不必交这个程序。
- 我知道我还没有检查函数的返回值。
1条答案
按热度按时间hc2pp10m1#
在这个while循环中似乎有两个逻辑错误
第一个是,如果函数
check_reps
返回TRUE
,则记录如下在循环的下一次迭代中被读取为例如标题,因为在if语句中的这些
fgets
调用不要得到控制。
第二个逻辑错误是变量
i
被递增,即使函数check_reps
再次返回TRUE
,尽管在这种情况下结构数组的新元素没有被填充。另外,函数
load_music_from_file
应该以某种方式报告结构数组中实际填充了多少个元素。你应该在函数中动态分配一个结构数组,而不是使用幻数4
。虽然在这种情况下,使用列表而不是数组会更好。注意这些宏定义
是不好的,只会让代码的读者感到困惑,因为通常逻辑值true被定义为非零值,而false被定义为零值。
你可以包含头文件
<stdbool.h>
,并使用定义的宏true
,false
和bool
。