I am making a bowling program for school that stored scores in a text file with the format:
paul 10 9 1 8 1, ...etc
jerry 8 1 8 1 10 ...etc
...etc
I want to read the file into a stringstream using getline() so I can use each endl as a marker for a new player's score (because the amount of numbers on a line can be variable, if you get a spare or strike on round 10). I can then read the stringstream using >> to get each score and push it into a vector individually.
However, when trying to use getline(fstream, stringstream), I get an error
no instance of overloaded function "getline" matches the argument list -- argument types are: (std::fstream, std::stringstream)
How can I make this work?
My code looks like this:
#include <iostream>
#include <vector>
#include <fstream>
#include <exception>
#include <string>
#include <sstream>
using namespace std;
//other parts of the program which probably don't matter for this error
vector <int> gameScore;
vector<string> playerName;
int i = 0;
int j = 0;
string name;
int score;
stringstream line;
while (in.good()){ //in is my fstream
playerName.push_back(name);
cout << playerName[i] << " ";
i++;
getline(in, line);
while (line >> score){
gameScore.push_back(score);
cout << gameScore[j] << " ";
j++;
}
}
You can't use std::getline() to read from a std::ifstream directly into a std::stringstream. You can only read into a std::string, which you can then assign to the std::stringstream, eg:
vector<int> gameScore;
vector<string> playerName;
string name, line;
int score;
while (getline(in, line)){
istringstream iss(line);
iss >> name;
playerName.push_back(name);
cout << name << " ";
while (iss >> score){
gameScore.push_back(score);
cout << score << " ";
}
}
Related
Let's say I have a txt file
Rahim
5 6 7
Karim
6 7 8
Rahman
7 8 9
I want to save those name in a vector and I want to put those number in a nested vector as integers.
I tried this but it's not working.
#include <string>
#include <vector>
using namespace std;
int main(){
vector<vector<int> > data;
vector<int> temp;
vector<string> nameF;
string file;
cout << "Enter a file: ";
cin >> file;
ifstream infile(file);
if(!infile.good()){
cout << "Enter a valid file: " << endl;
return 1;
}
string name;
string values;
while(!infile.eof()){
getline(infile, name);
getline(infile, values);
if(!infile.fail()){
nameF.push_back(name);
for(int i = 0; i < values.length(); i++){
string s = values.substr(i, values.find(" "));
temp.push_back(stoi(s));
}
data.push_back(temp);
}
}
}
So I suggest you use an istringstream to read the integers from the second string
#include <sstream>
nameF.push_back(name);
istringstream buffer(values);
vector<int> temp;
int value;
while (buffer >> value) {
temp.push_back(value);
}
data.push_back(temp);
An istringstream lets you read from a string as if it was any other input source. So it's an easy way to convert a whitespace separated string of integers.
Another problem in your original code is that you reuse temp for each line without clearing it in between. So each line is going to add to the integers that are already there from previous lines. I've fixed that problem by moving the declaration of temp to inside the loop, but you could just call temp.clear(); before the integer reading loop.
I am reading line by line from a text file whose contents are separated by commas and parsed by extracting with getline() into my stringColor, stringName, stringReward variables, passed into my stringstream ss, and then passed to my tileArray pointer array into respective int, string, and int variables.
My program compiles, however when I run it, it generates a Segmentation Fault 11 to what appears to be where I pass the line contents into stringstream. I cannot find where the problem is however...
Perhaps if someone could point out where the error is, I would be greatly appreciative.
This is the format of each line I am trying to read in from the text file.
It should be able to read in any number of lines.
0,tile 1,5
4,tile 2,0
2,tile 4,1
#include <stdio.h>
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <stdlib.h>
using namespace std;
typedef struct
{
int color;
string name;
int reward;
}tile;
int main()
{
string line;
int numberOfLines = 0;
ifstream inputFile("inputFile.txt");
if (inputFile.is_open())
{
while(getline(inputFile, line))
{
++numberOfLines; //value to set tile amount
cout << numberOfLines <<endl;
}
tile *tileArray = new tile[numberOfLines];
string stringColor, stringName, stringReward; //declare these values as strings and later convert
stringstream ss; //stringstream variable to convert string variable
for(int n = 0; n<(numberOfLines-1); n++)
{
getline(inputFile, stringColor, ','); //delimiter at first comma
cout << stringColor << endl;
getline(inputFile, stringName, ','); // delimiter at second
cout << stringName << endl;
getline(inputFile, stringReward); // stop at the end of the line
cout << stringReward << endl;
ss<<stringColor;
ss>>tileArray[n]->color;
ss.str("");
ss.clear();
cout << tileArray[n]->color;
ss<<stringName;
ss>>tileArray[n]->name;
ss.str("");
ss.clear();
cout << tileArray[n]->name;
ss<<stringReward;
ss>>tileArray[n]->reward;
ss.str("");
ss.clear();
cout << tileArray[n]->reward;
}
}
return 0;
}
I would simplify the use of the stringstream object. Using the same stringstream object as an input stream and output stream requires a deep understanding of how the internal position is manipulated.
{
// Create a nested block and a local istringstream in the nested scope
istringstream ss(stringColor);
ss >> tileArray[n]->color;
}
cout << tileArray[n]->color;
Similarly,
{
istringstream ss(stringName);
ss >> tileArray[n]->name;
}
cout << tileArray[n]->name;
and
{
istringstream ss(stringReward);
ss >> tileArray[n]->reward;
}
cout << tileArray[n]->reward;
So I'm really stuck trying to figured this bug on the program that is preventing me from displaying the text of my program..
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <string>
#include <stdio.h>
using namespace std;
int main ()
{
ifstream infile;
ofstream offile;
char text[1024];
cout <<"Please enter the name of the file: \n";
cin >> text;
infile.open(text);
string scores; // this lines...
getline(infile, scores, '\0'); // is what I'm using...
cout << scores << endl; // to display the file...
string name1;
int name2;
string name3;
int name4;
infile >> name1;
infile >> name2;
infile >> name3;
infile >> name4;
cout << "these two individual with their age add are" << name2 + name4 <<endl;
// 23 + 27
//the result I get is a bunch of numbers...
return 0;
}
Is there any way cleaner or simple method i can used to display the file ?
All the method in the internet are difficult to understand or keep track due to
the file is open in loop..
I want a program that you type the name of the file and displays the file
the file will contain the following...
jack 23
smith 27
Also I need to obtain data from the file now I'm using the above code to obtain that information from the file...
loop is probably the best thing you can do.
so if you know the format you could simply do it like this
#include <iostream>
#include <fstream>
using namespace std;
int printParsedFile(string fileName) { // declaration of a function that reads from file passed as argument
fstream f; // file stream
f.open(fileName.c_str(), ios_base::in); // open file for reading
if (f.good()) { // check if the file can be read
string tmp; // temp variable we will use for getting chunked data
while(!f.eof()) { // read data until the end of file is reached
f >> tmp; // get first chunk of data
cout << tmp << "\t"; // and print it to the console
f >> tmp; // get another chunk
cout << tmp << endl; // and print it as well
} else {
return -1; // failed to open the file
}
return 0; // file opened and read successfully
}
you can call then this function for example in your main() function to read and display file passed as argument
int main(int argc, char** argv) {
string file;
cout << "enter name of the file to read from: "
cin >> file;
printParsedFile(file);
return 0;
}
I personally use stringstreams for reading one line at a time and parsing it:
For example:
#include <fstream>
#include <stringstream>
#include <string>
std::string filename;
// Get name of your file
std::cout << "Enter the name of your file ";
std::cin >> filename;
// Open it
std::ifstream infs( filename );
std::string line;
getline( infs, line );
while( infs.good() ) {
std::istringstream lineStream( line );
std::string name;
int age;
lineStream >> name >> age;
std::cout << "Name = " << name << " age = " << age << std::endl;
getline( infs, line );
}
I have this program that changes negative numbers to positive in my file.
It works, but negative numbers in the file don't change.
for example, if I have this numbers in my file : 12 2 -3 -1
when I run the program, the sum of numbers will be 18, but when I open my file again, I see
12 2 -3 -1 . What should I do to see 12 2 3 1 ?
here is my code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string name;
cin >> name;
int number;
int num=0;
ifstream myFile(name, ios::in);
ofstream mine(name, ios::app);
while(myFile >> number)
{
num += (number<0 ? -number : number);
mine << num;
}
cout << "num = " << num << endl;
system("pause");
return 0;
}
Opening the file for reading and writing for the same time is generally not a bad idea. You probably got an I/O error during opening mine, but since you didn't check it, the program ignored your writes silently. Try reading the file contents first (to a vector for example), then close the file for reading and open again for writing (not appending, because that would leave the old contents in the file).
When writing the values back to the file, also write whitespace after the number, otherwise you'll just get a string of digits in the file but you won't know where one begins and another ends.
Your program now doesn't "change negative numbers to positive" but it prints the cumulative sum of absolute values to the file.
Try writing to the standard output first so you won't ruin your file while you are testing. If it works, then change cout to your output stream.
Here is the code.
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstdlib>
using namespace std;
int main()
{
string name;
cin >> name;
int number;
int num=0;
ifstream myFile(name, ios::in);
vector<int> vec;
while(myFile >> number)
{
vec.push_back(abs(number));
}
ofstream mine(name, ios::out);
for (vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
num += *it;
mine << *it << " ";
}
cout << "num = " << num << endl;
return 0;
}
Opening a read and write file streams for the same file and process at the same time is inviting file corruption. Use ostringstream to store the values read from the file. The values
from the file are read, and the values stored in the ostringstream
buffer. The ifstream object is closed before re-opening the file with
an ofstream object so that the buffer contents can be saved.
Note the ios::app flag has been removed. Otherwise the new values
will append to the existing values.
abs() function is used to write back the absolute values - this
forces all values positive.
#include<sstream>
int main()
{
string name;
cin >> name;
int number;
int num=0;
ifstream myfile(name.c_str(), ios::in);
ostringstream oss;
while (myfile >> number)
{
num += (number<0 ? -number : number);
oss << abs(number) << " ";
}
myfile.close();
ofstream mine(name.c_str());
cout << "num = " << num << endl;
mine << oss.str();
return 0;
}
string name;
cin >> name;
int number=0;
int sum=0;
string outname=name+".pos.txt";
ifstream myFile(name,ifstream::in);
ofstream mine(outname, ofstream::out );
while(myFile >> number)
{
number= (number<0 ? -number : number);
sum+=number;
mine << number<<' ';
}
myFile.close();
mine.close();
cout << "sum = " << sum << endl;
system("pause");
This is my problem: I read some lines from a txt. This txt is like this:
Ciao: 2000
Kulo: 5000
Aereo: 7000
ecc. I have to assign every word before(':') to a string and then to a map; and the numbers to a int and then to a map. The problem is that beginning from the second line, my string become ("\nKulo") ecc! I don't want this! What can I do?
This is the code:
#include <iostream>
#include <fstream>
#include <string>
#include <map>
using namespace std;
int main()
{
map <string, int> record;
string nome, input;
int valore;
ifstream file("punteggi.txt");
while (file.good()) {
getline(file, nome, ':');
// nome.erase(0,2); //Elimina lo spazio iniziale
file >> valore;
record[nome] = valore;
cout << nome;
}
file.close();
cout << "\nNome: ";
cin >> input;
cout << input << ": " << record[input] << "\n";
cout << "\n\n";
return 0;
}
The issue you have is that std::getline() is an unformatted input function and as such doesn't skip leading whitespace. From the looks of it, you want to skip leading whitespace:
while (std::getline(in >> std::ws, nome, ':') >> valore) {
...
}
Alternatively, if there are leading spaces, you can ignore() all characters up to the end of line after reading a value.
BTW, since I saw someone over here recommending the use of std::endl: do not use std::endl unless you really intend to flush the buffer. It is a frequent major performance problem when writing files.
Use the standard line reading idiom:
for (std::string line; std::getline(file, line); )
{
std::string key;
int n;
std::istringstream iss(line);
if (!(iss >> key >> n) || key.back() != ':') { /* format error */ }
m.insert(std::make_pair(std::string(key.cbegin(), std::prev(key.cend()),
n));
}
(Instead of the temporary string-from-iterators, you can also use key.substr(0, key.length() - 1), although I imagine that my version may be a bit more efficient. Or add a key.pop_back(); before inserting the data into the map.)