getline and reading into a struct array

Hello,

I'm stuck at the beginning of this project and can't figure out what I'm doing wrong. I've read at least a dozen other posts asking similar questions, but none of it seems explain my issue to me. I have a file with information about different songs (singer, song name, etc) and I am reading this file into a struct array.

I've barely even gotten started. The file opens successfully, but I just can't get it to read into the array. It's delimited by semi colons. I know getline is the right choice for this, but every time I try to use it I get errors.

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

using namespace std;

const int MAX = 18;

struct songType
{
    char songName[20];
    char artist[20];
    int min;
    int sec;
    char album[20];
}song[MAX];

void readInData(ifstream &infile, char songArr[MAX]);
void displayMenu();
void readAnswer();
void writeToFile();

int main()
{
    ifstream infile;
    ofstream outfile;
    char songArr[MAX];

    readInData(infile, songArr);
}

void readInData(ifstream &infile, char songArr[MAX])
{
    int i = 0;
    
    infile.open("songs.txt");

    if(infile)
        cout << "data is good!" << endl;
    else
        cout << "Cannot open file" << endl;

    for(i = 0; i < MAX; i++)
    {
        getline(infile, song[i].songName, ';');
        
        /*infile >> song[i].songName; //infile almost works but splits at spaces
                                      //rather than the ';' delimiter

               >> song[i].artist
               >> song[i].min
               >> song[i].sec
               >> song[i].album; */
    }
}


The errors that I'm getting:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
||=== Build file: "no target" in "no project" (compiler: unknown) ===|
project2.cpp||In function ‘void readInData(std::ifstream&, char*)’:|
project2.cpp|45|error: no matching function for call to ‘getline(std::ifstream&, char [20], char)’|
/usr/include/stdio.h|616|note: candidate: __ssize_t getline(char**, size_t*, FILE*)|
/usr/include/stdio.h|616|note:   no known conversion for argument 1 from ‘std::ifstream {aka std::basic_ifstream<char>}’ to ‘char**’|
/usr/include/c++/7/bits/basic_string.h|6339|note: candidate: template<class _CharT, class _Traits, class _Alloc> std::basic_istream<_CharT, _Traits>& std::getline(std::basic_istream<_CharT, _Traits>&&, std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&)|
/usr/include/c++/7/bits/basic_string.h|6339|note:   template argument deduction/substitution failed:|
project2.cpp|45|note:   mismatched types ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>’ and ‘char [20]’|
/usr/include/c++/7/bits/basic_string.h|6332|note: candidate: template<class _CharT, class _Traits, class _Alloc> std::basic_istream<_CharT, _Traits>& std::getline(std::basic_istream<_CharT, _Traits>&&, std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&, _CharT)|
/usr/include/c++/7/bits/basic_string.h|6332|note:   template argument deduction/substitution failed:|
project2.cpp|45|note:   mismatched types ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>’ and ‘char [20]’|
/usr/include/c++/7/bits/basic_string.h|6324|note: candidate: template<class _CharT, class _Traits, class _Alloc> std::basic_istream<_CharT, _Traits>& std::getline(std::basic_istream<_CharT, _Traits>&, std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&)|
/usr/include/c++/7/bits/basic_string.h|6324|note:   template argument deduction/substitution failed:|
project2.cpp|45|note:   mismatched types ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>’ and ‘char [20]’|
/usr/include/c++/7/bits/basic_string.tcc|1537|note: candidate: template<class _CharT, class _Traits, class _Alloc> std::basic_istream<_CharT, _Traits>& std::getline(std::basic_istream<_CharT, _Traits>&, std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&, _CharT)|
/usr/include/c++/7/bits/basic_string.tcc|1537|note:   template argument deduction/substitution failed:|
project2.cpp|45|note:   mismatched types ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>’ and ‘char [20]’|
||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|


When I comment out getline and just use infile, I get no errors but incorrect result. So it's getline. Everything that I've found online tells me that I'm using it correctly, but obviously I'm not because it's not working.

I would really appreciate any help!

begin01
The getline that you are using expects a std::string, not a raw char array.
If you must use a char array, then it looks like this:

infile.getline(song[i].songName, 20, ';');

But it's best to use std::string instead, and a std::vector instead of a raw array of structs.

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
#include <fstream>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>
using namespace std;

struct Song
{
    string name;
    string artist;
    string album;
    int seconds;
};

bool readData(string filename, vector<Song>& songs)
{
    ifstream fin(filename);
    if (!fin)
    {
        cerr << "Cannot open " << filename << '\n';
        return false;
    }

    Song song;
    while (getline(fin, song.name, ';'))
    {
        getline(fin, song.artist, ';');
        int min, sec;
        char ch; // for semicolon
        fin >> min >> ch >> sec >> ch;
        song.seconds = min * 60 + sec;
        getline(fin, song.album);
        songs.push_back(song);
    }

    return true;
}

void printData(const vector<Song>& songs)
{
    for (const auto& song: songs)
        cout << left
             << setw(20) << song.name   << "  "
             << setw(20) << song.artist << "  "
             << right
             << setw(4) << song.seconds / 60 << ':'
             << setfill('0')
             << setw(2) << song.seconds % 60 << "  "
             << setfill(' ')
             << song.album << '\n';
}

int main()
{
    vector<Song> songs;
    if (!readData("songs.txt", songs))
        return 1;
    printData(songs);
    return 0;
}

Topic archived. No new replies allowed.