-
第一期:
arr[i].song = (char*)malloc(sizeof(char));
arr[i].artist = (char*)malloc(sizeof(char));
只为 char* 指针、song 和 artist 分配 1 个字节。您可以为此分配大小:
arr[i].song = (char*)malloc(100 * sizeof(char)); /* or malloc(100) */
arr[i].artist = (char*)malloc(100 * sizeof(char));
或者你可以简单地malloc() 足够的缓冲区空间:
char buffer[100];
fgets(buffer, 100, input);
/* check for failure, remove newline */
arr[i].song = malloc(strlen(buffer)+1);
/* check error from malloc */
strcpy(arr[i].song, buffer);
甚至可以使用strdup():
arr[i].song = strdup(buffer);
这是malloc()/strcpy()的替代品。
注意:您也可以阅读Do I cast the result of malloc?。
-
第二期:
您当前的struct:
typedef struct Song {
char *song;
char *artist;
int *year;
} Song;
可以简化为:
typedef struct {
char *song;
char *artist;
int year;
} Song;
因为year 不需要是指针。如果它只是一个int,则更易于管理。这避免了必须进行如下分配:
arr[i].year = (int*)malloc(sizeof(int));
其他建议:
您应该检查fscanf() 和fgets() 的返回,因为这样做是安全的。它有助于防止您的文件包含不正确的数据。 malloc() 也是如此,它可以返回 NULL 在堆上分配不成功。
以下是一些考虑到上述注意事项的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100
typedef struct {
char *song;
char *artist;
int year;
} Song;
Song *create_array(FILE *input, int *nrof);
void load_data(Song *arr, FILE *input, int nrof);
void print_free_data(Song *arr, int nrof);
void get_buffer(char buffer[], FILE *input);
int main(void) {
FILE *input;
Song *arr;
int nrof;
input = fopen("artist.txt", "r");
if (input == NULL) {
fprintf(stderr, "Error reading file\n");
exit(EXIT_FAILURE);
}
arr = create_array(input, &nrof);
load_data(arr, input, nrof);
print_free_data(arr, nrof);
fclose(input);
return 0;
}
Song *create_array(FILE *input, int *nrof) {
Song *arr;
if (fscanf(input, "%d ", nrof) != 1) {
fprintf(stderr, "Cannot find number of songs\n");
exit(EXIT_FAILURE);
}
arr = malloc(*nrof * sizeof(*arr));
if (arr == NULL) {
fprintf(stderr, "Cannot allocate %d spaces for array\n", *nrof);
exit(EXIT_FAILURE);
}
return arr;
}
void load_data(Song *arr, FILE *input, int nrof) {
char buffer[SIZE];
for (int i = 0; i < nrof; i++) {
get_buffer(buffer, input);
arr[i].song = malloc(strlen(buffer)+1);
if (arr[i].song == NULL) {
fprintf(stderr, "Cannot allocate song\n");
exit(EXIT_FAILURE);
}
strcpy(arr[i].song, buffer);
get_buffer(buffer, input);
arr[i].artist = malloc(strlen(buffer)+1);
if (arr[i].artist == NULL) {
fprintf(stderr, "Cannot allocate artist\n");
exit(EXIT_FAILURE);
}
strcpy(arr[i].artist, buffer);
if (fscanf(input, "%d ", &arr[i].year) != 1) {
fprintf(stderr, "Cannot find year for Song: %s Album: %s\n",
arr[i].song, arr[i].artist);
exit(EXIT_FAILURE);
}
}
}
void get_buffer(char buffer[], FILE *input) {
size_t slen;
if (fgets(buffer, SIZE, input) == NULL) {
fprintf(stderr, "Error from fgets(), line not read\n");
exit(EXIT_FAILURE);
}
slen = strlen(buffer);
if (slen > 0 && buffer[slen-1] == '\n') {
buffer[slen-1] = '\0';
} else {
fprintf(stderr, "Too many characters entered\n");
exit(EXIT_FAILURE);
}
}
void print_free_data(Song *arr, int nrof) {
for (int i = 0; i < nrof; i++) {
printf("%s\n%s\n%d\n\n", arr[i].song, arr[i].artist, arr[i].year);
free(arr[i].song);
arr[i].song = NULL;
free(arr[i].artist);
arr[i].artist = NULL;
}
free(arr);
arr = NULL;
}
哪个输出正确的数据:
Mr Tambourine Man
Bob Dylan
1965
Dead Ringer for Love
Meat Loaf
1981
Euphoria
Loreen
2012
Love Me Now
John Legend
2016