addSong

How would i go about adding a song to a song array without a loop? the function takes in one song at a time, and it wont let me do song_array = song ,
says it cannot convert Song* to Song**

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void addSong(CD* cd, String* title, String* length)
{
	int num_tracks = cd->num_tracks;
	Song** song_array = new Song*[num_tracks];
	
	for(int i = 0; i < num_tracks; i++)
	{
		Song* song = createSong(title, length);
		song_array[i] = song;
	}
	
	cd->song_array = song_array;
}  

Song* createSong(String* title, String* length)
{
	Song* song = new Song;
	song->title = createString(title->text);
	song->length = createString(length->text);
	
	return song;
}


and the structs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
struct CD
{
   String* artist;
   String* title;

   int year;
   int rating;
   int num_tracks;
   int track_count;

   Song** song_array;
};

struct Song
{
   String* title;
   String* length;
};
If addSong takes one song at a time, it must do one of the following:

a) assume, that CD* it takes as first argument is already created and have known number of tracks. Then it also needs to know which track is being added - so another funtion parameter is required. It would then look like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void addSong(CD* cd, String* title, String* length, int track_num)
{
    // Create new song, add it to array to known position
    Song* song = createSong(title, length);
    cd->song_array[track_num] = song;
}

int main() {
    CD cd;
     // I will assume that this is the way to create String *
    cd.artist = new String ("Artist");
    cd.num_tracks = 3;

    // song_array has to be created before adding songs:
    cd.song_array= new Song* [num_tracks];

    addSong(&cd, new String("Some Title"), new String ("4:20"), 0);
    addSong(&cd, new String("Other Title"), new String ("1:52"), 1);
    addSong(&cd, new String("Yet another Title"), new String ("2:02"), 2);
}

b) be able to resize song_array - the more interesting option
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
void addSong(CD* cd, String* title, String* length)
{
    // Create new larger song array to hold one more song
    Song** new_song_array = new Song* [cd->num_tracks + 1];
    
    // Copy contents from old array
    for (int i = 0; i < cd->num_tracks; i++)
    {
        new_song_array[i] = cd->song_array[i];
    }

    // Create new song, add it to new array to the end
    Song* song = createSong(title, length);
    new_song_array[num_tracks] = song;
    
    // Update num_tracks
    cd->num_tracks ++;

    // delete old array, and replace with new one
    delete[] (cd->song_array);
    cd->song_array = new_song_array;
}

int main()
{
    CD cd;
    cd.artist = new String ("Artist");

    // The following two lines are required to initialize variables
    // to initial zero state (no songs added yet, so num_tracks = 0)
    cd.num_tracks = 0; 
    cd.song_array = new Song*[cd.num_tracks]; 
    
    // Add some songs
    addSong(&cd, new String("Some Title"), new String ("4:20"));
    addSong(&cd, new String("Other Title"), new String ("1:52"));
    addSong(&cd, new String("Yet another Title"), new String ("2:02"));

    // Just show the album details
    for(int i = 0; i < cd.num_tracks; i++)
    {
        cout << i+1 << ". " << cd.song_array[i]->title->value 
            << " " << cd.song_array[i]->length->value << endl;
    }
}
1. Some Title 4:20
2. Other Title 1:52
3. Yet another Title 2:02

c) You can also keep separate counters for max number of tracks on CD and current number of tracks to avoid resizing the array:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
void addSong(CD* cd, String* title, String* length)
{
    // Make sure not to go out of bounds
    if (cd->num_tracks >= cd->MAX_TRACKS)
        cout << "CD is full, sorry";

    // Create new song, add it to array to first free position
    // which is the same as cd->num_tracks, so it happens
    Song* song = createSong(title, length);
    new_song_array[cd->num_tracks] = song;

    // don't forget to increase it
    cd->num_tracks++;
}

int main() {
    CD cd;
    cd.artist = new String ("Artist");
    cd.MAX_TRACKS = 10;
    
    // number of added tracks
    cd.num_tracks = 0; 

    // must create complete array in advance of adding songs
    cd.song_array = new Song*[MAX_TRACKS]; 

    addSong(&cd, new String("Some Title"), new String ("4:20"));
    addSong(&cd, new String("Other Title"), new String ("1:52"));
    addSong(&cd, new String("Yet another Title"), new String ("2:02"));
}
Last edited on
Thanks! i went with option a, we already had a track_count so i was able to set it to i in the loop. Think you could tell my why my display cd isnt working? Once it gets to the songs it prints out gibberish and crashes. I know the songs are in the array so i dont understand what could be wrong.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
void displayCD(CD* cd)
{
	cout<<"Artist: "<< cd->artist->text <<endl;
	cout<<"Album: "<< cd->title->text <<endl;
	cout<<"Year: " <<cd->year<<endl;
	cout<<"Rating: "<<cd->rating <<endl;
	
	Song** song_array = cd->song_array;
	int k =0;
	for(int i = 1; i <= cd->num_tracks; i++)
	{
		cout<< i << ". ";
		displaySong(song_array[k]);
		k++;
	}
}

void displaySong(Song* song)
{
	displayString(song->title);
	cout<< " ";
	displayString(song->length);
	cout<<endl;
}

void displayString(String* str)
{
   const char* text = str->text;
   cout << text;
}
If you chose option a, check it again as I corrected my own errors there.
As for song printing - aren't you overcomplicating it? If you even need another function, which in actuality is one-liner, it could look like this:
1
2
3
4
void displaySong (Song* song)
{
    cout << song->title->text << " " << song->length->text << endl;
}

Besides, in line 28, declaring another variable just to hold function argument is redundant :
1
2
3
4
void displayString(String* str)
{
   cout << str->text;
}


EDIT:
The code you present seems to be valid, but if the garbage is printed I would need to know how text values are being created and how is String defined. One reason might be that you are assigning song->title->text a pointer to temporary variable, which goes out of scope in some function, and not to value created with new keyword.
Last edited on
Topic archived. No new replies allowed.