This is the sample text file content:
5 //columns
Id,Age,history,chemistry,biology //column names
100// number of data rows
3245167,12,45,78,12 //data rows separated by commas
30980424,10,26,38,98
and so on..
This is the general code i have so far:
int main()
{
//prints out input from file.
ifstream myFile;
myFile.open("WRITE FILE NAME");
while(Myfile.good()) { // good means while there is smthg in the file keep reading it
// until you reach to the end.
string line;
getline(myFile, line, ','); //read text until comma, then stop and store in variable.
cout << line << endl;
}
return 0;
}
You have a general outline of parsing the file itself, the data will be read from the file left to right. So there's two things I'd recommend for you to do at this point since you've already parsed the data. You'll probably want something to hold it like a queue to store and hold all the data and a double for loop to place it into the 2D array so like this:
std::queue<string> holder;
std::string myArray[row][col];
getline(myFile, line, ',');
holder.push(line);
for(int i=0; i < row; i++)
{
for(int j=0; j < col; j++)
{
myArray[i][j] = holder.pop();
}
}
Related
This is the file with data that I'm reading from:
MATH201,Discrete Mathematics
CSCI300,Introduction to Algorithms,CSCI200,MATH201
CSCI350,Operating Systems,CSCI300
CSCI101,Introduction to Programming in C++,CSCI100
CSCI100,Introduction to Computer Science
CSCI301,Advanced Programming in C++,CSCI101
CSCI400,Large Software Development,CSCI301,CSCI350
CSCI200,Data Structures,CSCI101
I have successfully read from the file and stored this information in a 2D Vector, but when I check the size of specific rows using course.info[x].size() it appears that its only counting the strings that have spaces between them. So for example, course.info[2].size() returns 2, whereas I would rather it would return 3. Essentially I want it to count each bit of information that is separated by a comma instead of a space. If I use while (getline(courses, line, ',') it puts the information separated by a comma in their own row, which is not what I want.
void LoadFile() {
vector<vector<string>> courseInfo;
ifstream courses;
courses.open("CourseInfo.txt");
if (!courses.is_open()) {
cout << "Error opening file";
}
if (courses) {
string line;
while (getline(courses, line)) {
courseInfo.push_back(vector<string>());
stringstream split(line);
string value;
while (split >> value) {
courseInfo.back().push_back(value);
}
}
}
for (int i = 0; i < courseInfo.size(); i++) {
for (int j = 0; j < courseInfo[i].size(); j++)
std::cout << courseInfo[i][j] << ' ';
std::cout << '\n';
}
getline(.., .., ',') is the tool for the job, but you need to use it in a different place.
Replace while (split >> value) with while (getline(split, value, ',').
I am trying to read from a data file that contains a header which is 4 lines, and also has a list of numbers that I will be storing into a 2d int array
for example
header
header
header
header
int
int
int
int
......
I need to somehow skip these header lines which contain text and only use the int lines and store them into the aforementioned 2d array. When I open the file and search through it, it doesn't store any values at all because of the text at the very start. I've tried multiple if statements and other things to get around this, but has worked so far.
int main()
{
ifstream imageFile;
imageFile.open("myfile");
if (!imageFile.is_open())
{
exit (EXIT_FAILURE);
}
int test2[16][16];
int word;
imageFile >> word;
while (imageFile.good())
for (int i = 0; i < 16; i++)
{
for (int j = 0; j < 16; j++)
{
test2[i][j] = word;
imageFile >> word;
}
}
}
As said in the comments, you need to first read the headers - here I just store the headers in a trash variable which is a string that's being overwritten every time I store new header:
std::string trash;
for (int i =0; i < 4; i++)
std::getline(imageFile, trash);
This part goes after you check if file opened correctly and will be directly followed by your original code where you declare the 2D array and read the integers.
As it was also said in the comments you need std::getline that reads every header line as a whole and not a word at a time which was the first version of my answer (imageFile >> trash;).
You can do this just by regex and patterns (Modify code for 2d array this is just example for how you can extract numbers from file or string):
std::string ss;
ifstream myReadFile;
myReadFile.open("foo.txt");
char output[100];
if (myReadFile.is_open()) {
while (!myReadFile.eof()) {
myReadFile >> output;
ss.append(output);
ss.append("\n");
}
}
myReadFile.close();
std::regex rx(R"((?:^|\s)([+-]?[[:digit:]]+(?:\.[[:digit:]]+)?)(?=$|\s))"); // Declare the regex with a raw string literal
std::smatch m;
std::string str = ss;
while (regex_search(str, m, rx)) {
std::cout << "Number found: " << m[1] << std::endl; // Get Captured Group 1 text
str = m.suffix().str(); // Proceed to the next match
}
Output:
Number found: 612
Number found: 551
Number found: 14124
I'm working on an app in QT, and I'm kinda new to C++ I/O; I want to read some data from a CSV file that currently has 2 columns and some rows, for example: (1 | 10) (2 | 20) I just want to store them in an array like this (1,10,2,20); for some, only values from the second column get stored in my array. Here is some code; I've checked many times, but I still can't see what I'm doing wrong:
void readingFiles::openFile(){
ofstream myFile;
myFile.open("/home/Dan/Desktop/mainFile.csv" ,std::ios::app);}
void readingFiles::addReadings(int readings1 , int readings2){
if(myFile.is_open()){
myFile<<readings1<<","<<readings2<<"\r";
myFile.close();
}
}
vector<int> values ;
ifstream iFile;
iFile.open("/home/Dan/Desktop/mainFile.csv");}
string data;
void readingFiles::read(){
for(int i =0; std::getline(iFile,data, ',') ; i++){
values.insert(values.end() , atoi(data.c_str()));
qDebug("vector list is %i" , values[i]);}
}
So, the result I get is that it reads the first row in the first column, then moves to read from the second column, and never goes back to the first (1, 10, 20, 30, 40 etc). Again, what I'm trying to get is (1, 10, 2, 20, 3, 30 etc.).
Your problem is that on second call getline is returning 10\n2. Then atoi converts this to 10. So you lose the 2. getline is supposed to discard newlines so I'm not sure why this is happening. It's a bit ugly, but parse 10\n2 in data to pick up anything after \n and add to vector.
I tested this with VC 2013 and that is the behaviour of getline with delimiter. I googled around and it does seem as if it is intended behaviour that getline with delimiter treats newline as a literal character. This works:
string line;
for (int i = 0; std::getline(myFile, line); i++)
{
stringstream ss(line);
for (int i = 0; std::getline(ss, data, ','); i++)
{
values.insert(values.end(), atoi(data.c_str()));
}
}
for (int i = 0; i < values.size(); i++)
{
cout << "vec=" << values[i] << endl;
}
I have to create a vector of vectors from a text file. The values in question are integers.
The values are a fixed 3 columns with varying rows. However, I don't believe this is causing my issues. The main issue I think I'm having is that the values from the text file aren't being put into the vector of vectors. The relevant code is as follows:
ifstream infile("material_properties.txt");
if (!infile)
{
cout << "File material_properties.txt not found." << endl;
return -1;
}
int lines = 0;
string line;
while (getline(infile, line))
{
++lines;
}
vector< vector<int> > properties(lines,vector<int>(3));
while (getline(infile,line)) {
for(int i=0; i < lines; i++){
for (int j=0; j<4; j++){
infile >> properties[i][j];
}
}
}
I'm very new to coding and very confused.
You need to rewind your ifstream, add:
infile.seekg(0);
before your second while (getline(infile,line)) {
This is because when you read a file, an internal pointer to the current file position is incremented. It incremented until end of file in first getline loop, so in second you need to rewind it.
Your second bug is that in;
vector< vector<int> > properties(lines,vector<int>(3));
you create vector of three elements in your vector of vector, but in the read loop you add four elements from your file. You should change it to vector<int>(4).
Third issue, is your way of parsing file. In your second loop you read file line by line, which indicates you want to parse it, but your code is actually wrong:
int i = 0;
while (getline(infile,line)) {
// This actually makes no sense, you have read one line
// which you should parse and put results into properties vector.
//for(int i=0; i < lines; i++){
// for (int j=0; j<4; j++){
// infile >> properties[i][j];
// }
//}
// parsing would look like this (depends on your input file):
std::istringstream in(line);
in >> properties[i][0] >> properties[i][1] >> properties[i][2];
i++;
}
First off
while (getline(infile, line))
{
++lines;
}
Is going to read in the file until it reaches the end of the file. Then when you go to read from the file again you are already at the end so nothing will be read. Instead of read in from the file to find the file size you can just read from the file and input the values into the vector. The vector will grow as you add data to it automatically.
ifstream infile("material_properties.txt");
vector< vector<int> > properties;
vector<int> row(3);
while (infile >> row[0] >> row[1] >> row[2])
{
properties.push_back(row);
}
Sorry, im a C++ noob! I have looked around for a solution but cant seem to find one that best suits my need. I am tring to read the width(max amount of char in line) and height (max amount of lines per file) of a txt file. Planning on using varaibles to help make dynamic sized txt files/levels.
I have had fixed width and height working previous to this!
TXT FILE: Simple output of chars for room layout (space=floor, #=wall, X=door):
########
# #
# X
# #
########
PROBLEM: Thought this to be a simple problem, but it only reads 2 of each variable(hNum,wNum)before breaking loop and program cant continue.
-What am i doing wrong?
-Should i be using seekg or different loop somehow?
-Do i need to alter my vector to 2D vector?
-Which is the best method for achieving this?
Room.cpp
//LOAD CURRENT ROOM FROM FILE
ss << RoomNo;
string str = ss.str();
string fname = ("Room");
fname.append(str);
fname.append(".txt");
infile.open(fname);
infile.clear();
infile.seekg(0);
if(infile.is_open())
{
// Sets width and height depndant on txt file size
string line;
//NOT WORKING!
while( !infile.eof())
{
hNum++;
getline ( infile, line);
wNum += line.length();
break;
}
height=hNum;
width=wNum;
//END
// Loop to end of file- to get you all the lines from txt file.
while(!infile.eof())
{
int i;
for(int row = 0; row < width; row++)
{
infile.getline(RoomFile, 256);
i = 0;
for(int col = 0; col < height; col++)
{
data.push_back(RoomFile[i]);
i++;
}
}
}
}
else
{
cout << "ERROR: infile not open" << endl;
}
infile.close();
UPDATE
This is what i got, tryin to do what Sky suggested...but cudnt work it all out. Then steped thro and thought the loop wasnt active so altered the argument. Now getting runtime error!
PROBLEM: Expression: vector subscript out of range!
Suggestions anyone?
string line;
while(getline(infile,line))
{
getline(infile, line);
tempVector.push_back(line);
}
width=line.length();
height=tempVector.size();
A possible way that can work would be to create a vector of strings and read the entire file, with each line a string in the vector.
Rough example:
#include <vector>
#include <string>
#include <fstream>
/* ... */
vector<string> content;
string buffer;
while(!infile.eof())
{
getline(infile, &string, '/n');
content.push_back(string);
}
width = findMaxLengthOfStrings(content);
height = content.size();
You are reading each line of the file as a separate string. The strings are pushed onto the vector. You can then easily find which string in the vector is longest, by iterating through the vector, using size(). The length in lines of the file is obtained with size() on the vector itself.
Also, posting just the relevant parts of the code, the I/O function, would have helped. Just saying ;) A small screen size and such.