Problem is described here.
I tried to solve it using code that's below, but it's not working.
const char* filename = "test.txt";
ifstream file1(filename);
vector<int> v1;
vector<int> v2;
vector<int> res;
int number;
char c;
while(1){
while(1){
v1.push_back(number);
file1.get(c);
if (c==';') break;
}
while(1){
v2.push_back(number);
file1.get(c);
if (c=='\n') break;
}
for (vector<int>::iterator it = v2.begin(); it!=v2.end(); it++)
cout << *it << ',';
cout << endl;
file1.get(c);
if (c==EOF) break;
file1.unget();
}
There is a problem with reading end of line. Is c=='\n' right?
To read a line, you should use:
istream& getline (istream& is, string& str, char delim);
In your case, with a delimiter of ';'
Then you can parse numbers in the same way, by using delimiter of ','
like this:
std::string line, temp;
std::getline(file1,line,';'); //get a line. (till ';')
std::istringstream s1 (line); //init stream with the whole line
while(std::getline(s1,temp,',')){//get a number as string from the line. (till ',')
int n;
std::istringstream s2(temp);
s2>>n; //convert string number to numeric value
//now you can push it into the vector...
}
Related
I have a file with following lines:
51:HD L80 Phone:78
22:Nokia Phone:91
I need to split these into 3 separate variables
(int, string, int)
int id = line[0]
string phoneName = line[1]
int price = line [2]
I have tried many solutions for example:
std::ifstream filein("records");
for (std::string line; std::getline(filein, line); )
{
// std::cout << line << std::endl;
std::istringstream iss (line);
std::string word;
std::vector<string> tempString;
while(std::getline(iss,word,',')){
tempString.push_back(word);
// std::cout << word << "\n";
}
However in this example I do get the values but they are coming in a stream and not in one go. I do not want to save them into vector (no other way to store the incoming values) but call a function immediately after getting all the 3 values.
SOLUTION
This is a modification of the accepted answer:
`for (std::string line; std::getline(filein, line); )
{
// std::cout << line << std::endl;
std::istringstream iss (line);
for (int stockID; iss >> stockID; )
{
char eater;
iss >> eater; // this gets rid of the : after reading the first int
std::string stockName;
std::getline(iss, stockName, ':'); // reads to the next :, tosses it out and stores the rest in word
std::string catagory;
std::getline(iss, catagory, ':'); // reads to the next :, tosses it out and stores the rest in word
std::string subCatagory;
std::getline(iss, subCatagory, ':');
int stockPrice;
iss >> stockPrice;
iss >> eater; // this gets rid of the : after reading the first int
int stockQTY;
iss >> stockQTY; // get the last int
// iss >> eater;
// std::cout << stockName << "\n";
Record recordd = Record(stockID,stockName,catagory,subCatagory,stockPrice,stockQTY);
record.push_back(recordd);
}
}`
for when text file contains:
51:HD L80 Phone:Mobile:Samsung:480:40
22:Nokia Phone:Mobile:Nokia:380:200
There is no reason to use a std::stringstream here if you know you are going to have exactly 3 columns in every row. Instead you can read those values directly from the file, store them in temporaries, and then call the function with those temporary variables.
for (int a; filein >> a; )
{
char eater;
filein >> eater; // this gets rid of the : after reading the first int
std::string word;
std::getline(filein, word, ':'); // reads to the next :, tosses it out and stores the rest in word
int b;
filein >> b; // get the last int
function_to_call(a, word, b);
}
You can find different ways to split a string here:
https://www.fluentcpp.com/2017/04/21/how-to-split-a-string-in-c/
Example:
std::vector<std::string> split(const std::string& s, char delimiter)
{
std::vector<std::string> tokens;
std::string token;
std::istringstream tokenStream(s);
while (std::getline(tokenStream, token, delimiter))
{
tokens.push_back(token);
}
return tokens;
}
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];
}
}
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});
}
I've spent almost 4 hours trying to get past this issue...
I have a text file with over 100 rows. Each row has 4 values separated by commas. I want to be able to extract each value and save it into a variable (v1...v4).
I have used a for loop, as I won't be reading the entire contents of the file. I'm just trying to get 1 working for now.
So far, I have managed to read a single row. I just need to break the row up now. This is for my Uni assignment, and I am not allowed to use any boost or tokeniser classes. Just getline and other basic commands.
I have this code:
// Read contents from books.txt file
ifstream theFile("fileName.txt");
string v1, v2, v3, v4, line;
for (int i = 0; i < 1; i++) {
getline(theFile, line, '\n');
cout << line << endl; // This part works fine
getline(line, v1, ","); // Error here
cout << v1 << endl;
getline(line, v2, ","); // Error here
cout << v2 << endl;
getline(line, v3, ","); // Error here
cout << v3 << endl;
getline(line, v4, '\n'); // Error here
cout << v4 << endl;
}
theFile.close();
The error I get is - error: no matching function for call to ‘getline(std::string&, std::string&, const char [2])
How can I fix this?
The delimiter for getline is a character. You have used double-quote marks "," which represent a string (hence why the compiler error indicates that you've used char[2] - string literals contain an additional 'nul' character).
Single character values are represented using single quotes instead:
getline(myFile, v1, ',');
edit - I've just noticed you're passing a string as the first parameter, which getline doesn't support (it won't let you retrieve tokens directly from a string). You probably wanted to stuff the string into a stringstream instead
#include <sstream>
// etc ...
std::string csv = "the,cat,sat,on,the,mat";
std::istringstream buffer( csv );
std::string token;
while( std::getline( buffer, token, ',' ) )
{
std::cout << token << std::endl;
}
According to this page, you have to call getline with std::istream as the first parameter.
But line is of type std::string. You should pass a std::istream instead, which can
be done by creating an std::istringstream from line. This could work:
string v1, v2, v3, v4, line;
istringstream line_stream;
for (int i = 0; i < 1; i++) {
getline(theFile, line, '\n');
cout << line << endl;
line_stream.str(line); // set the input stream to line
getline(line_stream, v1, ","); // reads from line_stream and writes to v1
...
If you want to read more about std::istringstream, you can do that here.
Also, according to the above page, the third parameter has to be of type char. But you pass "," which will automatically converted to const char[2], a string. For characters, you use 'c'.
There are two overloads for std::getline:
istream& getline ( istream& is, string& str, char delim );
istream& getline ( istream& is, string& str );
Three of your calls pass a literal string constant as the third parameter, where a single char is required. Use ' rather than " for character constants.
string filename, text, line;
vector<string> v1;
vector<string> v2;
vector<string> v3;
vector<string> v4;
int i = 0, k = 0, n;
cout << "Enter filename." << endl;
cin >> filename;
cout << "How many lines of text are in the file?" << endl;
cin >> n;
cin.ignore(200, '\n');
ifstream file(filename.c_str());
if (!file) {
cerr << "No such file exists." << endl;
exit(1);
}
cin.ignore(200, '\n');
if (file.is_open()) {
while (file.good()) {
for (k = 0; k < n; k++) { //Loops for as many lines as there are in the file
for (i = 0; i < 4; i++) { //Loops for each comma-separated word in the line
getline(cin, text, ',');
if (i == 0)
v1.push_back(text);
else if (i == 1)
v2.push_back(text);
else if (i == 2)
v3.push_back(text);
else if (i == 3)
v4.push_back(text);
}
}
}
}
file.close();
return 0;
}
I'm reading C++ Primer and working on its exercise. It want me to get user's input and separate by space ' '. So I come up with 2 solution.
First solution:
vector<string> vector1;
string input;
string temp = ""; // temperary hold each word value in input.
string x1 = "";
char x2 = 'b';
x1 += x2;
cout << x1 << endl;
getline(cin, input);
input += " ";
for (string::size_type index = 0; index != input.size(); index++)
{
if (!isspace(input[index]))
{
temp += input[index];
}
else
{
if (temp.size() > 0)
{
vector1.push_back(temp);
temp = "";
}
}
}
Second solution
vector<string> vector1;
string input;
string temp = ""; // temperary hold each word value in input.
string x1 = "";
char x2 = 'b';
x1 += x2;
cout << x1 << endl;
getline(cin, input);
//input += " ";
for (string::size_type index = 0; index != input.size(); index++)
{
if (!isspace(input[index]))
{
temp += input[index];
}
else
{
if (temp.size() > 0)
{
vector1.push_back(temp);
temp = "";
}
}
}
if (!temp.empty())
{
vector1.push_back(temp);
}
The difference between them is first solution is add space to user input while second solution check that I don't add last word or not. I want to know which one is better solution for this problem?
If there're better solutions, please tell me.
I would write this:
std::vector<std::string> data;
std::copy(std::istream_iterator< std::string>(std::cin),
std::istream_iterator< std::string>(),
std::back_inserter(data));
It is almost same as #K-ballo's answer, except that I let std::copy read directly from input stream (i.e std::cin) rather than from std::stringstream.
Demo: http://www.ideone.com/f0Gtc
--
Or you could make use of vector's constructor, avoiding std::copy altogether:
std::vector<std::string> data(std::istream_iterator<std::string>(std::cin),
std::istream_iterator<std::string>());
And you're done! Demo : http://www.ideone.com/Szfes
If you find it difficult to read, then use this instead:
std::istream_iterator<std::string> begin(std::cin), end;
std::vector<std::string> data(begin, end);
Demo : http://www.ideone.com/PDcud
In C++, reading space-separated values is quite easy, and is built into the language. I may be wrong, but it looks like you are over-complicating things.
std::string line;
if (std::getline(std::cin, line)) {
std::stringstream ss(line);
std::vector<std::string> inputs_on_this_line(
std::istream_iterator<std::string>(ss)
, std::istream_iterator<std::string>() );
//do stuff with the strings on this line.
}
You can easily split the input from a stream into string separated values, and insert them into a vector with:
string input;
... get the input, perhaps with getline(cin, input); ...
stringstream input_stream( input );
vector<string> vector1;
std::copy(
(std::istream_iterator< std::string >( input_stream )), std::istream_iterator< std::string >()
, std::back_inserter( vector1 )
);
The std::istream_iterator< std::string > pair will iterate over the input_stream by extracting an std::string at a time (a string is read until a whitespace character is found). std::back_inserter will call push_back into your vector for each of those strings.