getline() skipping over string line from text file - c++

My project is supposed to basically sum up the value of all ints on a line and print the word in the next line that amount of times. However, something is causing it to skip over the string line where the word but I am getting the summed value right.
Input file:
1,2,3
word
2,3,4
word2
Here is my code:
int main() {
std::ifstream in;
std::ofstream out;
std::string line;
in.open("input.txt");
out.open("output.txt");
while(std::getline(in, line)){
std::stringstream ss(line);
while(ss){
std::string word;
std::string number;
int a = 0;
while(std::getline(ss, number, ',')){
a = a + atoi(number.c_str());}
std::getline(ss, word);
for (int z = 0; z < a; z++){
out << word << ",";}
out << "\n";
}
}
return(0);
}
Output I'm getting:
,,,,,,
,,,,,,,,,
What I should be getting:
word,word,word,word,word,word
word2,word2,word2,word2,word2,word2,word2,word2

Change:
std::getline(ss, word);
To this:
// Gets the next line in input.txt and stores it in the variable 'word'
std::getline(in, word);
This is because during the while loop, ss is emptied (exhausted) by the nested while loop (the 2nd while loop) and has no words when it's contents are inserted into the variable 'word'.
Final code:
#include <iostream>
#include <fstream>
#include <sstream>
int main() {
std::ifstream in;
std::ofstream out;
std::string line;
in.open("input.txt");
out.open("output.txt");
while (std::getline(in, line)) {
std::stringstream ss(line);
while (ss) {
std::string word;
std::string number;
int a = 0;
while (std::getline(ss, number, ',')) {
a = a + atoi(number.c_str());
}
std::getline(in, word); // Changed line
for (int z = 0; z < a; z++) {
out << word << ",";
}
out << "\n";
}
}
return(0);
}

Related

Read array of objects from file by custom separator

I have model class for my objects:
class customClass {
string s1;
string s2;
string s3;
}
and file like this:
text1;text1;text1 text1 text1...
text2;text2;text2 text2 text2...
...
and I want make array of objects where
s1 = "text1"
s2 = "text1"
s3 = "text1 text1 text1..."
...
My code:
infile.open("file.txt");
if (infile.is_open())
{
string line;
for (int i = 0; i < 3; i++)
{
infile >> line;
stringstream ss(line);
while (ss.good())
{
string substring;
getline(ss, substring, ';');
cout << substring <<endl;
}
}
}
But it separated every single word. How can I ignore whitespaces to make my 3rd string as text not as single word.
The reason it doesnt work for you is because infile >> line; will read up to the first space character instead of the whole line (this is when you need getline). Maybe something like this:
#include <string>
#include <iostream>
#include <fstream>
int main()
{
std::ofstream outfile("file.txt");
outfile <<
R"(text1;text1;text1 text1 text1...
text2;text2;text2 text2 text2...)";
outfile.close();
// read file
std::ifstream infile("file.txt");
std::string par1, par2, par3;
while (std::getline(infile, par1, ';') && std::getline(infile, par2, ';') && std::getline(infile, par3))
std::cout << par1 << " | " << par2 << " | " << par3 << std::endl;
}
Demo: http://coliru.stacked-crooked.com/view?id=eb52001b5d4ecbed
Read all line with getline function. Default >> operation get values until \n, (space) character.
#include <iostream>
#include <fstream>
#include <string.h>
#include <sstream>
using namespace std;
class CustomClass
{
public:
string s1;
string s2;
string s3;
};
int main()
{
ifstream infile;
infile.open("test.txt");
if (infile.is_open())
{
while (!infile.eof())
{
string line;
getline(infile, line);
stringstream ss(line);
CustomClass cls;
getline(ss, cls.s1, ';');
getline(ss, cls.s2, ';');
getline(ss, cls.s3, ';');
cout << cls.s1 << " - " << cls.s2 << " - " << cls.s3 << endl;
}
}
return 0;
}
Just don't read single string at the begining, also I added the loop until the end of file, so your code would look like:
std::ifstream infile("file.txt");
std::string line;
if (infile.is_open())
{
string line;
while (std::getline(infile, line)) {
std::stringstream ss(line);
string substring;
while (getline(ss, substring, ';')) {
cout << substring <<endl;
}
}
}

C++ ifstream, issue loading with ";"

int a, b;
while (infile >> a >> b)
{
// process pair (a,b)
}
So this is the code i've been watching but i ran into a problem because my strings doesn't have whitespaces between them, they have ";"
My code:
void load(string filename){ // [LOAD]
string line;
ifstream myfile(filename);
string thename;
string thenumber;
if (myfile.is_open())
{
while (myfile >> thename >> thenumber)
{
cout << thename << thenumber << endl;
//map_name.insert(make_pair(thename,thenumber));
}
myfile.close();
}
else cout << "Unable to open file";
}
[Inside the txt.file]
123;peter
789;oskar
456;jon
What i get right now is "thename" as 123;peter and "thenumber" as 789;oskar.
I want "thename" as peter and "thenumber" as 123 so i can then insert it back into my map correctly, How?
The infile >> a read from infile the eligible type for a. In your case a is int so '>>' expect to find an int. In your code myfile >> thename >> thenumber both are string type so they expect string type in your file. The problem is that string include ';' so the variable name will take all the row until it find \n(new line).
in your code
std::string thename, thenumber;
char delimeter(';'); //It is always '-' is it?
std::getline(std::cin, thename, delimeter);
std::getline(std::cin, thenumber);
also thenumber will be string type. To convert your thenumber into int:
std::istringstream ss(thenumber);
int i;
ss >> i;
if (ss.fail())
{
// Error
}
else
{
std::cout << "The integer value is: " << i;
}
return 0;
It is fairly simple to read in a file in the format. You can use std::getline with a different delimiter to tell it where to stop reading the input.
while(getline(myfile, thenumber, ';')) // reads until ';' or end of file
{
getline(myfile, thename); // reads until newline or end of file
map_name.insert(make_pair(thename,thenumber));
}
You have to input a single string and then split it to get the name and number
....
#include <string>
#include <sstream>
#include <vector>
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;
}
....
void load(string filename){
..........
if (myfile.is_open())
{
while (myfile >>whole)
{
std::vector<std::string> parts = split(whole, ';');
name = parts[0];
number = parts[1];
}
}

Loop iteration issue c++

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>
using namespace std;
int main()
{
string line;
ifstream infile ("Input.csv");
vector<string> table;
string word;
if(infile.is_open())
{
getline(infile,line);
istringstream iss(line);
while(!iss.eof())
{
getline(iss,word, ',');
table.push_back(word);
}
}
for(int index=0; index<11; ++index)
{
cout<< "Element" << index << ":" << table.at(index) << endl ;
}
infile.close();
}
In the above program I am reading values from input file and splitting based on comma and finally storing the values into a vector.
when I print vector I am able to view only the first line of input file.
Input file:
CountryCode,Country,ItemCode,Item,ElementGroup,ElementCode,Element,Year,Unit,Value,Flag
100,India,3010,Population - Est. & Proj.,511,511,Total Population - Both sexes,1961,1000,456950,
100,India,3010,Population - Est. & Proj.,511,511,Total Population - Both sexes,1962,1000,466337,
100,India,3010,Population - Est. & Proj.,511,511,Total Population - Both sexes,1963,1000,476025,
100,India,3010,Population - Est. & Proj.,511,511,Total Population - Both sexes,1964,1000,486039,
Output:
Element0:CountryCode
Element1:Country
Element2:ItemCode
Element3:Item
Element4:ElementGroup
Element5:ElementCode
Element6:Element
Element7:Year
Element8:Unit
Element9:Value
Element10:Flag
Problem: Only 1st line is being printed
I suggest rewriting it like this:
int main()
{
string line;
ifstream infile ("Input.csv");
vector<string> table;
string word;
while(getline(infile, line))
{
istringstream iss(line);
while(getline(iss,word, ','))
{
table.push_back(word);
}
}
for(int index=0; index<11; ++index)
{
cout<< "Element" << index << ":" << table.at(index) << endl ;
}
infile.close();
}
The stream will return false from getline and most other operations whenever it is invalid. So if it didn't open, the while loop won't run. And when it reaches EOF, the while loop will stop. Much simpler to read this way I think.
You have several issues, addressed below:
int main()
{
std::string line;
std::ifstream infile ("Input.csv");
std::vector<std::string> table;
while (std::getline(infile, line)) // this is the loop you want to read the file
{
std::istringstream iss(line);
std::string word;
while (std::getline(iss, word, ',')) // there are better ways to do this, but this will work
{
table.push_back(word);
}
}
for(int index=0; index<table.size(); ++index) // loop through the whole size
{
std::cout<< "Element" << index << ":" << table[index] << std::endl ;
}
infile.close();
return 0;
}
Alternatively, you can avoid the use of nested while loops altogether:
struct csv_reader : std::ctype<char>
{
csv_reader() : std::ctype<char>(get_table()) {}
static std::ctype_base::mask const* get_table()
{
static std::vector<std::ctype_base::mask> rc(table_size, std::ctype_base::mask());
rc['\n'] = std::ctype_base::space;
rc[','] = std::ctype_base::space;
return &rc[0];
}
};
int main()
{
std::string line;
std::ifstream infile ("Input.csv");
csv_reader reader;
infile.imbue(std::locale(std::locale(), &reader);
std::vector<std::string> table{std::istream_iterator<std::string>(infile), std::istream_iterator<std::string>()};
// or
//std::vector<std::string> table;
//std::copy(std::istream_iterator<std::string>(infile), std::istream_iterator<std::string>(), std::back_inserter(table));
for(int index=0; index<table.size(); ++index) // loop through the whole size
{
std::cout<< "Element" << index << ":" << table[index] << std::endl ;
}
infile.close();
return 0;
}
You read only one line of the file
if(infile.is_open())
{
getline(infile,line);
istringstream iss(line);
while(!iss.eof())
{
getline(iss,word, ',');
table.push_back(word);
}
}
If you need to read all lines of the file then you can write instead
while (getline(infile,line))
{
istringstream iss(line);
while(!iss.eof())
{
getline(iss,word, ',');
table.push_back(word);
}
}
You only read the first line.
Add a loop with a condition like
while (getline(infile, line)) {
...
}
Your for loop only print the first 11 posts from the array.
You should it to the lenght of the array.
Not sure what the syntax is for c++ for length of the table but that should be the issue.
for(int index=0; index<table.size(); ++index)
{
cout<< "Element" << index << ":" << table.at(index) << endl ;
}

Trouble with reading/outputting files

I want to open a file for reading then output what is in that .txt file, any suggestion on my code?
string process_word(ifstream &word){
string line, empty_str = "";
while (!word.eof()){
getline(word, line);
empty_str += line;
}
return empty_str;
}
int main(){
string scrambled_msg = "", input, output, line, word, line1, cnt;
cout << "input file: ";
cin >> input;
ifstream inFile(input);
cout << process_word(inFile);
}
Instead of:
while (!word.eof()) {
getline(word, line);
empty_str += line;
}
do:
while ( std::getline(word, line) ) {
empty_str += line;
}
and it would be also wise to give your variables more appropriate names.
Your function can be simplified to:
#include <iterator>
std::string process_word(std::ifstream& word)
{
return std::string{std::istream_iterator<char>{word},
std::istream_iterator<char>{}};
}
int main()
{
string input;
std::cin >> input;
std::ifstream inFile(input);
std::cout << process_word(inFile);
}

C++: File I/O having difficulty with opening and working with it

I'm having difficulty opening files and processing what is inside of them. What i want to do is
pull a line from the input file
init an istreamstream with the line
pull each word from the istringstream
i. process the word
do my specific function i've created
ii. write it to the output file
I'm not sure how to go about doing 1-3 can anyone help with my functions? This is what i have so far...
string process_word(ifstream &inFile){
string line, empty_str = "";
while (getline(inFile,line)){
empty_str += line;
}
return empty_str;
}
int main(){
string scrambled_msg = "", input, output, line, word, line1, cnt;
cout << "input file: ";
cin >> input;
cout << "output file: ";
cin >> output;
ifstream inFile(input);
ofstream outFile(output);
cout << process_word(inFile);
}
std::vector<std::string> process_word(std::ifstream& in)
{
std::string line;
std::vector<std::string> words;
while (std::getline(in, line)) // 1
{
std::istringstream iss{line}; // 2
std::move(std::istream_iterator<std::string>{in},
std::istream_iterator<std::string>{},
std::back_inserter(words));
}
return words;
}
int main()
{
std::ifstream in(file);
std::ofstream out(file);
auto words = process_word(in);
for (auto word : words)
// 3 i.
std::move(words.begin(), words.end(), // 3 ii.
std::ostream_iterator<std::string>{out});
}