reading files

Hello im trying to read a file and put it inside a 2D array, until now i succeded on reading the first line of the file and putting it into a 1D array (str[4]) but i need help writting the code to read the other lines.
this is the file im trying to read (ignore the language, the important thing is that the parts i need of the file are separated by the same words in all the lines, which i represented by 1, 2, 3, 4 just for testing it out):

Agrupación Política(1): FJ - lista(2): 3 - Nombre(3): Yaniez - Votos(4): 29
Agrupación Política: FJ - lista: 3 - Nombre: Casamiqueta - Votos: 72
Agrupación Política: PAIS - lista: 4 - Nombre: Massa - Votos: 57
Agrupación Política: PAIS - lista: 4 - Nombre: Stolbizer - Votos: 71

thank you


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
int main()
{
    ifstream file("C:\\Users\\mmoto\\Desktop\\prueba.txt");
    stringstream buffer;
    buffer << file.rdbuf();
    string test = buffer.str();
    cout << test << endl << endl;

    size_t pos1 = 0;
    size_t pos2;

    string str[4];
      
        pos2 = test.find("1", pos1); 
        str[0] = test.substr(pos1, (pos2-pos1)); 
        cout << str[0] << endl;
        cout << "pos1:" << pos1 << ", pos2:" << pos2 << endl;
        pos1 = pos2+1; 

        pos2 = test.find("2", pos1);
        str[1] = test.substr(pos1, (pos2-pos1));
        cout << str[1] << endl;
        cout << "pos1:" << pos1 << ", pos2:" << pos2 << endl;
        pos1 = pos2+1;

        pos2 = test.find("3", pos1);
        str[2] = test.substr(pos1, (pos2-pos1));
        cout << str[2] << endl;
        cout << "pos1:" << pos1 << ", pos2:" << pos2 << endl;
        pos1 = pos2+1;

        pos2 = test.find("4", pos1);
        str[3] = test.substr(pos1, (pos2-pos1));
        cout << str[3] << endl;
        cout << "pos1:" << pos1 << ", pos2:" << pos2 << endl;
Hello maticode20,

You have several problems here.

1. I believe the use of "rdbuf()" will put the entire file into buffer. Not what you want when you should be reading one line at a time.

2. The first line of the file is different than the rest and will cause extra work that you do not need just to deal with "(1)", "(2)" etc.

3. Lines 14 on will only process one line of the file and there is no way to process the rest of the file.

I will need to work on this, but there are better ways to process the file than what you have done. Which is not to say that what you have can not be fixed.

Hope that helps,

Andy
Hello maticode20,

Out of any given line in the input file I do not know what information you need to use, but this might give you an idea of what you can do.

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
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>


int main()
{
	std::string line{ "" };
	std::string iFileName{ "InputFile.txt" };

	std::ifstream inFile;

	inFile.open(iFileName);

	if (inFile.is_open())
	{
		//std::cout << "\n File " << iFileName << " is open" << std::endl;
		//std::this_thread::sleep_for(std::chrono::seconds(2));  // <--- Needs header files chrono" and "thread".
	}
	else
	{
		std::cout << "\n File " << iFileName << " did not open" << std::endl;
		std::this_thread::sleep_for(std::chrono::seconds(3));  // <--- Needs header files chrono" and "thread".
		exit(1);
	}

	std::string agrupacion{ "" }, basura{ "" }, lista{ "" }, nombre{ "" }, votos{ "" };

	while (std::getline(inFile, line))
	{
		std::istringstream ss(line);

		std::getline(ss, basura, ':');  // 3rd parameter is the delimiter.
		std::getline(ss, basura, ' ');
		std::getline(ss, agrupacion, ' ');
		std::getline(ss, basura, ':');
		std::getline(ss, basura, ' ');
		std::getline(ss, lista, ' ');

		std::cout << std::endl;
	}  //  End while

}  //  End main function 


Lines 35 to 40 and what I did not put could be shortened by revising the input file to make use of a delimiter character and less spaces.

Out of a given line, Agrupación Política: FJ - lista: 3 - Nombre: Casamiqueta - Votos: 72, what parts do you actually need? E.g., "FJ", "3", "Casamiqueta", "72"?

Notice that I included the header file "vector". To use this I would create a class or struct to put the information from each line and store the class or struct in the vector for later use. Otherwise you are just overwriting the information from one read with the next unless you process that information before the next read.

Hope that helps,

Andy
Just for hints:
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Hello im trying to read a file and put it inside a 2D array, until now 
// i succeded on reading the first line of the file and putting it into a 1D 
// array (str[4]) but i need help writting the code to read the other lines.
// this is the file im trying to read (ignore the language, the important thing 
// is that the parts i need of the file are separated by the same words in all 
// the lines, which i represented by 1, 2, 3, 4 just for testing it out):

// Agrupación Política(1): FJ - lista(2): 3 - Nombre(3): Yaniez - Votos(4): 29
// Agrupación Política: FJ - lista: 3 - Nombre: Casamiqueta - Votos: 72
// Agrupación Política: PAIS - lista: 4 - Nombre: Massa - Votos: 57
// Agrupación Política: PAIS - lista: 4 - Nombre: Stolbizer - Votos: 71

#include <fstream>
#include <iostream>
#include <sstream>
#include <limits>
#include <stdexcept>
#include <string>
#include <vector>

struct FileData {
    std::string ap_name;        // e.g. FJ or PAIS
    unsigned lista          {}; // n. lista
    std::string nombre;         // e.g. Yaniez or Casamiqueta or Massa...
    unsigned votos          {}; // n. votos
    friend std::ostream& operator<<(std::ostream& os, const FileData fd);
};

std::vector<FileData>& readFileData(std::ifstream& myfile,
                                    std::vector<FileData>& myvec);
std::string findOneToken(std::string& line);
void waitForEnter();

int main()
{
    std::ifstream file("prueba.txt");
    std::vector<FileData> myfiledata;
    readFileData(file, myfiledata);
    for(const auto& v : myfiledata) { std::cout << v << '\n'; }
    waitForEnter();
    return 0;
}

std::ostream& operator<<(std::ostream& os, const FileData fd)
{
    return (os << "Agrupacion Politica: " << fd.ap_name // limited to English alphabet
               << " - lista: " << fd.lista
               << " - Nombre: " << fd.nombre
               << " - Votos: " << fd.votos);
}

std::vector<FileData>& readFileData(std::ifstream& myfile,
                                    std::vector<FileData>& myvec)
{
    std::string line;
    while(std::getline(myfile, line)) {
        FileData fd;
        try {
            fd.ap_name = findOneToken(line);
            std::string tmp = findOneToken(line);
            fd.lista = static_cast<unsigned>(std::stoul(tmp));
            fd.nombre = findOneToken(line);
            tmp = findOneToken(line);
            fd.votos = static_cast<unsigned>(std::stoul(tmp));
        } catch (std::range_error err) {
            std::cout << "\nUnexpected end of line!\nData could be inconsistent.\n";
            break;
        }
        myvec.push_back(fd);
    }
    return myvec;
}

std::string findOneToken(std::string& line)
{
    std::string::size_type colon = line.find_first_of(':');
    if(++colon == std::string::npos) { // ++colon --> skips ':'
        std::range_error err("Can't find any colon.");
        throw err;
    }
    std::string::size_type hyphen = line.find_first_of('-');
    std::string::size_type to = (hyphen == std::string::npos ? 
                                            std::string::npos : hyphen -  colon);
    std::string tmpstr = line.substr(colon, to);
    std::stringstream ss(tmpstr);
    ss >> tmpstr; // remove leading and trailing white spaces
    // Modifying the ORIGINAL string:
    // http://en.cppreference.com/w/cpp/string/basic_string/substr: 
    // "If the requested substring extends past the end of the string, or if 
    //  count == npos, the returned substring is [pos, size())."
    line.erase(0, ++hyphen);
    return tmpstr;
}

void waitForEnter()
{
    std::cout << "\nPress ENTER to continue...\n";
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}


(Prolix and inelegant - if someone fancies improving it, I'll be sincerely grateful.)
Last edited on
Topic archived. No new replies allowed.