Reputation: 37
so i have this program which asks the user to provide as input from the command line an artist name. At most 4 artists can be provided as input. For each artist, at least 1 and at most 3 songs could be provided. the issue i have is when i print the artists and playlist out, i keep getting some random symbols as output and no words. im not sure whats the mistake here. can someone help or direct me in some direction? (i know the program isnt done, i just wanted to get this working first)
#include <stdio.h>
#include <string.h>
#include "sortAndShuffle.h"
int main(void)
{
//The array containing artists names
char artists[4][80];
//The array containing the sorted artists
char sortedArtists[4][80];
//Songs for Artist 1
char songsArtist1[3][80];
//Songs for Artist 2
char songsArtist2[3][80];
//Songs for Artist 3
char songsArtist3[3][80];
//Songs for Artist 4
char songsArtist4[3][80];
//The total number of artists (Note it can be less than 4)
int numOfArtists =0;
//The total number of songs for each artist (Note that less than 3 songs can
be provided for each artist)
int numSongsPerArtist[4];
int i,j;
/*
* Use here functions that you should implement to insert artists and songs
from the standard input.
* Note that you also need to track the number of artists and the number of
songs for each artist.
*/
for(i=1; i<=1; i++) {
printf("Insert artist/group name");
fgets(artists[i], 80, stdin);
for(j=1; j<=3; j++) {
if(i==1) {
printf("Insert song %d for %s",j,artists[i]);
fgets(songsArtist1,80,stdin);
}
if(i==2) {
printf("Insert song %d for %s",j,artists[i]);
fgets(songsArtist2,80,stdin);
}
if(i==3) {
printf("Insert song %d for %s",j,artists[i]);
fgets(songsArtist3,80,stdin);
}
if(i==4) {
printf("Insert song %d for %s",j,artists[i]);
fgets(songsArtist4,80,stdin);
}
}
if(artists[i][0] !=' ' && artists[i][1] !=' ') {
numOfArtists
}
}
for(i=1; i<=4; i++) {
printf("%s\n", artists[i]);
for(j=1; j <=3; j++) {
if(i==1) {
printf("%s",songsArtist1[j]);
}
if(i==2) {
printf("%s",songsArtist2[j]);
}
if(i==3) {
printf("%s",songsArtist3[j]);
}
if(i==4) {
printf("%s",songsArtist4[j]);
}
}
}
/*
* Use here the function sortArtists to sort the array of the artists and sortSongs to sort the songs of each artist
* Print each artist (alphabetically) and for each of them print the list of songs sorted alphabetically
*/
/*
* Use here the function shuffleSongs to shuffle all the songs
* Print the list of shuffled songs
*/
return 0;
}
Upvotes: 0
Views: 96
Reputation: 84579
Damien, if you are still stuck on your problem reading the artist/group and songs, the two biggest parts of your problem (other than your zero indexing misunderstanding) are handling the input you take from the user, properly trimming the '\n'
characters included by fgets
, and then properly coordinating the relationship between the artist/group and songs. Your problems have little or nothing to do with Printing a 2D Array.
C provides a struct
that is tailor made to allow you to coordinate related information of differing types. This is what you are attempting to accomplish. When you individually declare array1, array2, etc.. to hold artist/group and then independently declare arraysong1, arraysong2, etc.. there is no relationship between the artist/group and the songs other than the array names (which is no way to manage the relationship). Instead, you could declare a struct to provide that relationship (and the constants to prevent magic numbers in your code), e.g.
#define NSONGS 3
#define NARTISTS 4
#define MAXC 80
typedef struct {
char name[MAXC], /* storage for name/group */
songs[NSONGS][MAXC]; /* storage for songs */
int nsaved; /* number songs currently saved */
} artists;
Now you simply declare an array of artists
(initialized to all zero), e.g.
artists a[NARTISTS] = {{ .name = "" }};
and you have an array of structs you can fill with artist/group and up to NSONGS
songs each while preserving the proper relationship as to which artist/group sings what songs.
Now for what goes in the artist/group name and what goes into songs, you have done a good job by choosing fgets
for user input. That avoids many of the pitfalls associated with taking input with scanf
. However, there are a couple additional steps you must take to prevent storing the trailing '\n'
that fgets
(and POSIX getline
) includes in the buffer it fills. It is a simple process of getting the length of the string stored by fgets
and then checking and overwriting the '\n'
at the end of the buffer with a nul-terminating character (e.g. 0
or '\0'
)
Putting those pieces together, you could read your data into an array of stuct and then write a simple print function (or functions) to output your data (I used 4-songs per artist in the example below). You will then simply need to write a compare function for qsort
to handle the sorting of your artists and song (there are plenty of examples on this site -- that is left for you)
A short example would be:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NSONGS 4
#define NARTISTS NSONGS
#define MAXC 80
typedef struct {
char name[MAXC], /* storage for name/group */
songs[NSONGS][MAXC]; /* storage for songs */
int nsaved; /* number songs currently saved */
} artists;
void prnsongs (artists *a);
void prncollection (artists *a, int n);
int main (void) {
int n = 0; /* counter for artists */
char buf[MAXC] = ""; /* buffer for input */
/* array of struct initialized all zero */
artists a[NARTISTS] = {{ .name = "" }};
while (n < NARTISTS) { /* loop until we fill all artists */
size_t len = 0; /* length of input to allow '\n' trim */
printf ("\nenter artists/group name: "); /* prompt */
fflush (stdout); /* precaution to insure prompt displayed */
if (!fgets (buf, MAXC, stdin)) { /* read artist/group name */
fprintf (stderr, "user canceled input - artists.\n");
break;
}
len = strlen (buf); /* get length of artist/group */
if (len && buf[len - 1] == '\n') /* check last char '\n' */
buf[--len] = 0; /* overwrite with nul-terminating char */
else if (len == MAXC - 1) { /* otherwise name too long - bail */
fprintf (stderr, "error: name exceeds %d chars.\n", MAXC);
exit (EXIT_FAILURE);
}
strcpy (a[n].name, buf); /* copy buf to artist.name */
while (a[n].nsaved < NSONGS) { /* loop until songs filled */
printf (" %s - song[%d]: ", a[n].name, a[n].nsaved + 1);
if (!fgets (buf, MAXC, stdin)) {
fprintf (stderr, "user canceled input - songs.\n");
break;
}
len = strlen (buf); /* same length & trim for each song */
if (len && buf[len - 1] == '\n')
buf[--len] = 0;
else if (len == MAXC - 1) {
fprintf (stderr, "error: name exceeds %d chars.\n", MAXC);
exit (EXIT_FAILURE);
} /* copy song to a[n].songs[x], increment .nsaved */
strcpy (a[n].songs[a[n].nsaved++], buf);
}
n++; /* increment artist index */
}
printf ("\n=== Stored Collection of Artists & Songs ===\n");
prncollection (a, n); /* print all artists and songs */
return 0;
}
/* simple function to print songs for artist */
void prnsongs (artists *a)
{
int i;
for (i = 0; i < a->nsaved; i++)
printf (" song[%d] - %s\n", i + 1, a->songs[i]);
}
/* simple function to print artists & songs */
void prncollection (artists *a, int n)
{
int i;
for (i = 0; i < n; i++) {
printf ("\nartist/group: %s\n", a[i].name);
prnsongs (&a[i]); /* & - to pass pointer to struct */
}
}
(note the print function was written in two logical pieces and you could have passed the structure to prnsongs
itself, but passing a pointer is a bit more efficient)
Example Use/Output
$ ./bin/artist_songs
enter artists/group name: elvis
elvis - song[1]: bs shoes
elvis - song[2]: hh burning love
elvis - song[3]: hound dog
elvis - song[4]: lm tender
enter artists/group name: nirvana
nirvana - song[1]: hs box
nirvana - song[2]: bloom
nirvana - song[3]: dumb
nirvana - song[4]: as you are
enter artists/group name: peal jam
peal jam - song[1]: alive
peal jam - song[2]: daughter
peal jam - song[3]: animal
peal jam - song[4]: jeremy
enter artists/group name: buffet
buffet - song[1]: changes in lattitude
buffet - song[2]: fins
buffet - song[3]: margaritaville
buffet - song[4]: went to paris
=== Stored Collection of Artists & Songs ===
artist/group: elvis
song[1] - bs shoes
song[2] - hh burning love
song[3] - hound dog
song[4] - lm tender
artist/group: nirvana
song[1] - hs box
song[2] - bloom
song[3] - dumb
song[4] - as you are
artist/group: peal jam
song[1] - alive
song[2] - daughter
song[3] - animal
song[4] - jeremy
artist/group: buffet
song[1] - changes in lattitude
song[2] - fins
song[3] - margaritaville
song[4] - went to paris
So the bulk of your problem had nothing to do with printing 2D arrays, your problem was basic data handling and handling the user input provided by fgets
. Look things over and let me know if you have further questions (and try to use a more descriptive and accurate title for your question next time)
Upvotes: 2