Can't read in data separated by delimiters

I'm working on a project for my cs162 class and am having some trouble. For part of my project I have a .txt file with a list of song attributes seperated by delimiters that I need to read into an array of structs(.txt file elements have to be seperated by delimiters).

It reads in the struct's Title, Artist, and Album fine but it wont read in the Min or Sec. I do eventually need to loop this to read in every song. I spent 5 hours trying to troubleshoot this yesterday and am at my wit's end. I would greatly appreciate any help.

//file below////////////////////////////////////

#include <iostream>
#include <cstring>
#include <fstream>

using namespace std;

const int MAX_CHAR=101;

struct Song
{
char Title[MAX_CHAR];
char Artist[MAX_CHAR];
char Album[MAX_CHAR];
int Min;
int Sec;
};

int main()

{

Song song[i];

ifstream in;
in.open("roster.txt");
if(!in) return(1);

in.get(song[i].Title, MAX_CHAR, ';');
in.ignore();
in.get(song[i].Artist, MAX_CHAR, ';');
in.ignore();
in.get(song[i].Album, MAX_CHAR, ';');
in>>song[i].Min;
in.ignore(MAX_CHAR, ';');
in>>song[i].Sec;
in.ignore(MAX_CHAR, '\n');



cout<<song[i].Title<<endl;

cout<<song[i].Artist<<endl;
cout<<song[i].Album<<endl;
cout<<song[i].Min<<endl;
cout<<song[i].Sec<<endl;

in.close();

return 0;
}
//////////////////////////////////////////////////////////////////////

//roster.txt below////////////////////////////////////////////////////

Break;Three Days Grace;Life Starts Now;3;13
Joker And The Thief;Wolfmother;Wolfemother;4;40
Satellite;Rise Against;Endgame;3;58
Come with Me Now;Kongos;Lunatic;3;31
//////////////////////////////////////////////////////////////////////

//Output of code below///////////////////////

Break
Three Days Grace
Life Starts Now
4
32766
closed account (1Ck93TCk)
Hi theleonicking,

It looks like we're working on the same assignment! lol. I did a quick side-by-side and there are a couple of things different.

HUGE disclaimer. I am a beginner and should not be trusted. I just think I might have some insight since I'm working on the same program.

First, instead of in.get, I used infile.get. Because we're reading from a file, right?
Second, I'm not sure you need all of those ignore statements. I just used it once, at the end of the input statements.
Third, what I did was use cin.get() in all of the places that you put cin.ignore(). This throws out the semicolon delimiter (which I think you were trying to do with ignore?).

Hope that helps!

And if anything I'm saying is bad info I hope someone will speak up so I can learn.

Good luck!
jmb
Last edited on
Thanks and the the changes don't seem to be working sadly. If yours is working right, could you paste your version of this part so I can see what's going on?

GL to you too!
Try this as a framework to build on. There are plenty of other ways to do this but seeing that you are using C-strings this way using strtok() to parse each line is OK.

See the strtok() reference and sample program on this site. Try the sample first :)
http://www.cplusplus.com/reference/cstring/strtok/?kw=strtok

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
46
47
48
#include <iostream>
#include <cstring>
#include <fstream>

using namespace std;

const int MAX_CHAR = 200;

struct Song
{
    char Title[MAX_CHAR];
    char Artist[MAX_CHAR];
    char Album[MAX_CHAR];
    int Min;
    int Sec;
};

const int ALBUM_SIZE = 100;

int main()

{
    Song song[ALBUM_SIZE];
    
    char buffer[MAX_CHAR];
    
    ifstream in;
    in.open("roster.txt");
    if(!in)
    {
        return(1);
    }
    
    int song_no = 0; // BECOMES USEFUL LATER ON
    while( in.getline(buffer, MAX_CHAR) )
    {
        cout << song_no << ' ' << buffer << '\n';
        // USE strtok() FUNCTION HERE AND AS EACH TOKEN ROLLS OUT
//        song[song_no].Title = ...
//        etc
        
        song_no++;
    }
    
    in.close();
    
    return 0;
}
Last edited on
PS The includes in the sample are a bit out of date so this works just as well.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/* strtok example */
#include <iostream>
#include <cstring>

int main ()
{
  char str[] ="- This, a sample string.";
  char * pch;
  printf ("Splitting string \"%s\" into tokens:\n",str);
  pch = strtok (str," ,.-");
  while (pch != NULL)
  {
    printf ("%s\n",pch);
    pch = strtok (NULL, " ,.-");
  }
  return 0;
}
Just to give you an idea...

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
46
47
48
49
50
#include <iostream>
#include <string>
#include <ios> // for streamsize
#include <limits> // for include numeric_limits.
#include <fstream>


struct Song
{
	std::string Title;
	std::string Artist;
	std::string Album;
	int Min;
	int Sec;
};

int main()

{
	const int totalOfElemFile = 4;
	Song song[totalOfElemFile];

	std::ifstream in;
	in.open("roster.txt");
	if (!in) return(1);

	for (int count = 0; count < totalOfElemFile; count++)
	{
		std::getline(in, song[count].Title, ';');
		std::getline(in, song[count].Artist, ';');
		std::getline(in, song[count].Album, ';');
		in >> song[count].Min;
		in.ignore(std::numeric_limits<std::streamsize>::max(), ';');
		in >> song[count].Sec;

	}

	for (int count = 0; count < totalOfElemFile; count++)
	{
		std::cout << song[count].Title << std::endl;
		std::cout << song[count].Artist << std::endl;
		std::cout << song[count].Album << std::endl;
		std::cout << song[count].Min << std::endl;
		std::cout << song[count].Sec << std::endl;
	}

	in.close();

	return 0;
}


Output...

Break
Three Days Grace
Life Starts Now
3
13

Joker And The Thief
Wolfmother
Wolfemother
4
40

Satellite
Rise Against
Endgame
3
58

Come with Me Now
Kongos
Lunatic
3
31
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <iostream>
#include <cstring>
#include <fstream>

using namespace std;

const int MAX_CHAR = 200;

struct Song
{
    char Title[MAX_CHAR];
    char Artist[MAX_CHAR];
    char Album[MAX_CHAR];
    int Min;
    int Sec;
};

const int ALBUM_SIZE = 100;

int main()

{
    Song song[ALBUM_SIZE];
    
    char buffer[MAX_CHAR];
    
    ifstream in;
    in.open("roster.txt");
    if(!in)
    {
        return(1);
    }
    
    int song_no = 0; // BECOMES USEFUL LATER ON
    char *pch;
    
    while( in.getline(buffer, MAX_CHAR) )
    {
        cout << song_no << ' ' << buffer << '\n';
        
        char temp[5][MAX_CHAR];// HOLDS THE TOKENS
        
        // TOKENIZE
        int counter = 0;
        
        pch = strtok (buffer,";");
        while (pch != nullptr)
        {
            strcpy(temp[counter], pch);
            cout << counter << ' ' << temp[counter] << '\n';
            
            pch = strtok (nullptr, ";");
            counter++;
        }
        
        strcpy(song[song_no].Title, temp[0]);
        strcpy(song[song_no].Album, temp[1]);
        strcpy(song[song_no].Artist, temp[2]);
        
        // NOW  CONVERT TO INTEGERS IF REQUIRED
        song[song_no].Min = std::atoi(temp[3]);
        song[song_no].Sec = std::atoi(temp[4]);

        song_no++;
    }
    in.close();
    
    for(int i = 0; i < song_no; i++)
    {
        if( strcmp(song[i].Album, "Wolfmother") )
            cout << "****************** Bingo\n";
        
        cout
        << "\""
        << song[i].Album << "\" by "
        << song[i].Artist
        << " Length: "
        << song[i].Min << ":"
        << song[i].Sec
        
        << '\n';
    }
    
    return 0;
}


0 Break;Three Days Grace;Life Starts Now;3;13
0 Break
1 Three Days Grace
2 Life Starts Now
3 3
4 13
1 Joker And The Thief;Wolfmother;Wolfemother;4;40
0 Joker And The Thief
1 Wolfmother
2 Wolfemother
3 4
4 40
2 Satellite;Rise Against;Endgame;3;58
0 Satellite
1 Rise Against
2 Endgame
3 3
4 58
3 Come with Me Now;Kongos;Lunatic;3;31
0 Come with Me Now
1 Kongos
2 Lunatic
3 3
4 31
****************** Bingo
"Three Days Grace" by Life Starts Now Length: 3:13
"Wolfmother" by Wolfemother Length: 4:40
****************** Bingo
"Rise Against" by Endgame Length: 3:58
****************** Bingo
"Kongos" by Lunatic Length: 3:31
Program ended with exit code: 0


EDIT: for strcmp()
Last edited on
againtry , Nice!
Thanks, yours too with another approach.

I would have helped the other guy, but you saw the result.
Thanks so much you guys! Now all I have left to do is figure out my search functions.
strcmp() is a C function that won't go astray.

Hint: Once you have a match the key result is the index number of the song, and don't go beyond the counted number of songs.
Thanks, I've been fooling around with strcmp but I can't seem to convert an inputed name or my song[i].Artist into a char a[] value like the syntax for it shows.
See above for strcmp() EDIT.

Next step is to store the cin value in a buffer to automate the comparison
Thanks and I finally figured it out. I had to use strcpy to convert. Its all working now except for the loop. I tried nesting a do..while loop inside a for loop so that i would increment and the strcmp value would stop at the correct value but it just loops infinitely.

void searchartist(int &listsize, int &i, Song song[])
{
listsize=i;
i=0;
cout<<"Please enter the name of the song's artist: ";

char artist[MAX_CHAR];
cin >> artist;
cin.ignore(MAX_CHAR, '\n');
char *a1=artist;
strcpy(a1, artist);
cout<<a1<<endl<<endl;;
int Compare;
char *a2=song[i].Artist;
strcpy(a2, song[i].Artist);
strcmp(a1, a2);

for(i=0;i<listsize;i++)
{
do
{
a2=song[i].Artist;
Compare=strcmp(a1,a2);
cout<<a1<<" : "<<a2<<" : "<<Compare<<endl;
}while(Compare!=0);
}
cout<<song[i].Title<<endl;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    cout << "Enter Artist to search for? ";
    cin.getline(buffer, MAX_CHAR);
    cout << "Searching for: " << buffer << '\n';
    
    for(int i = 0; i < song_no; i++)
    {
        if( strcmp(buffer, song[i].Artist) == 0 )
        {
            cout << "****************** Bingo\n";
            
            cout
            << "\""
            << song[i].Album << "\" by "
            << song[i].Artist
            << " Length: "
            << song[i].Min << ":"
            << song[i].Sec
            
            
            << '\n';
        }
    }


Topic archived. No new replies allowed.