C++ detect space in text file - c++

How can I go about detecting a space OR another specific character/symbol in one line of a file using the fstream library?
For example, the text file would look like this:
Dog Rover
Cat Whiskers
Pig Snort
I need the first word to go into one variable, and the second word to go into another separate variable. This should happen for every line in the text file.
Any suggestions?

This is pretty simple.
string a;
string b;
ifstream fin("bob.txt");
fin >> a;
fin >> b;
If that's not quite what you want, please elaborate your question.
Perhaps a better way overall is to use a vector of strings...
vector<string> v;
string tmp;
ifstream fin("bob.txt");
while(fin >> tmp)
v.push_back(tmp);
This will give you a vector v that holds all the words in your file.

Related

How can we take out the multiple integer numbers in the string array or string and assign them to different int data type?

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.

How to read string and corresponding int from a file in C++?

I am working on a two-part project for a class, and have finished the first section but have run into trouble on the second part. For the first part, I was able to read a list from a file and into a vector to manipulate with various functions. A list from this section would look like:
banana
apple
pineapple
grapefruit
orange
pear
grape
lime
lemon
Which I was able to complete. For this first part, I simply have a vector of strings. However, the second part introduces a quantity to these values. The list for this section would follow as:
foo 5
bar 4
baz 2
boz 1
foo 3
At this point, I'm not sure how to read for item as a string and a corresponding int which follows it. For items that are repeated, they're supposed to be add to the original value for that item. I was planning on having a vector of objects which had a name and a quantity to manipulate but I need to read the file first. Thanks for any help!
This is how I was originally reading the file
if (fileIn.is_open()){
//file opened successfully so we are here
ifstream inf(fileName + ".txt");
string word;
while (inf >> word)
{
currentSet.push_back(word);
}
Just do something like:
map<string, int> vals; //or some other data structure
ifstream ifs(somefile);
string word;
int i;
while(ifs >> word >> i) {
vals[word] += i;
}
Simply read them one after the other. Of course you can add error checking as you want. But I recommend the map data structure for easy access and manipulation.

Reading / Writing Files for a calculator: atof error

I currently have a text file that is as follows:
12 6 4 9
It is a very simple text file since I want to just get one line working and then maybe expand to multiple lines later. Extra aside: this is for a RPN calculator I am working on.
I want to go through this text file character by character. The way I currently have it implemented is with a simple while loop:
string line;
while (!infile.eof()){
getline(infile, line);
if (isdigit(line[0])){
rpn_stack.push_back(atof(line.c_str()));
}
}
rpn_stack is a vector since I will not be using the built in stack libraries in C++.
The problem I am currently having is that the output is just outputting "12". Why is this?
Is there a way that I can traverse through the file character by character instead of reading as a line? Is it breaking because it finds a white space (would that be considered the EOF)?
EDIT:
The code has been rewritten to be as the following:
string line;
while (!infile.eof()){
getline(infile, line);
for (int i = 0; i < line.size(); i++){
if (isdigit(line[i])){
rpn_stack.push_back(atof(line.c_str()));
}
}
}
The output is 12 5 different times, which is obviously wrong. Not only are there 4 items in the txt document, but only one of them is a 12. Can someone give some insight?
This will read as many doubles from infile as possible (i.e. until the end of file or until it comes across a token that isn't a double), separated by whitespace.
for (double d; infile >> d;)
rpn_stack.push_back(d);
If you need parse line-by-line, as #ooga says you will need a two-stage reader that looks something like this:
for (std::string line; getline(infile, line);) {
std::istringstream stream{line};
for (double d; stream >> d;)
rpn_stack.push_back(d);
}
Bonus hint: don't use .eof()

What's the correct way to read a text file in C++?

I need to make a program in C++ that must read and write text files line by line with an specific format, but the problem is that in my PC I work in Windows, and in College they have Linux and I am having problems because of line endings are different in these OS.
I am new to C++ and don't know could I make my program able read the files no matter if they were written in Linux or Windows. Can anybody give me some hints? thanks!
The input is like this:
James White 34 45.5 10 black
Miguel Chavez 29 48.7 9 red
David McGuire 31 45.8 10 blue
Each line being a record of a struct of 6 variables.
Using the std::getline overload without the last (i.e. delimiter) parameter should take care of the end-of-line conversions automatically:
std::ifstream in("TheFile.txt");
std::string line;
while (std::getline(in, line)) {
// Do something with 'line'.
}
Here's a simple way to strip string of an extra "\r":
std::ifstream in("TheFile.txt");
std::string line;
std::getline(input, line));
if (line[line.size() - 1] == '\r')
line.resize(line.size() - 1);
If you can already read the files, just check for all of the newline characters like "\n" and "\r". I'm pretty sure that linux uses "\r\n" as the newline character.
You can read this page: http://en.wikipedia.org/wiki/Newline
and here is a list of all the ascii codes including the newline characters:
http://www.asciitable.com/
Edit: Linux uses "\n", Windows uses "\r\n", Mac uses "\r". Thanks to Seth Carnegie
Since the result will be CR LF, I would add something like the following to consume the extras if they exist. So once your have read you record call this before trying to read the next.
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
If you know the number of values you are going to read for each record you could simply use the ">>" method. For example:
fstream f("input.txt" std::ios::in);
string tempStr;
double tempVal;
for (number of records) {
// read the first name
f >> tempStr;
// read the last name
f >> tempStr;
// read the number
f >> tempVal;
// and so on.
}
Shouldn't that suffice ?
Hi I will give you the answer in stages. Please go trough in order to understand the code.
Stage 1: Design our program:
Our program based on the requirements should...:
...include a definition of a data type that would hold the data. i.e. our
structure of 6 variables.
...provide user interaction i.e. the user should be able to
provide the program, the file name and its location.
...be able to
open the chosen file.
...be able to read the file data and
write/save them into our structure.
...be able to close the file
after the data is read.
...be able to print out of the saved data.
Usually you should split your code into functions representing the above.
Stage 2: Create an array of the chosen structure to hold the data
...
#define MAX 10
...
strPersonData sTextData[MAX];
...
Stage 3: Enable user to give in both the file location and its name:
.......
string sFileName;
cout << "Enter a file name: ";
getline(cin,sFileName);
ifstream inFile(sFileName.c_str(),ios::in);
.....
->Note 1 for stage 3. The accepted format provided then by the user should be:
c:\\SomeFolder\\someTextFile.txt
We use two \ backslashes instead of one \, because we wish it to be treated as literal backslash.
->Note 2 for stage 3. We use ifstream i.e. input file stream because we want to read data from file. This
is expecting the file name as c-type string instead of a c++ string. For this reason we use:
..sFileName.c_str()..
Stage 4: Read all data of the chosen file:
...
while (!inFile.eof()) { //we loop while there is still data in the file to read
...
}
...
So finally the code is as follows:
#include <iostream>
#include <fstream>
#include <cstring>
#define MAX 10
using namespace std;
int main()
{
string sFileName;
struct strPersonData {
char c1stName[25];
char c2ndName[30];
int iAge;
double dSomeData1; //i had no idea what the next 2 numbers represent in your code :D
int iSomeDate2;
char cColor[20]; //i dont remember the lenghts of the different colors.. :D
};
strPersonData sTextData[MAX];
cout << "Enter a file name: ";
getline(cin,sFileName);
ifstream inFile(sFileName.c_str(),ios::in);
int i=0;
while (!inFile.eof()) { //loop while there is still data in the file
inFile >>sTextData[i].c1stName>>sTextData[i].c2ndName>>sTextData[i].iAge
>>sTextData[i].dSomeData1>>sTextData[i].iSomeDate2>>sTextData[i].cColor;
++i;
}
inFile.close();
cout << "Reading the file finished. See it yourself: \n"<< endl;
for (int j=0;j<i;j++) {
cout<<sTextData[j].c1stName<<"\t"<<sTextData[j].c2ndName
<<"\t"<<sTextData[j].iAge<<"\t"<<sTextData[j].dSomeData1
<<"\t"<<sTextData[j].iSomeDate2<<"\t"<<sTextData[j].cColor<<endl;
}
return 0;
}
I am going to give you some exercises now :D :D
1) In the last loop:
for (int j=0;j<i;j++) {
cout<<sTextData[j].c1stName<<"\t"<<sTextData[j].c2ndName
<<"\t"<<sTextData[j].iAge<<"\t"<<sTextData[j].dSomeData1
<<"\t"<<sTextData[j].iSomeDate2<<"\t"<<sTextData[j].cColor<<endl;}
Why do I use variable i instead of lets say MAX???
2) Could u change the program based on stage 1 on sth like:
int main(){
function1()
function2()
...
functionX()
...return 0;
}
I hope i helped...

How to construct a parser for an input file

can i please get some guidance to constructing a parser for an input file, I've been looking for a help for weeks, the assignment is already past due, I would just like to know how to do it.
The commented code is what I've tried, but i have a feeling it is more serious than that. I have a text file and I want to parse it to count the number of times that words appear in the document.
Parser::Parser(string filename) {
//ifstream.open(filename);
// source (filename, fstream::in | fstream::out);
}
The commented code is what I've tried, but i have a feeling it is more serious than that.
I have a feeling you haven't tried a thing. So I am going to do the same.
Google is your friend.
To read a word:
std::ifstream file("FileName");
std::string word;
file >> word; // reads one word from a file.
// Testing a word:
if (word == "Floccinaucinihilipilification")
{
++count;
}
// Count multiple words
std::map<std::string, int> count;
// read a word
++count[word];
// To read many words from a file:
std::string word;
while(file >> word)
{
// You have now read a word from a file
}
Note: That is a real word :-)
http://dictionary.reference.com/browse/floccinaucinihilipilification
Take a look at the answers in How do you read a word in from a file in C++? . The easiest way is to use an ifstream and operator>> to read single words. You can then use a standard container like vector (as mentioned in the link above) or map<string, int> to remember the actual count.