I am new to c++.My aim is to read a file containing all integers, like
1 2 3\n 1 3 4\n 1 2 4\n
and
1,2 3,4 5,6\n 1,3 3,4 3,5\n 1,3 3,4 4,2\n
I could use getline to read them, but how could I split it into an integer array. Like array[3]={1,2,3} and array2={1,2,3,4,5,6} for the first line reading result? Sorry I forgot to mention that I was trying to not use the STLs for C++
You can do it without boost spirit
// for single line:
std::vector<int> readMagicInts(std::istream &input)
{
std::vector<int> result;
int x;
while(true) {
if (!(input >> x)) {
char separator;
input.clear(); // clear error flags;
if (!(input >> separator >> x)) break;
if (separator != ',') break;
}
result.push_back(x);
}
return result;
}
std::vector<std::vector<int>> readMagicLinesWithInts(std::istream &input)
{
std::vector<std::vector<int>> result;
std::string line;
while (std::getline(input, line)) {
std::istringstream lineData(line);
result.push_back(readMagicInts(lineData));
}
return result;
}
Related
I have an input from isstream
1 2
3 4
5 6
I would like to populate this from isstream overloading the >> operator
the input would be something like
Matrix m;
string input = "1 2 \n 3 4\n 5 6\n";
istringstream ss(input);
ss >> m;
how do I implement the >> operator to parse the matrix from isstream?
I have tried the code below but the peek call seems to ignoring the new line
std::istream& operator>>(std::istream& is, Matrix& s)
{
vector<vector<int>> elements;
int n;
while (!is.eof())
{
vector<int> row;
while ((is.peek() != '\n') && (is >> n))
{
row.push_back(n);
}
is.ignore(numeric_limits<streamsize>::max(), '\n');
elements.push_back(row);
}
return is;
}
The simplest way is to parse one line at a time:
std::istream& operator>>(std::istream& is, Matrix& s)
{
std::vector<std::vector<int>> elements;
for (std::string line; std::getline(is, line);) {
std::istringstream line_iss{line};
std::vector<int> row(std::istream_iterator<int>{line_iss},
std::istream_iterator<int>{});
elements.push_back(std::move(row));
}
s.set(elements); // dump elements into s (adapt according to the interface of Matrix)
return is;
}
I want to be able to parse a string such as:
inputStr = "abc 12 aa 4 34 2 3 40 3 4 2 cda t 4 car 3"
Into separate vectors (a string vector and integer vector) such that:
strVec = {"abc", "aa", "cda", "t", "car"};
intVec = {12, 4, 34, 2, 3, 40, 3, 4, 2, 4, 3};
What is a good method to do this? I'm somewhat familiar with stringstream and was wondering whether it's possible to do something like this:
std::string str;
int integer;
std::vector<int> intVec;
std::vector<std::string> strVec;
std::istringstream iss(inputStr);
while (!iss.eof()) {
if (iss >> integer) {
intVec.push_back(integer);
} else if (iss >> str) {
strVec.push_back(str);
}
}
I have attempted something to that effect, but the program seems to enter a halt of sorts (?). Any advice is much appreciated!
When iss >> integer fails, the stream is broken, and iss >> str will keep failing. A solution is to use iss.clear() when iss >> integer fails:
if (iss >> integer) {
intVec.push_back(integer);
} else {
iss.clear();
if (iss >> str) strVec.push_back(str);
}
I think this answer is the best here.
#include <string>
#include <sstream>
#include <vector>
#include <iterator>
template<typename Out>
void split(const std::string &s, char delim, Out result) {
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, delim)) {
*(result++) = item;
}
}
std::vector<std::string> split(const std::string &s, char delim) {
std::vector<std::string> elems;
split(s, delim, std::back_inserter(elems));
return elems;
}
Originally answered here, You can then try to distinguish between strings and numbers.
I'm quite new to C++, so sorry if this is a dumb question!
For a project we are given a file with a couple of thousand lines of values, each line having 9 different numbers.
I want to create a for/while loop that, for each loop, stores the 8th and 9th integer of a line as a variable so that I can do some calculations with them. The loop would then move onto the next line, store the 8th and 9th numbers of that line as the same variable, so that I can do the same calculation to it, ending when I've run out of lines.
My problem is less to do with reading the file, I'm just confused how I'd tell it to take only the 8th and 9th value from each line.
Thanks for any help, it is greatly appreciated!
Designed for readability rather than speed. It also performs no checking that the input file is the correct format.
template<class T> ConvertFromString(const std::string& s)
{
std::istringstream ss(s);
T x;
ss >> x;
return x;
}
std::vector<int> values8;
std::vector<int> values9;
std::ifstream file("myfile.txt");
std::string line;
while (std::getline(file, line))
{
std::istringstream ss(line);
for (int i = 0; i < 9; i++)
{
std::string token;
ss >> token;
switch (i)
{
case 8:
{
values8.push_back(ConvertFromString<int>(token));
}
break;
case 9:
{
values9.push_back(ConvertFromString<int>(token));
}
break;
}
}
}
First, split the string, then convert those to numbers using atoi. You then will take the 8th and 9th values from the array or vector with the numbers.
//Split string
std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, delim)) {
elems.push_back(item);
}
return elems;
}
std::vector<std::string> split(const std::string &s, char delim) {
std::vector<std::string> elems;
split(s, delim, elems);
return elems;
}
//new code goes here
std::string line;
std::vector<std::string> lineSplit = split(line, ' ');
std::vector<int> numbers;
for (int i = 0; i < lineSplit.size(); i++)
numbers.push_back(atoi(lineSplit[i]);//or stoi
int numb1 = numbers[7];//8th
int numb2 = numbers[8];//9th
if i have a file like
1 5 6 9 7 1
2 5 4 3 8 9
3 4 3 2 1 6
4 1 3 6 5 4
and i want to sort the numbers in every line ..
how to know when there is a newline ?
code for example :
while (!input.eof) {
input>>num;
while (not new line ?){
input>>o;
b.push_back(o);
}
sort (b.begin(),b.end());
se=b.size();
output<<num<<" "<<b[se-1]<<endl;
b.clear();
}
Note: i tried while(input>>num) and getline will now work with me
any ideas ?
Your input doesn't work! Using a loop testing for stream.eof() as the only control for the input is always wrong. You always need to test your input after you tried to read it. Incidentally, I posted earlier how you can guarantee that there is no newline between to objects. there is already an answer using std::getline() as a first stage which is somewhat boring. Here is an alternate approach:
std::istream& noeol(std::istream& in) {
for (int c; (c = in.peek()) != std::char_traits<char>::eof()
&& std::isspace(c); in.get()) {
if (c == '\n') {
in.setstate(std::ios_base::failbit);
}
}
return in;
}
// ...
while (input >> num) {
do {
b.push_back(num);
} while (input >> noeol >> num);
std::sort (b.begin(),b.end());
se=b.size();
output<<num<<" "<<b[se-1]<<endl;
b.clear();
input.clear();
}
You can use std::getline together with std::istringstream to read the file line by line, and then process each line individually:
#include <sstream>
std::string line;
while (std::getline(infile, line))
{
std::istringstream iss(line);
int a, b;
//You can now read the numbers in the current line from iss
}
For further reference on how to read the file line by line, see this post.
My test file has data like this:
1
2
3
0
1, 2
3, 4
0, 0
4, 3
2, 1
0, 0
How would I separate the data by line but also separate each section of data by the zeros.
ifstream data("testData.txt");
string line, a, b;
while(getline(data,line))
{
stringstream str(line);
istringstream ins;
ins.str(line);
ins >> a >> b;
hold.push_back(a);
hold.push_back(b);
}
How do I separate them by the zeros?
First of all, I would try to improve the problem definition ☺
So the lines are significant, and the zero-delimited lists of numbers are also significant? Try something like this:
std::ifstream data("testData.txt");
std::vector<int> hold;
std::string line;
std::vector<std::string> lines;
while(std::getline(data,line))
{
lines.push_back(line);
std::stringstream str(line);
// Read an int and the next character as long as there is one
while (str.good())
{
int val;
char c;
str >> val >> c;
if (val == 0)
{
do_something(hold);
hold.clear();
}
else
hold.push_back(val);
}
}
This isn't very fault-tolerant, but it works. It relies on a single character (a comma) to be present after every number except the last one on each line.
When you're done you have
[1,2,3,0,1,2,3,4,0,0,4,3,2,1,0,0]
How about using std::find()?