I writing a C++ program that needs to be able to read from a .txt file, and parse the input in order to be able to get commands and arguments from each line.
Say I have Animals.txt
A cat1 3
A dog1 4
A cat2 1
D cat1
I want to be able to take this file, and then create a set of if statements for the first letter, so that I can call a function in the main class that corresponds to the first letter, and pass the rest of the line in as arguments.
An exmaple of what i'm trying to do:
if(line[0].compare("A")==0){
add(line[1],line[2]);
}
if(line[0].compare("D")==0){
delete(line[1])
}
I've tried to use strtok and the stringstream classes, but either I dont know how to implement the for my needs or they do not work for my needs as values are being put in line[0] that are not at the beginning of the lines of the text file.
Any help would be much appreciated.
First you need std::ifstream to open the file. Then you need std::getline to extract lines from the file:
std::ifstream file("Animals.txt");
std::string line;
while (std::getline(file, line)) {
// ...
}
Then inside the while loop, stick the line in a std::stringstream and extract the values you need:
std::stringstream ss(line);
char letter;
ss >> letter;
// And so on...
For a char you can do simple == comparison in your if statements:
if (letter == 'A') {
// ...
}
If you extract the letter into a std::string, just make sure you compare against "A".
I'll let you plug it all together and figure out the rest.
Create a istringstream object to split each line:
std::istringstream line(my_line);
std::string line0;
std::string line1;
std::string line2;
line >> token;
if (line0 == "A") {
line >> line1 >> line2;
add(line1, line2);
} else if (line0 == "D") {
line >> line1;
remove(line1);
}
Related
I am trying to read through a text file that can possibly look like below.
HI bye
goodbye
foo bar
boy girl
one two three
I am trying to take the lines with only two words and store them in a map, the first word would be the key and second word would be the value.
below is the code I came up with but I can't figure out how to ignore the lines that do not have two words on them.
this only works properly if every line has two words. I understand why this is only working if every line has two words but, I'm not sure what condition I can add to prevent this.
pair myPair;
map myMap;
while(getline(file2, line, '\0'))
{
stringstream ss(line);
string word;
while(!ss.eof())
{
ss >> word;
myPair.first = word;
ss >> word;
myPair.second = word;
myMap.insert(myPair);
}
}
map<string, string>::iterator it=myMap.begin();
for(it=myMap.begin(); it != myMap.end(); it++)
{
cout<<it->first<<" "<<it->second<<endl;
}
Read two words into a temporary pair. If you can't, do not add the pair to the map. If you can read two words, see if you can read a third word. If you can, you have too many words on the line. Do not add.
Example:
while(getline(file2, line, '\0'))
{
stringstream ss(line);
pair<string,string> myPair;
string junk;
if (ss >> myPair.first >> myPair.second && !(ss >> junk))
{ // successfully read into pair, but not into a third junk variable
myMap.insert(myPair);
}
}
let me suggest a little different implementation
std::string line;
while (std::getline(infile, line)) {
// Vector of string to save tokens
vector <string> tokens;
// stringstream class check1
stringstream check1(line);
string intermediate;
// Tokenizing w.r.t. space ' '
while(getline(check1, intermediate, ' ')) {
tokens.push_back(intermediate);
}
if (tokens.size() == 2) {
// your condition of 2 words in a line apply
// process 1. and 2. item of vector here
}
}
You can use fscanf for take input from file and sscanf for take input from string with format. sscanf return how many input successfully take with given format. so you can easily check, how many word have a line.
#include<stdio.h>
#include<stdlib.h>
#include <iostream>
using namespace std;
int main()
{
char line[100];
FILE *fp = fopen("inp.txt", "r");
while(fscanf(fp, " %[^\n]s", line) == 1)
{
cout<<line<<endl;
char s1[100], s2[100];
int take = sscanf(line, "%s %s", s1, s2);
cout<<take<<endl;
}
return 0;
}
I'm trying to write a program that reads a bunch of strings from the user, then a newline, and pushes all the strings I've read onto a stack. Here's what I have so far:
stack<string> st;
string str;
while(str != "\n")
{
cin >> str;
st.push(str);
}
However, this goes into an infinite loop and doesn't stop when I read a newline. Why is this happening? How do I fix it?
By default, the stream extraction operator (the >> operator) as applied to strings will skip over all whitespace. If you type in A B C, then a newline, then D E F, then try reading strings one at a time using the stream extraction operator, you'll get the strings "A", "B", "C", "D", "E", and "F" with no whitespace and no newlines.
If you want to read a bunch of strings until you hit a newline, you can consider using std::getline to read a line of text, then use an std::istringstream to tokenize it:
#include <sstream>
/* Read a full line from the user. */
std::string line;
if (!getline(std::cin, line)) {
// Handle an error
}
/* Tokenize it. */
std::istringstream tokenizer(line);
for (std::string token; tokenizer >> token; ) {
// Do something with the string token
}
As a note - in your original code, you have a loop that generally looks like this:
string toRead;
while (allIsGoodFor(toRead)) {
cin >> toRead;
// do something with toRead;
}
This approach, in general, doesn't work because it will continue through the loop one time too many. Specifically, once you read an input that causes the condition to be false, the loop will keep processing what you've read so far. It's probably a better idea to do something like this:
while (cin >> toRead && allIsGoodFor(toRead)) {
do something with toRead;
}
Try doing
stack<string> st;
string str;
while(str!="\n")
{
cin>>str;
if(str == "\n")
{
break;
}
st.push(str);
}
And see if that works.
And if not, then try
while ((str = cin.get()) != '\n')
instead of
while(str!="\n")
I have an input with the following from a text file using C++
command1 5 #Create 5 box
length 12
insertText THIS IS A BOX
how can i read in the input while ignoring anything after the #sign?
for example output should be without #Create 5 box
command1 5
length 12
insertText THIS IS A BOX
EDIT:
I tried the following:
while(getline(myfile, line))
{
istringstream readLine(line);
getline(readLine, command, ' ');
getline(readLine, input, '\0');
}
...but it doesn't seem to work.
The outer while(getline( and istringsteam are good, but after that you'd want to read a space-separated word into command, then perhaps one or more space-separated inputs after that: something like
std::string command, input;
std::vector<std::string> inputs;
if (readLine >> command && command[0] != '#')
{
while (readLine >> input && input[0] != '#')
inputs.push_back(input);
// process command and inputs...
}
It's easier to use >> than getline to parse readLine because they set the stream failure state if they don't get at least one valid character, making the [0] indexing safe and dropping out cleanly for empty lines, or commands with no inputs.
You can simply use std::getline() like this:
int main()
{
std::ifstream ifs("file.txt");
std::string line;
while(std::getline(ifs, line))
{
std::istringstream iss(line);
if(std::getline(iss, line, '#')) // only read up to '#'
{
// use line here
std::cout << line << '\n';
}
}
}
Output:
command1 5
length 12
insertText THIS IS A BOX
in your function where you check every character one by one, add this code: (pseudo code)
if(currChar == #){
while(currChar != '\n'){
getNextChar();// you arent saving it so youre ignoring it
}
}else{
Char c = getNextChar();
//now you can add this character to your output string
for example. You can use ignore(inputSize, "#") or you can use getline
http://www.cplusplus.com/reference/istream/istream/ignore/
http://www.cplusplus.com/reference/istream/istream/getline/
I want to read in scores from a txt file. The scores are going into a struct.
struct playerScore
{
char name[32];
int score, difficulty;
float time;
};
the text file looks like this
Seth 26.255 40 7
as one line, where each item is followed by a tab. (Name\t time\t score\t difficulty\n)
When I begin to read in the text, I don't know how to tell the program when to stop. The scores file could be any number of lines or score entries. This is what I have attempted.
hs.open("scores.txt", ios_base::in);
hs.seekg(0, hs.beg);
if (hs.is_open())
{
int currpos = 0;
while (int(hs.tellg()) != int(hs.end));
{
hs>> inScore.name;
hs >> inScore.time;
hs >> inScore.score;
hs >> inScore.difficulty;
hs.ignore(INT_MAX, '\n');
AllScores.push_back(inScore);
currpos = (int)hs.tellg();
}
}
I'm trying to make a loop that will read in a line of code into a temp struct for the data, then push that struct into a vector of structs. Then update the currpos variable with the current location of the input pointer. However, the loop just gets stuck on the condition and freezes.
There are a multitude of ways to do this, but the following is likely what you're looking for. Declare a free-operator for extracting a single-line definition of a player-score:
std::istream& operator >>(std::istream& inf, playerScore& ps)
{
// read a single line.
std::string line;
if (std::getline(inf, line))
{
// use a string stream to parse line by line.
std::istringstream iss(line);
if (!(iss.getline(ps.name, sizeof(ps.name)/sizeof(*ps.name), '\t') &&
(iss >> ps.time >> ps.score >> ps.difficulty)))
{
// fails to parse a full record. set the top-stream fail-bit.
inf.setstate(std::ios::failbit);
}
}
return inf;
}
With that, your read code can now do this:
std::istream_iterator<playerScore> hs_it(hs), hs_eof;
std::vector<playerScore> scores(hs_it, hs_eof);
I dont think that you can just >> from your file. Do you think it will take everything till \t? :)
You can try to take for example token with strtok()
I guess it can use '\t' to split string and take for each variable via this function needed part of string
In case if it strtok() doesnt work that way i guess you can just copy till '\t' in sub-loop
You can do like this
playerScore s1;
fstream file;
file.open("scores.txt", ios::in | ios::out);
while(!file.eof()) //For end of while loop
{
file.read(s1, sizeof(playerScore));//read data in one structure.
AllScores.push_back(s1);
}
I'm trying to read a file word by word and do some implementation on each word. In future I want to know where was the position of each word. Position is line number and character position in that line. If character position is not available I only need to know when I'm reading a file when I go to the next line. This is the sample code I have now:
string tmp;
while(fin>>tmp){
mylist.push_back(tmp);
}
I need to know when fin is going to next line?!
"I need to know when fin is going to next line"
This is not possible with stream's operator >>. You can read the input line by line and process each line separately using temporary istringstream object:
std::string line, word;
while (std::getline(fin, line)) {
// skip empty lines:
if (line.empty()) continue;
std::istringstream lineStream(line);
for (int wordPos = 0; lineStream >> word; wordPos++) {
...
mylist.push_back(word);
}
}
just don't forget to #include <sstream>
One simple way to solve this problem would be using std::getline, run your own counter, and split line's content into words using an additional string stream, like this:
string line;
int line_number = 0;
for (;;) {
if (!getline(fin, line)) {
break;
}
istringstream iss(line);
string tmp;
while (iss >> tmp) {
mylist.push_back(tmp);
}
line_number++;
}