I have a file which the first line reads ">FileName.txt". My goal is to read this line, and save "FileName.txt" to a variable called name. So I have:
ifstream file;
/* File opening stuff */
string line, name;
getline(file,line);
stringstream converter(line);
converter >> name;
This accomplishes saving ">FileName.txt" to the variable name, but I need to remove the '>' character. I am not sure if I should do that after this point, or if there is a way to skip over it entirely using the stringstream.
You can skip over it with the stream fairly easily:
char ch;
converter >> ch; // skip initial >
converter >> name; // now read the name
You can skip over it with the function ignore, add follow statement after stringstream converter(line); only need one line.
converter.ignore(line.length(), '>');
Related
I am new to C++ and I am reading in a text file. The content of text file is like:
$ (first line)
2 (second)
MY NAME IS (whatever sentence with 10 or below characters)(third)
12 21 (forth)
22 22 (fifth)
221 (sixth)
fly jump run (seventh)
fish animal (eighth)
So I need to read all of these and store them into different variables line by line and so far I'd manage to store them into string array line by line but how can I store the numbers like 12 21 in forth line into 2 different integer variables such as int b and int c?
and also like last two line
how can I store the fly jump run fish animal into 5 different string variables respectively?
Basically Now I am putting them into a string array line by line and trying to access them and take them out of the array and store it.
if (file.is_open()){
cout<<"Congratulations! Your file was successfully read!";
while (!file.eof()){
getline(file,line);
txt[i]=line;
i++;
}
}
Just want to store every line into variables based on their data type.
The streams support streaming the content directly into the basic data types (int, double etc.). So the istream::operator>>(int&) does the work for you.
The below small sample class demonstrates it by reading your sample file into the members -- hope that helps:
class Creature
{
public:
void read(istream& stream)
{
string line;
stream.ignore(10, '\n'); // skip line 1 (= $)
stream >> m_integers[0]; // line 2 = single int
stream.ignore(1, '\n'); // skip end of line
getline(stream, m_sentence); // get the full sentence line ..
// and the rest ... we can read that in a single code line ...
stream >> m_integers[1] >> m_integers[2] >> m_integers[3] >> m_integers[4]
>> m_integers[5] >> m_whatCanIdDo[0] >> m_whatCanIdDo[1] >> m_whatCanIdDo[2] >> m_whatIAm[0] >> m_whatIAm[1];
}
private:
string m_sentence;
int m_integers[6];
string m_whatCanIdDo[3];
string m_whatIAm[2];
};
Calling the function:
int main()
{
ifstream file;
file.open("creature.txt");
Creature cr;
cr.read(file);
file.close();
}
There are several ways of doing this, but one of the most straightforward is to use a stringstream.
To do this, copy the lines you want to tokenize from your txt array into a stringstream. Use the stream extratction operator (>>) to read out each word from that line, separated by a space, into a separate variable.
//Required headers
#include <string>
#include <sstream>
...
string word1, word2;
stringstream words(txt[lineNumber]);
words >> word1 >> word2;
//Process words
For each line you tokenize, you'll have to reset the stream.
//Read in next line
lineNumber++;
//Reset stream flags
words.clear();
//Replace the stream's input string
words.str(txt[lineNumber]);
words >> word1 >> word2;
//Process new words
You can use the same process for both integers and strings. The stream extraction operator will automatically convert strings to whatever data type you give it. However, it's up to you to make sure that the data it's trying to convert is the correct type. If you try to write a string to an int using a stringstream, the stringstream will set a fail bit and you won't get any useful output.
It's a good idea to write your input to a string, and then check whether that string is, in fact, a number, before trying to write it to an integer. But that's an entirely different topic, there are many ways to do it, and there are several other questions on this site that cover it.
I have managed to skip the name section when reading values from a file with name and value pairs. But is there another way to skip the name section without declaring a dummy string to store the skipped data?
Example text file: http://i.stack.imgur.com/94l1w.png
void loadConfigFile()
{
ifstream file(folder + "config.txt");
while (!file.eof())
{
file >> skip;
file >> screenMode;
if (screenMode == "on")
notFullScreen = 0;
else if (screenMode == "off")
notFullScreen = 1;
file >> skip;
file >> playerXPosMS;
file >> skip;
file >> playerYPosMS;
file >> skip;
file >> playerGForce;
}
file.close();
}
You can use std::cin.ignore to ignore input up to some specified delimiter (e.g., a new-line, to skip an entire line).
static const int max_line = 65536;
std::cin.ignore(max_line, '\n');
While many people recommend specifying a maximum of something like std::numeric_limits<std::streamsize>::max(), I do not. If the user accidentally points the program at the wrong file, they shouldn't wait while it consumes an inordinate amount of data before being told something's wrong.
Two other points.
Don't use while (!file.eof()). It mostly leads to problems. For a case like this, you really want to define a struct or class to hold your related values, define an operator>> for that class, then use while (file>>player_object) ...
The way you're reading right now really tries to read a "word" at a time, not a whole line. If you want to read a whole line, you probably want to use std::getline.
I have a file for example
M
4
2
//comments
.#..
It is given to the program via stdin. I can't use fstream, just iostream.
If I want to read the whole thing character by character could I do?
char first_letter, first_num, second_num;
cin >> first_letter;
cin >> first_num;
cin >> second_num;
Or would the end of the line mess up cin? As in, does cin know after it reads M for first_letter, that it needs to go to the end line?
Secondly I dont want to read the comment lines. My plan is that if I see a / I will use getline to "trash" the line then move to the . # . . and store those in my array. Would that be the best way to do that?
Firstly, streams skip whitespace (space, tabs, newlines) by default, so that part is easy.
Now, concerning the comment lines, this is a bit more complicated. You can use std::getline() to read one line. This will store the line in a string and discard the trailing newline. However, if you e.g. read the first letter in your code above, the newline remains in the stream, so getline() will read an empty string. In short, don't mix line-based and token-based input.
In practice, you read a line and either parse the it manually or you create a stream for that:
while(getline(in, line)) {
if(line.empty()) continue; // empty line
if(line[0] == '#') continue; // comment line
// parse line
std::stringstream s(line);
char c;
s >> c;
}
I have a variable
ifstream inFile("stuff.txt");
in the stuff.txt file there's a full sentance:
The quick brown fox jumps over the lazy dog
How do I put it into a char array with all the spaces?
char text[250];
inFile >> text;
gets me to the first space, nothing else.
Use ifstream::getline() to read into a char array or use std::getline() to read into a std::string. When you use inFile >> text whitespace will act as a delimiter, which is why it stops at the first space.
Using std::getline() to read into a std::string removes the requirement for specifying the maximum number of characters to read. This removes the potential for buffer overruns and avoids the added complexity of coping with partially read lines (if a line was > 250 in this case for example).
Always check the result of IO operations immediately:
std::ifstream inFile("stuff.txt");
if (inFile.is_open())
{
std::string line;
if (std::getline(inFile, line))
{
// Use 'line'.
}
}
while (!inFile.eof()) {
inFile >> text;
}
I am doing a homework assignment where we are to read company data from a file and then process it for errors.
What I have so far I think will work with the first line, but I'm not sure how to make it read each line after. Each line is a record with ID, name, and payments. Basically I want to know how I can skip to the next line after I've processed the first. I haven't included the error checking yet but I think it will be in the last do while loop after 1 record is read. If the information read into each variable is wrong I can check it and output it to either the summary file or error file.
void processFile()
{
string filename;
ifstream recordFile;
ofstream summary("summary.dat");
ofstream error("error.dat");
cout << "Please enter a filename\n";
do
{
cin >> filename;
recordFile.open(filename);
if (!recordFile.is_open())
cout << "No file by that name. Please enter another filename\n";
}
while(!recordFile.is_open());
int ID = 0;
string firstName;
string lastName;
double payment1, payment2, payment3 = (0.00, 0.00, 0.00);
string numberOfRecords;
getline(recordFile, numberOfRecords);
do
{
ws(recordFile);
recordFile >> ID;
recordFile >> firstName;
recordFile >> lastName;
recordFile >> payment1;
recordFile >> payment2;
recordFile >> payment3;
}
while(!recordFile.eof());
}
*edit : I found part of my problem, I actually need to skip the first line and read on from that point. The first line in each file has useless data in it.
Use the getline function on the ifstream object
Two things. The first is if you're going to have to read multiple
records, and each record is a new line, the best solution is almost
always to read line by line, using std::getline, and then use
std::istringstream to break up the line (record) into the desired
fields. This has the advantage of keeping your input synchronized, even
in case of errors; you don't have to worry about how much to skp ahead
or ignore.
The second point is that you're checking for eof(). This is almost
always an error; sometimes, it will lead you to reading one line too
many, and in other cases, of ignoring the last line or field. If the
input is successful (and you can only check for end of file after
trying to input beyond it), the stream will behave as true in a
conditional context; if not, it will behave as false. So your loop
should be:
std::string line;
while ( std::getline( recordFile, line ) ) {
std::istringstream record( line );
record >> ID;
if ( ! record ) ...
// ...
}
And one final comment: all of the >> operators strip leading spaces,
so you don't need your call to ws. On the other hand, with the above
schema, you might want to do something like:
if ( record >> ws && record.get() != EOF ) {
// Unexpected garbage at end of line...
}
at the very end of your loop, to verify that there isn't extra text.