C++ ignore alphabetical characters when reading input from a file - c++

I have a program that takes an input stream from a text file, which contains positive integers, delimited by spaces. The file contains only numbers and one instance of abc which my program should ignore before continuing to read data from the file.
this is my code and it does not work
int line;
in >> line;
in.ignore(1, 'abc');
in.clear();
could someone specify what the problem is? essentially, I want to discard the alpha input, clear cin and continue to read from file but I get an infinite loop.

This code should work
I get three parts from the input stream, and put the useful parts into a stringstream and read from it
int part1, part2;
std::string abc;
in >> part1 >> abc >> part2;
std::stringstream ss;
ss << part1 << part2;
int line;
ss >> line

You can explicitely ignore any alphabetical character this way:
#include <locale>
#include <iostream>
std::istream& read_number(std::istream& is, int& number) {
auto& ctype = std::use_facet<std::ctype<char>>(is.getloc());
while(ctype.is(std::ctype_base::alpha, is.peek())) is.ignore(1);
return is >> number;
}
int main() {
using std::string;
using std::cin;
using std::locale;
int number;
while(read_number(std::cin, number)) {
std::cout << number << ' ';
}
}
For input like "452abc def 23 11 -233b" this will produce "452 23 11 -233".

Related

How to read file into vector of tuple?

I would like to read a text file, which contains the following data:
Wogger John 2 6.2
Bilbo 111 81.3
Mary 29 154.8
The data separated by tabulator. The problem is if the string contains a space (for example: 'Wogger John'), then the program doesn't work. THe program does work if I replace string 'Wogger John' to 'Wogger' or 'John'. How to fix the problem? How to use the getline() function. Here the code:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cerrno>
#include <cstring>
#include <tuple>
std::vector<std::tuple<std::string, int, double>> Readfile()
{
std::ifstream File("file_read_v3.txt");
std::vector<std::tuple<std::string, int, double>> data;
std::string name;
int a;
double b;
while (File >> name >> a >> b)
{
data.push_back(std::tuple<std::string, int, double>(name, a, b));
}
return data;
}
int main()
{
auto vt = Readfile();
for (const auto& i : vt) {
std::cout << std::get<0>(i) << ", " << std::get<1>(i) << ", " << std::get<2>(i) << std::endl;
}
return 0;
system("pause");
}
while (std::getline(File, name, '\t') >> a >> b)
{
data.push_back(std::tuple<std::string, int, double>(name, a, b));
}
std::getline reads up to and including a delimiter, then discards the delimiter. It defaults to the delimiter being a newline; here we make it a tab.
If the separator was always the same, and different from the separator between the names you could use it in getline as a delimiter, something like:
while (std::getline(File, name, '\t')){
File >> a >> b;
data.push_back(std::tuple<std::string, int, double>(name, a, b));
}
But by your sample file contents, it seems that you have tabs and spaces randomly placed, for that reason getline wouldn't really help very much, the problem remains.
You could, for instance, read the file char by char and stop reading when you encouter a digit, put that digit back and then parse the numeric values, roughly something like this:
std::vector<std::tuple<std::string, int, double>> Readfile()
{
std::ifstream File("file_read_v3.txt");
std::vector<std::tuple<std::string, int, double>> data;
if (File.is_open()) // always check if file was opened
{
int a;
double b;
char c;
do
{
std::string name;
while (!std::isdigit(c = File.get())) // get character, check if is digit
{
name.push_back(c); // add characters until a digit is found
}
File.unget(); // put digit back
File >> a >> b; // parse the int and double
data.push_back(std::tuple<std::string, int, double>(name, a, b));
c = File.get(); // get next character
} while (c != EOF); // if there is nothing else to read
}
return data;
}
To do, remove the space or tab at the end of name.
Thise line:
while (File >> name >> a >> b)
is causing your problems. You are saying cut my line into 1 string and 2 ints seperated by whitespace, so the line:
Wogger John 2 6.2
can not be parsed because it contains 2 strings + 2 ints and the stream operator is going to return false and your while loop is exiting.
To solve this natively you need to parse every char until you hit an \t. Put the parsed chars in a string, then parse the number until \t comes again and parse the next number.

Stringstream doesn't lose data when extracted

I want to create a file which stores some digits, later to be extracted into an array.
#include <vector>
#include <fstream>
#include <iostream>
#include <stringstream>
//for setw()
#include <iomanip>
std::vector<int> getData()
{
using namespace std;
//For the sake of this question simplicity
//I won't validate the data
//And the text file will contain these 10 digits:
//1234567890
ifstream in_file("altnum.txt");
//The vector which holds the results extracted from in_file
vector<int> out;
//It looks like C++ doesn't support extracting data
//from file to stringstream directly
//So i have to use a string as a middleman
stringstream ss;
string str;
//Extract digits from the file until there's no more
while (!in_file.eof())
{
/*
Here, every block of 4 digits is read
and then stored as one independent element
*/
int element;
in_file >> setw(4) >> str;
cout<<str<<"\n";
ss << str;
cout<<ss.str()<<"\n";
ss >> element;
cout<<element<<"\n";
out.push_back(element);
}
//Tell me, program, what have you got for my array?
for (auto &o : out)
cout << o << ' ';
in_file.close();
return out;
}
When i run the snippet of code above, i get the following numbers:
1234 1234 1234
while
1234 5678 90
is expected.
And then i found out (by cout-ing each variable to the screen) that the stringstream ss does not release its content when extracted to 'element'
But why is that? I thought that like cin stream, after the extraction, the stream would pop data out of it? Did i miss anything extremely important?

How to extract specific data from text file containing whitespace and newlines?

I would like to extract and analyze data from a large text file. The data contains floats, integers and words.
The way I thought of doing this is to extract a complete line (up to newline) using std::getline(). Then extract individual data from the line extracted before (extract until whitespace, then repeat).
So far I have this:
int main( )
{
std::ifstream myfile;
myfile.open( "example.txt", std::ios::in );
if( !(myfile.is_open()) )
{ std::cout << "Error Opening File";
std::exit(0); }
std::string firstline;
while( myfile.good() )
{
std::getline( myfile, firstline);
std::cout<< "\n" << firstline <<"\n";
}
myfile.close();
return 0;
}
I have several problems:
1) How do I extract up to a whitespace?
2) What would be the best method of storing the data? There are about 7-9 data types, and the data file is large.
EDIT: An example of the file would be:
Result Time Current Path Requirements
PASS 04:31:05 14.3 Super_Duper_capacitor_413 -39.23
FAIL 04:31:45 13.2 Super_Duper_capacitor_413 -45.23
...
Ultimately I would like to analyze the data, but so far I'm more concerned about proper input/reading.
You can use std::stringstream to parse the data and let it worry about skipping the whitspaces. Since each element in the input line appears to require additional processing just parse them into local variables and after all post processing is done store the final results into a data structure.
#include <sstream>
#include <iomanip>
std::stringstream templine(firstline);
std::string passfail;
float floatvalue1;
std::string timestr;
std::string namestr;
float floatvalue2;
// split to two lines for readability
templine >> std::skipws; // no need to worry about whitespaces
templine >> passfail >> timestr >> floatvalue1 >> namestr >> floatvalue2;
If you do not need or want to validate that the data is in the correct format you can parse the lines directly into a data structure.
struct LineData
{
std::string passfail;
float floatvalue1;
int hour;
int minute;
int seconds;
std::string namestr;
float floatvalue2;
};
LineData a;
char sep;
// parse the pass/fail
templine >> a.passfail;
// parse time value
templine >> a.hour >> sep >> a.minute >> sep >> a.seconds;
// parse the rest of the data
templine >> a.timestr >> a.floatvalue1 >> a.namestr >> a.floatvalue2;
For the first question, you can do this:
while( myfile.good() )
{
std::getline( myfile, firstline);
std::cout<< "\n" << firstline <<"\n";
std::stringstream ss(firstline);
std::string word;
while (std::getline(ss,word,' '))
{
std::cout << "Word: " << word << std::endl;
}
}
As for the second question, can you give us more precision about the data types and what is it you want to do with the data once stored?

is it possible to read from a specific character in a line from a file in c++?

Hey all so I have to get values from a text file, but the values don't stand alone they are all written as this:
Population size: 30
Is there any way in c++ that I can read from after the ':'?
I've tried using the >> operator like:
string pop;
inFile >> pop;
but off course the whitespace terminates the statement before it gets to the number and for some reason using
inFile.getline(pop, 20);
gives me loads of errors because it does not want to write directly to string for some reason..
I don't really want to use a char array because then it won't be as easy to test for the number and extract that alone from the string.
So is there anyway I can use the getline function with a string?
And is it possible to read from after the ':' character?
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <cstdlib>
using namespace std;
int main()
{
string fname;
cin >> fname;
ifstream inFile;
inFile.open(fname.c_str());
string pop1;
getline(inFile,pop1);
cout << pop1;
return 0;
}
ok so here is my code with the new getline, but it still outputs nothing. it does correctly open the text file and it works with a char array
You are probably best to read the whole line then manipulate the string :-
std::string line;
std::getline(inFile, line);
line = line.substr(19); // Get character 20 onwards...
You are probably better too looking for the colon :-
size_t pos = line.find(":");
if (pos != string::npos)
{
line = line.substr(pos + 1);
}
Or something similar
Once you've done that you might want to feed it back into a stringstream so you can read ints and stuff?
int population;
std::istringstream ss(line);
ss >> population;
Obviously this all depends on what you want to do with the data
Assuming your data is in the form
<Key>:<Value>
One per line. Then I would do this:
std::string line;
while(std::getline(inFile, line))
{
std::stringstream linestream(line);
std::string key;
int value;
if (std::getline(linestream, key, ':') >> value)
{
// Got a key/value pair
}
}

Reading Values from fields in a .csv file?

Yesterday I made a small script with some help to read .csv files. I though I found a way to read the first value and store it, but for some reason it stores the last value instead.
I store what I thought should be the first value under value1, and re-display it to make sure it displays properly and is in fact being stored under a callable variable.
Does anyone know what is wrong with this code? I think I should be using vectors but as I read the reference sheets I find on the internet about them I am being a little thrown of. Any help is appreciated.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main ()
{
int loop = 1;
string value;
string value1;
while(loop = 1)
{
cout << "Welcome! \n" << endl;
ifstream myfile;
myfile.open ("C:/Documents and Settings/RHatfield/My Documents/C++/Product Catalog Creator/Source/External/Sample.csv");
while (myfile.good())
getline ( myfile, value, ',' );
cout << string ( value) << endl;
value1 = value;
cout << value1;
myfile.close();
system("PAUSE");
return 0;
}
}
Your error seems to be in pure code formatting.
while (myfile.good())
There is no {} after the loop. So only next line is repeated.
The following code is executed after reading of the whole file.
cout << string ( value) << endl;
Thus value stores the last line of the file.
You may want to change the condition in your while loop:
char separator;
int value1;
int value2;
int value3;
while (myfile >> value1)
{
// Skip the separator, e.g. comma (',')
myfile >> separator;
// Read in next value.
myfile >> value2;
// Skip the separator, e.g. comma (',')
myfile >> separator;
// Read in next value.
myfile >> value3;
// Ignore the newline, as it is still in the buffer.
myfile.ignore(10000, '\n');
// Process or store values.
}
The above code fragment is not robust but demonstrates the concept of reading from a file, skipping non-numeric separators and processing the end of the line. The code is optimized either.