diff options
| author | Abigail <abigail@abigail.be> | 2021-03-14 18:35:42 +0100 |
|---|---|---|
| committer | Abigail <abigail@abigail.be> | 2021-03-14 19:59:46 +0100 |
| commit | 5f0e63208b7989972d90eb3c62eabae9577659a1 (patch) | |
| tree | f300fa6dcb771de0320810ad7d12bf8a8d9e7358 | |
| parent | cc9c06d6417c7a55db2a2740f852c9c056f2a77d (diff) | |
| download | perlweeklychallenge-club-5f0e63208b7989972d90eb3c62eabae9577659a1.tar.gz perlweeklychallenge-club-5f0e63208b7989972d90eb3c62eabae9577659a1.tar.bz2 perlweeklychallenge-club-5f0e63208b7989972d90eb3c62eabae9577659a1.zip | |
C solution for week 103, part 2
| -rw-r--r-- | challenge-103/abigail/README.md | 1 | ||||
| -rw-r--r-- | challenge-103/abigail/c/ch-2.c | 142 |
2 files changed, 143 insertions, 0 deletions
diff --git a/challenge-103/abigail/README.md b/challenge-103/abigail/README.md index 4059ddea7e..9d90314025 100644 --- a/challenge-103/abigail/README.md +++ b/challenge-103/abigail/README.md @@ -124,6 +124,7 @@ Output: ### Solutions * [GNU AWK](awk/ch-2.awk) +* [C](c/ch-2.c) * [Lua](lua/ch-2.lua) * [Perl](perl/ch-2.pl) * [Python](python/ch-2.py) diff --git a/challenge-103/abigail/c/ch-2.c b/challenge-103/abigail/c/ch-2.c new file mode 100644 index 0000000000..f776892e0c --- /dev/null +++ b/challenge-103/abigail/c/ch-2.c @@ -0,0 +1,142 @@ +# include <stdlib.h> +# include <stdio.h> +# include <string.h> +# include <unistd.h> + +/* + * See ../README.md + */ + +/* + * Run as: cc -o ch-2.o ch-2.c; ./ch-2.o < input-file + */ + +/* + * Return a malloced string of the given size, or die with + * an error message if it fails. + */ +char * malloc_char (size_t size) { + char * string = (char *) malloc (size * sizeof (char)); + if (string == NULL) { + perror (NULL); + exit (1); + } + return (string); +} + +int main (void) { + char * line = NULL; + size_t len = 0; + size_t str_len; + struct track { + long long run_time; + char * title; + }; + + while ((str_len = getline (&line, &len, stdin)) != -1) { + long long start_time; + long long current_time; + long long time_diff; + char * file_name = malloc_char (str_len); + size_t index; + /* + * Parse input + */ + if (sscanf (line, "%lld %lld %s", + &start_time, ¤t_time, file_name) != 3) { + fprintf (stderr, "Failed to parse input\n"); + exit (1); + } + + /* + * Switch to milliseconds + */ + time_diff = (current_time - start_time) * 1000; + + /* + * Open the file, and count the number of lines. Then seek back. + */ + FILE * media_file = fopen (file_name, "r"); + char ch; + size_t number_of_tracks = 0; + while ((ch = fgetc (media_file)) != EOF) { + if (ch == '\n') { + number_of_tracks ++; + } + } + + if (fseek (media_file, 0, SEEK_SET) == -1) { + perror ("Fseek failed"); + exit (1); + } + + /* + * Allocate memory for the track info. + */ + struct track * tracks = (struct track *) + malloc (number_of_tracks * sizeof (struct track)); + + if (tracks == NULL) { + perror ("Mallocing tracks failed"); + exit (1); + } + + /* + * Read the file, line by line, and store it on tracks. + */ + char * mline = NULL; + size_t mlen = 0; + size_t slen = 0; + size_t i = 0; + long long total_time = 0; + while ((slen = getline (&mline, &mlen, media_file)) != -1) { + long long run_time = atoll (mline); + char * title = malloc_char (slen); + strncpy (title, mline, slen); + while (* title != ',') { + title ++; + } + title ++; + struct track this_track = {run_time, title}; + tracks [i ++] = this_track; + + total_time += run_time; + } + + /* + * Skip complete loops. + */ + time_diff %= total_time; + + /* + * Find the right track. + */ + for (size_t i = 0; i < number_of_tracks; i ++) { + struct track this_track = tracks [i]; + if (time_diff - this_track . run_time < 0) { + printf ("%s", this_track . title); + /* + * C uses integer division, which is quite handy here. + */ + time_diff /= 1000; + int hours = time_diff / 3600; + int minutes = (time_diff % 3600) / 60; + int seconds = time_diff % 60; + if (hours > 0) { + printf ("%02d:%02d:%02d\n", hours, minutes, seconds); + } + else { + printf ( "%02d:%02d\n", minutes, seconds); + } + break; + } + else { + time_diff -= this_track . run_time; + } + } + + } + free (line); + + return (0); +} |
