I have a data file with a lot of columns of doubles but I want to read only two of them with a while loop
double x, y;
ifstream in;
double foo;
while( in >> foo ) {
in >> foo;
in >> foo;
...
in >> x;
in >> y;
... something with x and y
}
Two questions
1) There is a way to do the same thing without a fake double foo?
2) there is a way to do that without repeat in >> foo (or a for loop) like stream to the n° whitespace with a one-line code? There is a built-in function to skip to the n° whitespace?
What I would suggest instead is to read an entire row in a string and use a stringstream to manipulate it or just use something like find_last_of functions from the string class itself to pick out the last two columns and then convert it back to a double.
Related
Something like this..
do{
int x{};
std::cin >> x;
}while(/*i want the condition mentioned here*/);
I mean, if the user input x and press Enter, I want the loop to end.
Can I do that?
The most common method is to read an entire line and then extract data from that line.
That is, a change of perspective from "read things until you encounter a newline character" to the slightly higher-level "read all the things on the line".
std::string line;
if (std::getline(std::cin, line))
{
std::stringstream ls(line);
int x = 0;
while (ls >> x)
{
// Process x
}
}
I'm working on an assignment with equations, but I can't figure out how to input the different parts of the equation.
The equation is always formatted:
[double][x/y/z][sign][double][x/y/z][sign][double][x/y/z]=[double].
An example: 2.5y+4.7x+7z=46
To accomplish this, I tried using four double variables and six character variables.
double a,d,g,j;
char b,c,e,f,h,i;
so that the equation splits into the variables a b c d e f g h i, which I can then manipulate.
If there were whitespaces anywhere in the equation, I could have used istringstream to split them, but there aren't. I am not allowed to change the input file.
How can I put the numbers in doubles, and the letters/symbols in characters?
You can use istringstream and out of stream operator.
For example:
std::istringstream iss("2.5y+4.7x+7z=46");
double a,b,c,s;
char v1,v2,v3;
iss >> a; // read 1st koef
iss >> v1; // read 1st var's name
iss >> b; // read 2nd koef
iss >> v2; // read 2nd var's name
iss >> c; // read 3rd koef
iss >> v3; // read 3rd var's name
iss.ignore(); // skip '=' symbol
iss >> s; // read sum
Signs in equation is sign of relevant koefs.
I process some data with data in columns like,
1 -0.004002415458937208 0.0035676328502415523
2 -0.004002415796209478 0.0035676331876702957
....
I am only interested in the last two values. I usually find it convenient to read the values as:
std::ifstream file(file_name);
double a, b;
for (lines) {
// | throwing away the first value by reading it to `a`
file >> a >> a >> b;
store(a, b);
}
I'm not sure how readable this is for others, and it might be thought of as an error when the structure of the data is not known. Could I somehow make it look more explicit that I really want to throw away the first read value?
I wanted something in the line of this, but nothing worked:
file >> double() >> a >> b; // I hoped I could create some r-value kind of thing and discard the data in there
file >> NULL >> a >> b;
If you don't want to create a variable explicitly to be ignored, and you feel explicitly ignoring the value with calls to manipulate the stream are too verbose, you could take advantage of the operator>> overload for std::istream that takes a std::istream&(*)(std::istream&) function pointer:
template <typename CharT>
std::basic_istream<CharT>& ignore(std::basic_istream<CharT>& in){
std::string ignoredValue;
return in >> ignoredValue;
}
to be used like:
std::cin >> ignore >> a >> b;
and if you wanted to verify that it was of a form that could be read into a type you could supply an additional template argument specifying the type of ignored value:
// default arguments to allow use of ignore without explicit type
template <typename T = std::string, typename CharT = char>
std::basic_istream<CharT>& ignore(std::basic_istream<CharT>& in){
T ignoredValue;
return in >> ignoredValue;
}
to be used like:
std::cin >> ignore >> a >> b;
// and
std::cin >> ignore<int> >> a >> b;
demo on coliru
You can use std::istream::ignore.
E.g.:
file.ignore(std::numeric_limits<std::streamsize>::max(), ' '); //columns are separated with space so passing it as the delimiter.
file >> a >> b;
You can use file::ignore(255, ' ') to ignore characters until the next space.
std::ifstream file(file_name);
double a, b;
for (lines) {
// skip first value until space
file.ignore(255, ' ');
file >> a >> b;
store(a, b);
}
or you can use an auxiliary variable to store the first value:
std::ifstream file(file_name);
double aux, a, b;
for (lines) {
// skip first value
file >> aux >> a >> b;
store(a, b);
}
ifstream has nice tools for parsing files, such as << which work in loops and can consume floats, ints, or whatever you want into variables (as long as your variable types match what you are trying to consume with <<. I want to know if, instead of:
ifstream myReadFile;
myReadFile.open(some_file); // open the file
float x;
int y;
// some_file = "0.5 5"
myReadFile >> x >> y;
If I can somehow get a string object that is identical to some_file into ifstream. What I want to do is:
ifstream myReadFile;
myReadFile = my_string
...
Essentially parsing files is easy with ifstreams but parsing strings in c++ is a PITA (compared to say, Python).
Use std::stringstream:
// Initialize contents of the stream with your string
std::stringstream myReadString(my_string);
float x;
int y;
// Use the stream just like an fstream
// my_string = "0.5 5"
myReadString >> x >> y;
erm, you might want to look at stringstream.
A little background: I am working on a sliding block puzzle for a school project and this is our first using C++ instead of Java. This is the first time I have had to implement something that reads data from a file.
I have a simple question regarding reading input from a text file.
I understand how to read the file line by line and hold each line in a string, I want to know if I can parse the string into different data types as the file is read.
Currently I am reading each line and storing them as strings in a vector for parsing later, and I know there must be a much simpler way to implement this
The first line holds 2 integers which will indicate the length and width of the grid, the following lines will have 4 integers and a char for use as arguments when creating the blocks.
My question is this, if I read the file character by character instead, is there a function I can use that will detect if the character is an integer or a char (and ignore the spaces) so I can store them immediately and create the block objects as the file is read? How would i deal with integers >10 in this case?
EDIT: Just noting I am using fstream to read the files, I am unfamiliar with other input methods
A sample input:
4 4
3 1 2 1 b
1 1 1 1 a
To detect whether a piece of string can be parsed as an integer, you just have to parse it and see if you succeed. The best function for that would probably be std::strtoul(), since it can be made to tell you how many characters it consumed, so that you can continue parsing after that. (See the man page for details.)
However, if you already know the format of your file, you can use iostream formatted extraction. This is quite straightforward:
#include <fstream>
std::ifstream infile("thefile.txt");
int n1, n2, x1, x2, x3, x4;
char c;
if (!(infile >> n1 >> n2)) { /* error, could not read first line! Abort. */ }
while (infile >> x1 >> x2 >> x3 >> x4 >> c)
{
// successfully extracted one line, data is in x1, ..., x4, c.
}
Another alternative is to read every line into a string (using std::getline), then creating a stringstream from that line, and parsing the stringstream with >>. This has the added benefit that you can discover and skip bad lines and recover, while in the direct formatted extraction I presented above, you cannot recover from any error.
If you can assert each type, I suggest using stream operators, like you would with cin.
#include <fstream>
using namespace std;
int main()
{
fstream fileStream;
fileStream.open("inputfile.txt");
int firstNumber;
fileStream >> firstNumber;
char firstChar;
fileStream >> firstChar;
}
This way, you can read by value, instead of reading by line and then parsing the line. Just read in every value you need into a variable, as you discover you need it, like that.
I would read each line into a string (as you have been doing).
Then I would read the tokens from that line into the appropriate variables.
The operator>> when applied to a stream will convert the next value in a stream into the correct type. If this is not possable it sets flags on the stream indicating failure that are easy to test.
int x;
stream >> x; // ignores white space then: reads an integer from the stream into x
char c;
stream >> c; // ignores white space then: reads an char from the stream into c
double d;
stream >> d; // ignores white space then: reads an double from the stream into d
Assuming your input:
4 4
3 1 2 1 b
1 1 1 1 a
Not knowing what the the values mean I will put my assumptions in comments.
// Assume that stream is a std::fstream already opened to you file.
std::string line1;
std::getline(stream, line1); // reads "4 4" into `line1`
std::stringstream line1stream(line1); // convert line1 into a stream for reading.
int a;
int b;
line1stream >> a >> b; // reads "4 4" from 'line1' into a (now 4) b (now 4)
if (!stream || !line1stream)
{
// failed reading the first line.
// either reading the line failed (!stream)
// or reading 2 integers from line1stream failed (!line1stream)
throw SomeException("Failed");
}
std::string line2;
std::getline(stream, line2); // reads "3 1 2 1 b" into line2
std::stringstream line2stream(line2); // convers line2 into a stream for reading.
int data[4];
char c;
line2stream >> data[0] >> data[1] >> data[2] >> data[3] >> c;
if (!stream || !line2stream)
{
// failed reading the second line.
// either reading the line failed (!stream)
// or reading 4 integers and one char from line2stream failed (!line2stream)
throw SomeException("Failed");
}
ifstreams are also istreams, so you can use the same operator >> as with std::cin.
int main()
{
std::ifstream s("test.txt");
if (s.is_open())
{
int i, j, k;
s >> i >> j >> k;
}
}
Note that this is way not the fastest way of parsing, but that is probably irrelevant to you.