I am trying to do file read by column. Main function is that my file should be show one of columns all values.
I am trying to do it with vectors.
void search(){
const int COLUMNS = 4;
vector< vector <int> > data;
string filename = "bla.txt";
ifstream ifile(filename.c_str());
if (ifile.is_open()) {
int num;
vector <int> numbers_in_line;
while (ifile >> num) {
numbers_in_line.push_back(num);
if (numbers_in_line.size() == COLUMNS) {
data.push_back(numbers_in_line);
numbers_in_line.clear();
}
}
}
else {
cerr << "There was an error opening the input file!\n";
exit(1);
}
//now get the column from the 2d vector:
vector <int> column;
int col = 2;//example: the 2nd column
for (int i = 0; i < data.size(); ++i) {
column.push_back(data[i][col - 1]);
cout << column[i] << endl;
}
ifile.close();
}
my file looks like:
John 1990 1.90 1
Peter 1980 1.88 0
...
This code compiles, but I am not getting any value shown in console. When I try to debug last line it wont get cached, so I guess they do nothing?
while (ifile >> num) {
The loop is never entered because num is an int and the first element of the input line is John, which cannot be interpreted as an int, so ifile is set to an error state and the loop condition is immediately false.
The clean fix is to first read the entire line with std::getline and then tokenise the resulting std::string, for example with an std::istringstream.
Individual std::string tokens resulting from that tokenisation can then be converted to appropriate types with functions like std::stoi.
Do step by step and make sure each step is correct.
Read each line, then print out to make sure you are doing it correctly.
You need to split each line. After this step, you will have John, 1990 etc as strings. My favorite split method
Now convert 2-4th columns into integers.
There are good solutions for each step that you can easily find.
Related
I am trying to read text file line by line and then read each column as vector but when i am tryin to cout first column it shows zeros i.e. not reading the file correctly.
int main(void)
{
ifstream myfile ("data1.txt");
string line;
if (myfile.is_open())
{
int ln=1;
while ( getline (myfile,line) )
{
if(ln==1){ln++; continue;}
istringstream iss(line);
string word;
vector<double> column;
int w=1;
while(iss >> word)
{
//double dw=atof(Form("%s",word));
column.push_back(atof(Form("%s",word)));
cout<<column[0];
w++;
}
ln++;
cout<<"\n";
}
myfile.close();
}
//else
else cout<<"Unable to open file";
cout<<"\n";
return ;
}enter code here
push_back appends an element as last element of the vector while columns[0] always refers to the first element of the vector.
Is the first element 0
Is there another problem?
(Please explain what is Form, give an example of input file and output in the command line)
First of all learn how to indent and consistently use some scheme for inserting blank lines that makes sense. When you do that you can read your own code and figure out if it is doing what you think it is.
Second. Save Form("%s",word) in a string ( for now call it form_string) add this line cout<<"form returns "<<form_string<<endl; 99.99% probably it will print zeros.
Finally change: cout<<column[0]; to cout<<column[0]<<" "; or cout<<*(column.rbegin())<<" ";. The latter prints out all the values that you read, the former prints out the first value you read over and over.
This may be a very simplistic question, but I have not found any examples to guide me. I am trying to write class in C++ that can read a text file where columns of data (float, char, int, etc...) are separated by spaces. I would like the class to be able to ignore some columns and read in specified columns. For now I am experimenting with one and two column formats and progressing from there. A brief example of a test input file is listed below.
103.816
43.984
2214.5
321.5
615.8
8.186
37.6
My first attempt at writing a code to read in one column of data is trivial and looks like this.
void Read_Columnar_File::Read_File(const std::string& file_name)
{
int i;
std::ifstream inp(file_name,std::ios::in | std::ios::binary);
if(inp.is_open()) {
std::istream_iterator<float> start((inp)), end;
std::vector<float> values(start,end);
for(i=0; i < 7; i++) std::cout << values[i] << std::endl;
}
else std::cout << "Cannot Open " << file_name << std::endl;
inp.close();
}
In my next attempt I am trying to read in only one column of a two column format like the input shown below. The numbers are just made up for this example
103.816 34.18
43.984 21.564
2214.5 18.5
321.5 1.00
615.8 4.28
8.186 1.69
37.6 35.48
I modified the code format slightly to look like the example below. I am using a brief but of pseudocode after the inp >> statement to illustrate that I am trying to get the code to skip to the next line after reading in the first column. my question is "How do I get the code to just read the first column and then skip to the next line where again it just reads the first column of data and make it keep doing this until the end of file?" And thank you in advance for any advice that you can give.
void Read_Columnar_File::Read_File(const std::string& file_name)
{
int i;
float input;
std::vector<float> values;
std::ifstream inp(file_name,std::ios::in | std::ios::binary);
if(inp.is_open()) {
for(i=0; i < 7; i++) {
inp >> input >> \\ - At this point I want the code to skip to the next
\\ line of the input file to only read the first column
\\ of data
values.push_back(input);
}
for(i=0; i < 7; i++) std::cout << values[i] << std::endl;
}
else std::cout << "Cannot Open " << file_name << std::endl;
inp.close();
}
You can use the member function ignore() to discard all the characters until the next line. I would also fix up your code to use a for() loop predicated on the success of the extraction so your code will work for any number of columns, not just 7:
for (float input; inp >> input; values.push_back(input))
{
inp.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
When you want to read only part of a line, and skip the rest of that line, one easy starting point is to:
read the entire line into a string
put the whole string into an istringstream
Parse out the parts you care about
Repeat
As a rule, I generally find this easier to generalize than ones that alternate between reading and ignoring data as it's being read from the file.
this is from the google practice problem, https://code.google.com/codejam/contest/32014/dashboard#s=p1, and
I'm just having a little bit of problem with reading the input.
The input has the form
3
jam google foo code bar
20 15 40 30 60
foo bar
3 2
code jam
3 2
where the first integer is the number of cases, and each case consists of two lines. The first line contains the list of products, space separated, and second line contains your initial guesses for each product in the list, respectively.
For each case, I want to get the first line as a vector of strings, and second line as a
vector of integers, and the code I came up with is the following: (made modifications using the comment)
ifstream inFile;
inFile.open("B-small-practice.in");
ofstream outFile;
outFile.open("B-small-practice.out");
inFile >> numCase;
inFile.ignore();
for (i = 0; i < numCase; i++) {
vector<string> v1;
vector<int> v2;
getline(inFile, a);
getline(inFile, b);
stringstream aa(a);
stringstream bb(b);
j = 0;
while (aa >> c) {
v1.push_back(c);
if (aa.peek() == ' ')
aa.ignore();
j++;
}
while (bb >> d) {
v2.push_back(d);
if (bb.peek() == ' ')
bb.ignore();
}
}
(all the variables are defined)
However, this code terminates after throwing an error "out of range," and I'm not sure because I thought my code was within the range.
Is there a way of fixing this? Or is there something wrong with my code?
I've been trying to retrieve saved data from a text file. The data stored are both numbers, separated by a ~. I've managed to get it to print out one of the lines (the top line) however I've been unable to figure out how to proceed through the entire file.
There are only two numbers (integers) on each line, an X and Y position of another vector. The idea is to assign each integer to the respective variable in the vectors. I've not managed to get that far since I can't get it to go past line 1. But I'd thought that by having an array size of 2, and the array temporarily stores the value, assigns it to the vector, then overwrites it with the next value(s) that could work. But again not managed to get that far.
Below is the code I've been trying to use;
........
string loadZombieData;
loadFile >> loadZombieData; //Data gets read from the file and placed in the string
vector<string> result; //Stores result of each split value as a string
stringstream data(loadZombieData);
string line;
while(getline(data,line,'~'))
{
result.push_back(line);
}
for(int i = 0; i < result.size(); i++){
cout << result[i] << " ";
}
.......
Just to clarify, this is not my code, this is some code I found on Stackoverflow, so I'm not entirely certain how it all works yet. As I said, I've been trying to get it to read multiple lines, then using the for loop was going to assign the results to the other vector variables as needed. Any help is appreciated :)
Use two while loops:
std::vector<std::string> result;
std::vector<int> numbers;
std::string filename;
std::ifstream ifile(filename.c_str());
if (!ifile.is_open()) {
std::cerr << "Input file not opened! Something went wrong!" << std::endl;
exit(0);
}
std::string temp;
//loop over the file using newlines as your delimiter
while (std::getline(ifile, temp, '\n')) {
//now temp has the information of each line.
//create a stringstream initialized with this information:
std::istringstream iss(temp);//this contains the information of ONE line
//now loop over the string stream object as you would have in your code sample:
while(getline(iss, temp,'~'))
{
//at this point temp is the value of a token, but it is a string
result.push_back(temp); //note: this only stores the TOKENS as strings
//so to store the token as a int or float, you need to convert it to that
//via another stringstream:
std::istringstream ss(temp);
//if your number type is float, change it here as well as in the vector
//initialization of `numbers`:
int num = 0;
//this checks the stream to ensure that conversion occurred.
//if it did, store the number, otherwise, handle the error (quit - but, this is up to you)
//if stringstreams aren't your cup of tea, try some others (refer to this link):
//http://stackoverflow.com/questions/21807658/check-if-the-input-is-a-number-or-string-c/21807705#21807705
if (!(ss >> num).fail()) {
numbers.push_back(num);
}
else {
std::cerr << "There was a problem converting the string to an integer!" << std::endl;
}
}
}
Note: this version stores the numbers verbatim: i.e. without a sense of how many numbers were on a line. However, that is reconcilable as all you have to do is output n numbers per line. In your case, you know every 2 numbers will be represent the numbers in a line.
This requires:
#include <string>
#include <vector>
#include <cstdlib>
#include <sstream>
int exam1[100];// array that can hold 100 numbers for 1st column
int exam2[100];// array that can hold 100 numbers for 2nd column
int exam3[100];// array that can hold 100 numbers for 3rd column
int main()
{
ifstream infile;
int num;
infile.open("example.txt");// file containing numbers in 3 columns
if(infile.fail()) // checks to see if file opended
{
cout << "error" << endl;
}
while(!infile.eof()) // reads file to end of line
{
for(i=0;i<100;i++); // array numbers less than 100
{
while(infile >> [exam]); // while reading get 1st array or element
???// how will i go read the next number
infile >> num;
}
}
infile.close();
}
int exam1[100];// array that can hold 100 numbers for 1st column
int exam2[100];// array that can hold 100 numbers for 2nd column
int exam3[100];// array that can hold 100 numbers for 3rd column
int main() // int main NOT void main
{
ifstream infile;
int num = 0; // num must start at 0
infile.open("example.txt");// file containing numbers in 3 columns
if(infile.fail()) // checks to see if file opended
{
cout << "error" << endl;
return 1; // no point continuing if the file didn't open...
}
while(!infile.eof()) // reads file to end of *file*, not line
{
infile >> exam1[num]; // read first column number
infile >> exam2[num]; // read second column number
infile >> exam3[num]; // read third column number
++num; // go to the next number
// you can also do it on the same line like this:
// infile >> exam1[num] >> exam2[num] >> exam3[num]; ++num;
}
infile.close();
return 0; // everything went right.
}
I assume you always have 3 numbers per line. If you know the exact number of lines, replace the while with a for from 0 to the number of lines.
Rule # 1 about reading data from a file: don't trust the contents of the file. You never know with absolute certainty what is in the file until you've read it
That said, one correct way to read lines of data from a file, where each line is composed of multiple whitespace-delimited fields would be to use a combination of getline and stringstream:
std::string line;
while (std::getline(infile, line))
{
std::stringstream ss(line);
int a, b, c;
if (ss >> a >> b >> c)
{
// Add a, b, and c to their respective arrays
}
}
In English, we get each line from the file stream using getline, then parse the line into three integers using a stringstream. This allows us to be certain that each line is formatted correctly.
We check to ensure the extraction of the integers succeeded before we add them to the arrays to ensure that the arrays always have only valid data.
There is other error handling that might be desirable:
In the example, if extraction of the integers from the line fails, we just ignore that line; it could be a good idea to add logic to abort the process or report an error.
After we get three integers, we ignore the rest of the line; it might be a good idea to add checks to ensure that there is no more data on the line after the required integers, depending on how strict the file's formatting needs to be.
After we finish reading the file, we should test to be sure eof() is set and not fail() or bad(); if one of those two flags is set, some error occurred when reading the file.