correction-4-3.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_STR 64
#define MAX_SONGS 64

enum kind_t {
    UNKNOWN, ROCK, POP, JAZZ, HIP_HOP,
    KIND_COUNT
};

const char* kind_texts[] = {
    "Unknown", "Rock", "Pop", "Jazz", "Hip-Hop"
};

struct song_t {
    char path[MAX_STR];
    char title[MAX_STR];
    char artist[MAX_STR];
    char album[MAX_STR];
    int track;
    enum kind_t kind;
};

struct playlist_t {
    int count;
    struct song_t songs[MAX_SONGS];
};

const char* or_unknown(const char* str)
{
    if (str == NULL || str[0] == 0) // La chaine est vide
        return "Unknown";
    return str;
}

void print_song(struct song_t song)
{
    printf("[%s] %s - %s - %s - %d - %s\n",
            or_unknown(song.path),
            or_unknown(song.title),
            or_unknown(song.artist),
            or_unknown(song.album),
            song.track,
            kind_texts[song.kind]); // TODO a function to check bounds
}

// TODO Le bonus pas testé
#define BUFFER_SIZE     100
char* my_gets(int size, char* buffer)
{
    buffer[size - 1] = 0;
    if (fgets(buffer, size - 1, stdin) == NULL)
        return NULL;
    if (strlen(buffer) == size) { // Line is too long
        char trash_buffer[BUFFER_SIZE] = {};
        do {
            fgets(trash_buffer, BUFFER_SIZE, stdin);
        } while (strlen(trash_buffer) == size);
    }
    return buffer;
}

int scan_song(struct song_t* song)
{
    struct song_t s = {};
    char buffer[12];
    if (!gets(s.path) || strlen(s.path) == 0)
        return 0;
    if (!gets(s.title)) {
    } else if (!gets(s.artist)) {
    } else if (!gets(s.album)) {
    } else if (gets(buffer)) {
        int n = atoi(buffer);
        s.track = n;
        if (gets(buffer)) {
            n = atoi(buffer);
            s.kind = n;
        }
    }
    *song = s;
    return 1;
}

/**
 * Version avec pointeur
 */
int song_count(const struct playlist_t* playlist)
{
    return playlist->count;
}

void init_playlist(struct playlist_t* playlist)
{
    playlist->count = 0;
}

int append_song(struct playlist_t* playlist, struct song_t song)
{
    if (song_count(playlist) < MAX_SONGS) {
        playlist->songs[playlist->count++] = song;
        return 1;
    }
    return 0;
}

/**
 * Version sans pointeur ... mais pas forcement plus simple
 */
int song_count_fun(struct playlist_t playlist)
{
    return playlist.count;
}

struct playlist_t init_playlist_fun()
{
    struct playlist_t playlist = {
        .count = 0
    };
    return playlist;
}

struct playlist_t append_song_fun(struct playlist_t playlist, struct song_t song)
{
    playlist.songs[playlist.count++] = song;
    return playlist;
}

/******************************************************************/

void print_playlist(const struct playlist_t* playlist)
{
    int n = song_count(playlist);
    for (int i = 0; i < n; ++i)
        print_song(playlist->songs[i]);
}

/******************************************************************/
struct playlist_t select_kind(const struct playlist_t* playlist, enum kind_t kind)
{
    struct playlist_t result;
    init_playlist(&result);
    int n = song_count(playlist);
    for (int i = 0; i < n; ++i) {
        if (playlist->songs[i].kind == kind)
            append_song(&result, playlist->songs[i]);
    }
    return result;
}

// La version fonctionelle
struct playlist_t select_kind_fun(const struct playlist_t playlist, enum kind_t kind)
{
    struct playlist_t result = init_playlist_fun();
    int n = song_count_fun(playlist);
    for (int i = 0; i < n; ++i) {
        if (playlist.songs[i].kind == kind)
            result = append_song_fun(result, playlist.songs[i]);
    }
    return result;
}

/******************************************************************/

int main(int argc, char* argv[])
{
    struct playlist_t playlist;
    init_playlist(&playlist);

    struct song_t some_song;
    while (scan_song(&some_song)) {
        append_song(&playlist, some_song);
    }
    print_playlist(&playlist);

    struct playlist_t rock = select_kind(&playlist, ROCK);
    print_playlist(&rock);

    return 0;
}