私はソングデータベースをコーディングしています。今のところ、2曲のデータは1行に1つの構造体フィールドであるテキストファイルに格納されます。私は、ファイルの内容を行ごとに配列にコピーしたいのですが、load()を呼び出した後にプログラムがクラッシュする理由はありません。 fgets()に関連する問題ですか?または '\ n'を '\ 0'に置き換えるとどうなりますか?ファイルの内容をC言語の配列に1行ずつ読み込みます
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "functions.h"
int main()
{
int menu;
bool exit = false;
/*char title[256];
char artist[256];
char album[256];*/
int year;
Song **songs = NULL; // base pointer to the array (of pointers to struct)
FILE *f; // pointer to a file structure
int n = 0; // height of array at the beginning (= number of pointers to struct)
int i;
f = fopen("database.txt", "r+");
if(f == NULL)
return 0;
count_songs_db(f, &n); // will modify n (height of array) according to the number of existing songs
printf("n = %d\n", n);
songs = (Song**)malloc(n*sizeof(Song));
load(f, songs, n);
// MENU
for(i = 0 ; i < n ; ++i)
free(songs[i]);
free(songs);
fclose(f);
return 0;
}
機能:
void count_songs_db(FILE *f, int *n) // calculate how many songs there are already in the database.
{
int c, n_lines = 0;
while ((c = getc(f)) != EOF)
if (c == '\n')
++n_lines; // count number of lines
*n = n_lines/6; // 1 song = 6 lines. Changes the height of array accordingly.
rewind(f); // go back to beginning of file, to be able to load the db
}
void load(FILE *f, Song **songs, int n) // load existing songs (in the file) into the array
{
int i;
for(i = 0 ; i < n ; ++i)
{
fgets(songs[i]->title, 256, f); // reads a line of text
songs[i]->title[strlen(songs[i]->title)-1] = '\0'; // to replace \n by \0 at the end // not working?
fgets(songs[i]->artist, 256, f);
songs[i]->title[strlen(songs[i]->artist)-1] = '\0';
fgets(songs[i]->album, 256, f);
songs[i]->title[strlen(songs[i]->album)-1] = '\0';
fscanf(f, "%d\n", &(songs[i]->year)); // use it like scanf
fgets(songs[i]->genre, 256, f);
songs[i]->title[strlen(songs[i]->genre)-1] = '\0';
fscanf(f, "%d:%d\n", &(songs[i]->length.m), &(songs[i]->length.s));
}
for(i = 0 ; i < n ; ++i)
{
printf("Title: %s\n", songs[i]->title);
printf("Artist: %s\n", songs[i]->artist);
printf("Album: %s\n", songs[i]->album);
printf("Year of release: %d\n", songs[i]->year);
printf("Genre: %s\n", songs[i]->genre);
printf("Length: %d:%d\n", songs[i]->length.m, songs[i]->length.s);
}
}
構造体:あなたの助けを
typedef struct Length {
int m, s;
} Length;
typedef struct Song {
char title[256];
char artist[256];
char album[256];
int year;
char genre[256];
Length length;
} Song;
おかげでここ は、コードの興味深い部分です。
を編集します。単純な構造体の配列を使用するようにコードを変更しました。ここでadd_song()関数があると、保存()関数:
void add_song(Song *songs, int *n)
{
printf("Title: ");
read(songs[*n].title, MAX_SIZE); // another function is used instead of scanf(), so the user can enter string with spaces. Also more secure.
printf("Artist: ");
read(songs[*n].artist, MAX_SIZE);
printf("Album: ");
read(songs[*n].album, MAX_SIZE);
printf("Year of release: ");
songs[*n].year = read_long(); // still have to check the user inputs (ie. year has to be between 1900 and 2017)
printf("Genre: ");
read(songs[*n].genre, MAX_SIZE);
printf("Length: \nmin: ");
songs[*n].length.m = read_long();
printf("sec: ");
songs[*n].length.s = read_long();
++(*n);
}
void save(FILE *f, Song *songs, int n) // save song in file
{
fprintf(f, "%s\n%s\n%s\n%d\n%s\n%d:%d\n", songs[n-1].title, songs[n-1].artist, songs[n-1].album, songs[n-1].year, songs[n-1].genre, songs[n-1].length.m, songs[n-1].length.s); // use it like printf. Prints the data in the file.
}
'ソング**歌= NULL;'と '曲=(ソング**)はmalloc(n個の*のはsizeof(ソング)); 'マッチしない。 'Song * songs = NULL;'に変更し、 'songs [i] - > title'を' 'song [i] .title'などに変更します。 –
' malloc'の結果をキャストすべきではありませんCでは、正しいポインタ型に安全に昇格され、キャストはコンパイラエラーを隠すことがあります。 –
テキストファイルはasciiエンコーディングで保存して、1つのchar = 1バイトにする必要があります。この行の曲[i] - > title [strlen(songs [i] - > album)-1] = '\ 0'、アーティスト[]、アルバム[]、ジャンル[]に対して同じ操作をするのを忘れてしまった。 –