Grabbing data from file using getline - c++

So I have a file that has multiple columns of data like this:
1 2 3
4 5 6
7 8 9
etc...
And I'm traversing through this file with a while loop trying to store the data in a vector as I go along. But when I use a delimiter to deal with the spaces in between the data it only reads the first line and stops. The code for the while loop is as follows:
while(getline(infile,content, ' '))
{
double temp = atof(content.c_str();
cout << "value storing is: " << temp << endl;
data.push_back(temp);
}
Using the data above with this code I just get "1 2 3" as the output. So i'm not sure where I'm going wrong with this.
The column the numbers are in are also important when I crunch the data later. For example, every iteration of the while loop will add a counter and every time it goes to a new line will be another counter so with that i can figure out how many lines I have so when I need to compute something I can use i%(columnNumber) to grab that value.
Thanks for any light anyone can shed on my situation.

It's because there are no spaces after a new line.
This is what the file looks like (to std::getline())
1 space 2 space 3 newline 4 space 5 space 6 newline 7 space 8 space 9
I can't reproduce "1 2 3" as output. When I run your code, I get
value storing is: 1
value storing is: 2
value storing is: 3
value storing is: 5
value storing is: 6
value storing is: 8
value storing is: 9
where my test file looks like this:
1 2 3
4 5 6
7 8 9
To fix the problem, try doing something like this:
int main()
{
std::ifstream in("test");
std::string content;
std::vector<int> data;
while (getline(in, content))
{
std::stringstream linestream(content);
int value;
// Read an integer at a time from the line
while(linestream >> value)
{
// Add the integers from a line to a 1D array (vector)
data.push_back(value);
std::cout << "value storing is: " << value << std::endl;
}
}
}

Related

C++ [std::regex] trying to match only numbers with spaces in between

I'm working on a card game in C++ where I want to get some user input via getline(). The input needs to be in this specific format:
"1 2 3 4 5 6"
The range of numbers is 1-11 and each number must be seperated with a space. The user is putting in index numbers for a vector. Say he writes "1 2 3" and hits enter, position 0, 1 and 2 are being adressed by the vector.
I'm also open for any other recommendations considering the design decision to let the user input the vector (or essentially their card's) position.
The player cards are displayed in this format "1 blue" and are stored as strings in a vector. I figured it is too much hassle for the user to input the whole card name, so I chose to use the vector index.
Below is the code snippet of my regex string. It works, kinda. It just pushes the whole string in the vector, missing the 10. But I don't need 1 vector element like this: "1 2 3 4", I need 4 vector elements with every number being one element.
Things that shouldn't match:
"1234567"
"abcdef"
"12 34 567 32"
If you need any further context, I will gladly provide so.
Thanks in advance
int main()
{
int i = 0;
std::regex rx("([[:digit:]]\\s)+([[:digit:]]\\s)+");
std::string line = "1 2 3 4 5 6 7 8 9 10";
std::smatch m;
std::vector<std::string> catchit;
while (regex_search(line, m, rx))
{
std::cout << "Pattern found " << m[i] << '\n';
catchit.push_back(m[i]);
line = m.suffix().str();
i++;
}
return 0;
}
This solves my problem without having to use regex, thank you very much #Nick
Why not std::cin? Or wrap your output from getline in a
std::stringstream and use operator>> to read numbers one at a time and
validate them then? E.g. std::stringstream stream(line); /* loop */
stream >> val; if (val < 0 || val > 11)...

Getline skips last semicolon (csv) c++

I have a really big csv file with 10 comma seperated values in each line, at the end of each line is a \n.
Now I have a row with just semicolons. The amount of values corresponds to how many comma seperated values are in the other lines
5696;Neusser Strasse;49;1;50670;Neustadt-Nord;18.09.1990;um;1890;Wohn- u. Geschäftshaus
;;;;;;;;;
5698;Richard-Wagner-Strasse;18;1;50674;Neustadt-Süd;18.09.1990;;1905;Wohnhaus
When I now start to run my program, it gets the "5698" from the 3rd line as the last value of the 2nd line, so what I get is this:
0 Denkmalnummer: 5696
1 Strasse: Neusser Strasse
2 Nummer: 49
3 Bezirk: 1
4 PLZ: 50670
5 Ort: Neustadt-Nord
6 unter Schutz: 18.09.1990
7 Baujahr Zusatz: um
8 Baujahr: 1890
9 Kurzbezeichnung: Wohn- u. Geschäftshaus
****************
0 Denkmalnummer:
1 Strasse:
2 Nummer:
3 Bezirk:
4 PLZ:
5 Ort:
6 unter Schutz:
7 Baujahr Zusatz:
8 Baujahr:
9 Kurzbezeichnung: 5698
****************
0 Denkmalnummer: Richard-Wagner-Strasse
1 Strasse: 18
2 Nummer: 1
3 Bezirk: 50674
4 PLZ: Neustadt-S├╝d
5 Ort: 18.09.1990
6 unter Schutz:
7 Baujahr Zusatz: 1905
8 Baujahr: Wohnhaus
9 Kurzbezeichnung: 5699
This continues and messes up the proper alignment of the data.
My major code looks like this (via getline the file's data is stored in a vector):
if (denkmallist.is_open()) {
if (counter < 1) {
while (getline(denkmallist, line)) {
stringstream ss(line);
while (getline(ss, line, ';')) {
ausgelesenes.push_back(line);
counter++;
daten.push_back(ausgelesenes);
ausgelesenes.clear();
}
}
}
else{
while (getline(denkmallist, line)){
ausgelesenes.push_back(line);
}
daten.push_back(ausgelesenes);
ausgelesenes.clear();
}
}
and the code which then displays the results looks like this:
for(int x=0, y=semis; x<=semi2+2, y<daten.size(); x++, y++){
if (x > semi2-1){
x = 0;
cout << '\n' << "****************" << '\n' << endl;
}
cout << x << " " << daten[x][0] << ": " << daten[y][0] << endl;
}
Semi represents the amount of entires.
I would be very happy if someone could help me out :)
The inner loop uses the call to getline to decide when it has finished parsing the text string that was read by the outer call to getline. That's okay, but you have to watch out for extraneous failures.
For the first line, the inner loop runs ten times; once for each field that ends with a ; and once more to read the remaining text.
For the second line, there is no text after the last ;. After the ninth time through the loop, getline sees no text and no delimiter, so it concludes that it's at the end of the input. The call fails, and the inner loop exits after reading only nine inputs instead of the expected ten.

Reading numbers and strings from a file in C++

I know this question has been asked a lot, and I have gone through the most popular answer on stackoverflow.
I have a bunch of numbers in the following format:
4 // number of testcases
1 2 3 4 5 6 // Each line contains numbers for that particular testcase
1 4 5 6 7 8 9 19
12 3 5
1 4 9
The first line is the number of testcases. Each line following that contains numbers for that particular testcase.
I want to read line by line, process the numbers, output the solution and only then move to read to the second line.
In another stackoverflow question, the suggested solution is leading to a lot of duplication of data in the vector all_integers.
std::string line;
std::vector< std::vector<int> > all_integers;
while ( getline( std::cin, line ) ) {
std::istringstream is( line );
all_integers.push_back(
std::vector<int>( std::istream_iterator<int>(is),
std::istream_iterator<int>() ) );
for(auto it = all_integers.begin();it!=all_integers.end();it++) {
for(auto j = it->begin();j!=it->end();j++) {
cout << *j << " " ;
}
cout << endl;
}
What is the correct way of reading this from a file?
Follow up question:
In another file, I have input in the following format:
5 2
abc
bcd
eee
zyc
abv
abc bcd
zyc anv
The first line contains two numbers: m,n.
m : Number of words in the dictionary
n: Number of queries.
Then m number of words follow and last n lines read the number of queries that are to be made to it.
How can I read this efficiently? Is there any way to read the last K lines of a file efficiently in C++?

Storing file data variables in a dimentional array

I have a .txt file which I'm trying to gather data from, that can then be used within variables within my code to be used in other functions.
Here's an example of my text file:
0 10 a namez 1 0
0 11 b namea 1 1
1 12 c nameb 1 1
2 13 d namec 0 1
3 14 e named 1 1
So my file will not always be the same number of lines, but always the same number of variables per line.
I currently have this, to firstly get the length of the file and then change the amount of rows within the array:
int FileLength()
{
int linecount = 0;
string line;
ifstream WorkingFile("file.txt");
while(getline(WorkingFile, line))
{
++linecount;
}
return linecount;
}
int main()
{
string FileTable [FileLength()][6];
}
Firstly I don't know if the above code is correct or how I can add the values from my file into my FileTable array.
Once I have my FileTable array with all the file data in it, I then want to be able to use this in other functions.
I've been able to do:
if(FileTable[2][0] = 1)
{
cout << "The third name is: " << FileTable[2][3] << endl;
}
I understand my code may not make sense here but I hope it demonstrates what I'm attempting to do.
I have to do this for a larger text file and all the 6 variables per line relate to be input to a function.
Hold each line in its own object, this is much clearer:
struct Entry
{
std::array<std::string, 6> items; // or a vector
};
In main:
std::vector<Entry> file_table( FileLength() );
Note that it is a waste of time to read the whole file first in order to find the number of entries. You could just start with an empty vector, and push in each entry as you read it.
Your access code:
if( file_table.size() > 2 && file_table[2].items[0] == "1" )
{
cout << "The third name is: " << FileTable[2].items[2] << endl;
}
I would actually recommend giving the members of Entry names, instead of just having an array of 6 of them. That would make your code more readable. (Unless you really need to iterate over them, in which case you can use an enum for the indices).
You could define an operator[] overload for Entry if you don't like the .items bit.
since the number of lines is dynamic I suggest to use vector instead of array. you can push back your data to the vector line by line until you read eof.
also try to study about OOP a little , it would make your code more understandable.
take look at these:
http://www.cplusplus.com/reference/vector/vector/
http://www.geeksforgeeks.org/eof-and-feof-in-c/

Getting input from external files?

I need to get very basic input from an external file in C++. I tried searching the internet a few times but nothing really applied to what I need. This would be a .txt file that the input it coming from, and it would be filled with lines like this:
131
241
371
481
I have code already to manually get this input, and it looks like this:
using namespace std;
//Gets the initial values from the user.
int control=0;
while (rowb!=0){
cout << "Row: ";
cin >> rowb;
cout << "Column: ";
cin >> columnb;
cout << "Number: ";
cin >> numb;
row[control]=rowb-1;
column[control]=columnb-1;
num[control]=numb;
control++;
}
This is part of a program that solves sudoko boards. The inputed numbers are the initial values that a sudoko board holds, and the user is inputing the row, column, and number that comes from a board.
What I need is to be able to create a .txt file with these numbers stored in rows so that I do not have to enter so many numbers. I have very little idea how to go about doing this. Mainly I'll only be using the txt file for testing my program as I move along with adding more code to it. It takes 150+ entered numbers within my program just to get a single board, and it takes a lot of time. Any accidentally wrong entered value is also a huge problem as I have to start again. So how would I get C++ to read a text file and use those numbers as input?
Aside from the other suggestions, you can simply redirect a file to standard input, like so (where $ is the command prompt):
$ myprogram < mytextfile.txt
That will run myprogram just as normal but take input from mytextfile.txt as if you had typed it in. No need to adjust your own program at all.
(This works on both Unix/Linux systems and on Windows.)
You can open a file for input with std::ifstream from the header <fstream>, then read from it as you would from std::cin.
int main()
{
std::ifstream input("somefile.txt");
int a;
input >> a; // reads a number from somefile.txt
}
Obviously, you can use >> in a loop to read multiple numbers.
Create an std::ifstream object, and read from it just like you would from std::cin. At least if I understand what you're trying to do, the 131 as the first input is really intended to be three separate numbers (1, 3, and 1). If so, it's probably easiest to change your input file a bit to put a space between each:
1 3 1
2 4 1
3 7 1
4 8 1
Personally, I would start with a different format of the file: enter a value for each cell. That is, each row in the input file would represent a row in the sudoko board. Empty fields would use a space character. The immediate advantage is that the input actually pretty much looks like the sudoko board. Also, you would enter at most 90 characters: 9 characters for the board and a newline for each line:
#include <iostream>
#include <fstream>
#include <algorithm>
#include <iterator>
int main(int ac, char* av[])
{
std::ifstream in(ac == 1? "sudoko.init": av[1]);
char board[9][9];
for (int i(0); i != 9; ++i)
{
in.read(board[i], 9).ignore();
}
if (!in)
{
std::cout << "failed to read the initial board\n";
}
else
{
typedef std::ostream_iterator<char> iterator;
std::fill_n(iterator(std::cout << "board:\n\n+", "+"), 9, '=');
for (int i(0); i != 9; ++i)
{
std::copy(board[i] + 0, board[i] + 9, iterator(std::cout << "\n|", "|"));
std::fill_n(iterator(std::cout << "\n+", "+"), 9, (i + 1) % 3? '-': '=');
}
std::cout << "\n";
}
}
This would take input like this:
4 5 3 8
71 3
16 7
6 4 7
6 8
1 9 5
6 42
5 94
4 7 9 3
Note that each of these lines uses 9 characters. You might want to use something more visible like ..