In this assignment you will complete the Digital Music Manager that you started
ID: 3863314 • Letter: I
Question
In this assignment you will complete the Digital Music Manager that you started in PA 2. You must implement the following features:
What must “insert” do?
The “insert” command must prompt the user for the details of a new record. The prompt must request the artist name, album title, song title, genre, song length, number of times played, and rating. The new record must be inserted at the front of the list.
What must “delete” do?
The “delete” command must prompt the user for a song title, and remove the matching record from the list. If the song title does not exist, then the list remains unchanged.
What must “sort” do?
The “sort” command must prompt the user for 4 different methods to sort the records in the list. These include:
Sort based on artist (A-Z)
Sort based on album title (A-Z)
Sort based on rating (1-5)
Sort based on times played (largest-smallest)
Once a sort method is selected by the user, the sort must be performed on the records in the list. Consider using bubble sort, insertion sort, or selection sort.
What must “shuffle” do?
The “shuffle” command must provide a random order in which the songs are played. This command must not modify the links in the list. It must just specify the order in which songs are played, based on the position of the song in the list. For example, let’s say we have a list with 5 songs at positions 1 – 5 in the list, shuffle must generate an order 1 – 5 in which the songs are played. An order 2, 5, 3, 1, 4 would require that the second song in the list is played first, the fifth song in the list is played second, the third song in the list is played third, the first song in the list is played fourth, and the fourth song in the list is played fifth. The songs are accessed by traversing the list both forwards and backwards to satisfy the order. Hence, the need for a doubly linked list!
Once again you will find an example musicPlayList.csv (here).
IV. Logical Block Diagram
Once again, the logical block diagram for your doubly linked list should look like the following:
As you can see from the illustration a doubly linked list has a pointer to the next node and the previous node in the list. The first node’s previous node pointer is always NULL and the last node’s next pointer is always NULL. When you insert and delete nodes from a doubly linked list, you must always carefully link the previous and next pointers.
BONUS:
Modify your doubly linked list implementation(s) for your DMM so that last node in the list points to the first node, and the first node points to the last node. Hence, there is no longer a first or last node. This list is now called “circular”. Overall, it is called a circular doubly linked list. Any one of the nodes may by the current node!
PA2 information
Many of us have large digital music collections that are not always very well organized. It would be nice to have a program that would manipulate our music collection based on attributes such as artist, album title, song title, genre, song length, number times played, and rating. For this assignment you will write a basic digital music manager (DMM).
Your DMM program must have a text-based interface which allows the user to select from a main menu of options including: (1) load, (2) store, (3) display, (4) insert, (5) delete, (6) edit, (7) sort, (8) rate, (9) play, (10) shuffle, and (11) exit. For Part I of the assignment, you will only need to complete the main menu, (1) load, (2) store, (3) display, (6) edit, (8) rate, (9) play, and (11) exit features. The other features will be completed in the next part of the assignment.
What must the main menu contain?
The main menu must display the following commands:
(1) load
(2) store
(3) display
(4) insert
(5) delete
(6) edit
(7) sort
(8) rate
(9) play
(10) shuffle
(11) exit
After a command is selected and completed, your program must display the main menu again. This procedure will continue until the “exit” command is selected.
What must “load” do?
The “load” command must read all records from a file called musicPlayList.csv (you may find a sample file here) into a dynamic doubly linked list. The doubly linked list is considered the main playlist. As each record is read from the file, it must be inserted at the front of the list. Each record consists of the following attributes:
Each attribute, in a single record, will be separated by a comma in the .csv (comma separated values) file. This means that you will need to design an algorithm to extract the required attributes for each record. Each field in each record will have a value. You do not need to check for null or empty values.
You must define a struct called Record to represent the above attributes. Also, do not forget that the Song Length must be represented by another struct called Duration. Duration is defined as follows:
Finally, each struct Node in the doubly linked list must be defined as follows:
What must “store” do?
The “store” command writes the current records, in the dynamic doubly linked list, to the musicPlayList.csv file. The store will completely overwrite the previous contents in the file.
What must “display” do?
The “display” command prints records to the screen. This command must support two methods, one of which is selected by the user:
Print all records.
Print all records that match an artist.
What must “edit” do?
The “edit” command must allow the user to find a record in the list by artist. If there are multiple records with the same artist, then your program must prompt the user which one to edit. The user may modify all of the attributes in the record.
What must “rate” do?
The “rate” command must allow the user to assign a value of 1 – 5 to a song; 1 is the lowest rating and 5 is the highest rating. The rating will replace the previous rating.
What must “play” do?
The “play” command must allow the user to select a song, and must start “playing” each song in order from the current song. “Playing” the song for this assignment means displaying the contents of the record that represents the song for a short period of time, clearing the screen and showing the next record in the list, etc. This continues until all songs have been played.
What must “exit” do?
The “exit” command saves the most recent list to the musicPlayList.csv file. This command will completely overwrite the previous contents in the file.
IV. Logical Block Diagram
The logical block diagram for your doubly linked list should look like the following:
As you can see from the illustration a doubly linked list has a pointer to the next node and the previous node in the list. The first node’s previous node pointer is always NULL and the last node’s next pointer is always NULL. When you insert and delete nodes from a doubly linked list, you must always carefully link the previous and next pointers.
V. Submitting Assignments:
Using the OSBLE+ MS VS plugin, please submit your solution. Please visit http://osble.codeplex.com/wikipage?title=Submitting%20an%20Assignment&referringTitle=VS%20Plugin for more information about submitting using OSBLE+.
Your project must contain at least one header file (a .h file), two C source files (which must be .c files), and a local copy of the .csv file.
Your project must build properly. The most points an assignment can receive if it does not build properly is 65 out of 100.
Explanation / Answer
The question says ...
For Part I of the assignment, you will only need to complete the main menu, (1) load, (2) store, (3) display, (6) edit, (8) rate, (9) play, and (11) exit features. The other features will be completed in the next part of the assignment.
So implemented these features.
1. The music.csv format is not given the question. I have assumed the file structure to be something like shown below.... comma separated values and duration shown as min:sec . For ex:
Michael Jackson,Thriller,Thriller,Pop,3:40,2,5
So if there is any change in the format, please let me know through comment . Otherwise the load function will not work. We need to give correct format.
2. In some places you would see getchar(). This is because there will be from previous input and then the next input will not be read from keyboard. So to flush out newline, getchar() is used whereever needed , if next input is string
Please do rate the answer if it helped. Thanks
main.c
#include <stdio.h>
#include "list.h"
#include <ctype.h>
#include <stdlib.h>
#include <conio.h>
int main()
{
int choice;
FILE *fp;
char filename[256];
int num,rating;
node *list=NULL,*rec,*start;
char artist[MAX_LEN],album[MAX_LEN],song[MAX_LEN],genre[MAX_LEN];
duration d;
char ans;
do
{
//display menu and get user's choice
printf(" 1.Load 2.Store 3.Display 4.Insert 5.Delete");
printf(" 6.Edit 7.Sort 8.Rate 9.Play 10.Shuffle 11.Exit");
printf(" Enter your choice: ");
scanf("%d",&choice);
//depending on choice ask user for required inputs and call the functions
switch(choice)
{
case 1: /*load - get file name, load and close*/
printf(" Enter name of file to load: ");
getchar();
gets(filename);
fp=fopen(filename,"r");
list=load(fp);
fclose(fp);
break;
case 2:/*store - get file name , store and close*/
printf(" Enter name of file to store: ");
getchar();
gets(filename);
fp=fopen(filename,"w");
store(fp,list);
fclose(fp);
break;
case 3:/*display*/
printf(" The list of songs is ");
display(list);
break;
case 6:/*edit*/
printf(" Enter the artist name : ");
getchar();gets(artist);
start=list;
do
{
rec=find(artist,start); //find matching record from after the point where previous search ended
if(rec!=NULL)
{
displayRecord(rec); //show the record to user if it is the one
printf(" Is this the record you want to edit ? (y/n): ");
scanf("%c",&ans);
if(toupper(ans)=='Y') //if this is the record to be modified , get all new values
{
printf(" Enter new values for the record: ");
printf(" Artist: ");
getchar();gets(artist);
printf(" Album: ");
gets(album);
printf(" Song title: ");
gets(song);
printf(" Genre: ");
gets(genre);
printf(" Duration (min:sec) :");
scanf("%d:%d",&d.minutes,&d.seconds);
printf(" Rating: ");
scanf("%d",&rating);
edit(rec,artist,album,song,genre,d,rating);
printf(" Record edited successfully.");
break;
}
else
start=start->next;
}
}while(rec!=NULL);
if(rec==NULL)
{
printf(" No more records for the artist %s",artist);
}
break;
case 8:/*rate- display all records and ask which record user wants to rate*/
display(list);
printf(" Which record number do you want to rate ? ");
scanf("%d",&num);
printf(" Enter rating (1-5): ");
scanf("%d",&rating);
rate(num,rating,list);
break;
case 9:/*play - display list and ask the song number to start playing*/
display(list);
printf(" Enter the song number you want to start playing : ");
scanf("%d",&num);
play(num,list);
break;
case 11:/*exit*/
exit(0);
default:
;
}
}while(choice!=11);
}
list.h
#define MAX_LEN 100 /*the maximum size of all string data*/
#include <stdio.h>
/*represents the duration of song */
typedef struct time_details
{
int seconds;
int minutes;
}duration;
/*each node in the doubly linked list*/
typedef struct list_node
{
char *artist;
char *album;
char *song;
char *genre;
duration length; // the song length
int times; //times played
int rating; //rating 1-5
struct list_node *next;
struct list_node *prev;
}node;
//add a node to front of head
node *add_node(node *head,node *p);
node * create_node(char *artist,char *album,char *song,char *genre,duration d,int times,int rating);
void store(FILE *fp,node *head);
node *load(FILE *fp);
void display(node *head);
void displayRecord(node *rec);
void rate(int recordNo,int rating,node *head);
void edit(node *rec,char *artist,char *album,char *song,char *genre,duration d,int rating);
void play(int recordNo,node *head);
/*helper functions*/
node* find(char *artist,node *start);
char * copyspecial(char *s1,char *s2);
list.c
#include "list.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
/*add a node to front of head and returns the new head*/
node *add_node(node *head,node *p)
{
if(head==NULL)
return p;
else
{
p->next=head;
head->prev=p;
return p;
}
}
/*create a node with specified value*/
node * create_node(char *artist,char *album,char *song,char *genre,duration d,int times,int rating)
{
node *p = (node *)malloc(sizeof(node));
p->artist=(char *)malloc(strlen(artist)+1); //allocate how much ever is needed for the string
strcpy(p->artist,artist);
p->album=(char *)malloc(strlen(album)+1);
strcpy(p->album,album);
p->song=(char *)malloc(strlen(song)+1);
strcpy(p->song,song);
p->genre=(char *)malloc(strlen(genre)+1);
strcpy(p->genre,genre);
p->length.minutes=d.minutes;
p->length.seconds=d.seconds;
p->times=times;
p->rating=rating;
p->next=p->prev=NULL;
return p;
}
/* stores each record in the following format
* artist,album,songtitle,genre,m:s,times,rating
*/
void store(FILE *fp,node *head)
{
node *p=head;
while(p!=NULL)
{
fprintf(fp,"%s,%s,%s,%s,%d:%d,%d,%d ",p->artist,p->album,p->song,p->genre,p->length.minutes,p->length.seconds,p->times,p->rating);
p=p->next;
}
}
/*
* reads from file assuming each record format is
* artist,album,songtitle,genre,m:s,times,rating
*/
node *load(FILE *fp)
{
node *head=NULL,*p;
char artist[MAX_LEN],album[MAX_LEN],song[MAX_LEN],genre[MAX_LEN];
duration d;
int times,rating;
if(fp==NULL)
return NULL;
printf(" Loading file...");
while(!feof(fp))
{
fscanf(fp,"%[^,],%[^,],%[^,],%[^,],%d:%d,%d,%d ",artist,album,song,genre,&d.minutes,&d.seconds,×,&rating);
p=create_node(artist,album,song,genre,d,times,rating);
head=add_node(head,p);
}
printf(" Finished loading");
return head;
}
/*displays all the records starting from head to end of list*/
void display(node *head)
{
node *p=head;
int i=1;
while(p!=NULL)
{
printf(" Record %d",i);
displayRecord(p);
p=p->next;
i++;
}
}
/*displays the values in a single record rec*/
void displayRecord(node *rec)
{
printf(" Artist: %s",rec->artist);
printf(" Album: %s",rec->album);
printf(" Song: %s",rec->song);
printf(" Genre: %s",rec->genre);
printf(" Length: %d:%d",rec->length.minutes,rec->length.seconds);
printf(" Times: %d",rec->times);
printf(" Rating: %d ",rec->rating);
}
/*modifies the rating for the record number specified . if recordno is out of range , no records are modified but a message is shown*/
void rate(int recordNo,int rating,node *head)
{
int i=1;
node *p=head;
while(p!=NULL && i<recordNo)
{
p=p->next;
i++;
}
if(i!=recordNo) // not valid record number
{
printf(" Record number out of range");
}
else
{
p->rating=rating;
}
}
/*starts displaying message "playinga ..." from song number specified in recordno till end of list. If recordno is out range, error message is shown*/
void play(int recordNo,node *head)
{
int i=1;
node *p=head;
while(p!=NULL && i<recordNo)
{
p=p->next;
i++;
}
if(i!=recordNo) // not valid record number
{
printf(" Record number out of range");
}
else
{
do
{
printf(" Now playing %s ",p->song);
for(i=0;i<3000;i++) //just to pause for sometime
; //do nothing
p->times=p->times+1; //increase the number of times the record was played.
p=p->next;
}while(p!=NULL);
}
}
/*finds a matching record with given artist name ,beginning teh search at specified start node. If none is found NULL is returned*/
node* find(char *artist,node *start)
{
node *p=start;
while(p!=NULL)
{
if(strcmpi(p->artist,artist)==0) //do case insensitve name comparsion
{
break;
}
else
{
p=p->next;
}
}
return p;
}
/*this function is used to allocate memory for strings. In the records when an edit happens and we need to set new name, if space is not enough for new name
* allocate bigger size memory and free the old memory. Returns the memory location to be used - old one if no new memory was created. Otherwise new memory location
* is returned. The new value from s2 is copied.
*/
char * copyspecial(char *s1,char *s2)
{
if(strlen(s1)<strlen(s1))
{
free(s1);
s1=(char *)malloc(strlen(s2)+1);
}
strcpy(s1,s2);
return s1;
}
/*edits the values in the rec to specified values*/
void edit(node *rec,char *artist,char *album,char *song,char *genre,duration d,int rating)
{
rec->artist=copyspecial(rec->artist,artist);
rec->album=copyspecial(rec->album,album);
rec->song=copyspecial(rec->song,song);
rec->genre=copyspecial(rec->genre,genre);
rec->length.minutes=d.minutes;
rec->length.seconds=d.seconds;
rec->rating=rating;
}
sample input music.csv
Michael Jackson,Thriller,Thriller,Pop,3:40,2,5
Jennifer Lopez,albu1,song1,Hip Hop,2:50,1,4
sample output
1.Load
2.Store
3.Display
4.Insert
5.Delete
6.Edit
7.Sort
8.Rate
9.Play
10.Shuffle
11.Exit
Enter your choice: 1
Enter name of file to load: c:/test/music.csv
Loading file...
Finished loading
1.Load
2.Store
3.Display
4.Insert
5.Delete
6.Edit
7.Sort
8.Rate
9.Play
10.Shuffle
11.Exit
Enter your choice: 3
The list of songs is
Record 1
Artist: Jennifer Lopez
Album: albu1
Song: song1
Genre: Hip Hop
Length: 2:50
Times: 1
Rating: 4
Record 2
Artist: Michael Jackson
Album: Thriller
Song: Thriller
Genre: Pop
Length: 3:40
Times: 2
Rating: 5
1.Load
2.Store
3.Display
4.Insert
5.Delete
6.Edit
7.Sort
8.Rate
9.Play
10.Shuffle
11.Exit
Enter your choice: 9
Record 1
Artist: Jennifer Lopez
Album: albu1
Song: song1
Genre: Hip Hop
Length: 2:50
Times: 1
Rating: 4
Record 2
Artist: Michael Jackson
Album: Thriller
Song: Thriller
Genre: Pop
Length: 3:40
Times: 2
Rating: 5
Enter the song number you want to start playing : 1
Now playing song1
Now playing Thriller
1.Load
2.Store
3.Display
4.Insert
5.Delete
6.Edit
7.Sort
8.Rate
9.Play
10.Shuffle
11.Exit
Enter your choice: 6
Enter the artist name : Jenni
No more records for the artist Jenni
1.Load
2.Store
3.Display
4.Insert
5.Delete
6.Edit
7.Sort
8.Rate
9.Play
10.Shuffle
11.Exit
Enter your choice: 3
The list of songs is
Record 1
Artist: Jennifer Lopez
Album: albu1
Song: song1
Genre: Hip Hop
Length: 2:50
Times: 2
Rating: 4
Record 2
Artist: Michael Jackson
Album: Thriller
Song: Thriller
Genre: Pop
Length: 3:40
Times: 3
Rating: 5
1.Load
2.Store
3.Display
4.Insert
5.Delete
6.Edit
7.Sort
8.Rate
9.Play
10.Shuffle
11.Exit
Enter your choice: 6
Enter the artist name : jennifer lopez
Artist: Jennifer Lopez
Album: albu1
Song: song1
Genre: Hip Hop
Length: 2:50
Times: 2
Rating: 4
Is this the record you want to edit ? (y/n): y
Enter new values for the record:
Artist: jenni
Album: my album
Song title: my title
Genre: my gener
Duration (min:sec) :4:50
Rating: 3
Record edited successfully.
1.Load
2.Store
3.Display
4.Insert
5.Delete
6.Edit
7.Sort
8.Rate
9.Play
10.Shuffle
11.Exit
Enter your choice: 8
Record 1
Artist: jenni
Album: my album
Song: my title
Genre: my gener
Length: 4:50
Times: 2
Rating: 3
Record 2
Artist: Michael Jackson
Album: Thriller
Song: Thriller
Genre: Pop
Length: 3:40
Times: 3
Rating: 5
Which record number do you want to rate ? 1
Enter rating (1-5): 2
1.Load
2.Store
3.Display
4.Insert
5.Delete
6.Edit
7.Sort
8.Rate
9.Play
10.Shuffle
11.Exit
Enter your choice: 9
Record 1
Artist: jenni
Album: my album
Song: my title
Genre: my gener
Length: 4:50
Times: 2
Rating: 2
Record 2
Artist: Michael Jackson
Album: Thriller
Song: Thriller
Genre: Pop
Length: 3:40
Times: 3
Rating: 5
Enter the song number you want to start playing : 1
Now playing my title
Now playing Thriller
1.Load
2.Store
3.Display
4.Insert
5.Delete
6.Edit
7.Sort
8.Rate
9.Play
10.Shuffle
11.Exit
Enter your choice: 11