3

I'm writing 2 programs, the first program has an array of integers

vector<int> v = {10, 200, 3000, 40000};

Then it converts the vector into string

int i;
stringstream sw;
string stringword;

for (i=0;i<v.size();i++) 
{
    sw << v[i] << ',';
}
stringword = sw.str();
cout << "Vector in string : "<< stringword << endl;

And then write it in a file

ofstream myfile;
myfile.open ("writtentext");
myfile << stringword;
myfile.close();

The output :

Vector in string : 10,200,3000,40000

The second program will read the file, convert the string back to integer, and then push it back to vector.

The code :

string stringword;

ifstream myfile;
myfile.open ("writtentext");
getline (myfile,stringword);
cout << "Read From File = " << stringword << endl;

cout << "Convert back to vector = " ;
for (int i=0;i<stringword.length();i++)
{
    if (stringword.find(','))
    {
        int value;
        istringstream (stringword) >> value;
        v.push_back(value);
        stringword.erase(0, stringword.find(','));
    }
}
for (int j=0;j<v.size();j++) 
{
    cout << v.at(j) << " " ;
}

The problem is, it can only convert and push back the first element, the rest is erased. Here is the output :

Read From File = 10,200,3000,40000,
Convert back to vector = 10

What did I do wrong? Thanks

dulipat
  • 171
  • 2
  • 4
  • 12
  • skip the string part and just write the vector to a file. – andre Aug 20 '13 at 13:12
  • 1
    Check what `stringword.find(',')` returns (http://en.cppreference.com/w/cpp/string/basic_string/find). If that doesn't make it obvious, run the code through a debugger and you'll see. And while you are at it, check also the documentation for `erase`: http://en.cppreference.com/w/cpp/string/basic_string/erase. – R. Martinho Fernandes Aug 20 '13 at 13:19

6 Answers6

4

There's problem with your for loop

Consider this:

while(1) //Use a while loop, "i" isn't doing anything for you
{
    //if comman not found find return string::npos

    if (stringword.find(',')!=std::string::npos)
    {
        int value;
        istringstream (stringword) >> value;

        v.push_back(value);

       //Erase all element including comma
        stringword.erase(0, stringword.find(',')+1);
    }
    else 
       break; //Come out of loop
}

Instead, just use std::stringstream to read back from file

std::stringstream ss(stringword);
int value;
while (ss >> value)
{
    v.push_back(value);

    if (ss.peek() == ',')
        ss.ignore();
}

for (int j=0;j<v.size();j++)  //Fix variables
{
    cout << v.at(j) << " " ; // Can use simply v[j]
}
P0W
  • 46,614
  • 9
  • 72
  • 119
0
for (int j=0;j<v.size();i++) 
{
    cout << v.at(i) << " " ;
}

should be

for (int j=0;j<v.size();j++) 
{
    cout << v.at(j) << " " ;
}

i is not declared in the for loop

Sakthi Kumar
  • 3,047
  • 15
  • 28
0

You can skip the string conversion. All stream can handle int types.

std::vector<int> to output:

#include <iostream>
#include <iterator>
#include <vector>

int main() {
    std::vector<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    v.push_back(4);
    std::ostream_iterator<int> output_iterator(std::cout, ",");
    std::copy(v.begin(), v.end(), output_iterator);
}

input to std::vector<int>:

#include <iostream>
#include <vector>
#include <sstream>
using namespace std;

int main() {
    std::vector<int> v;
    int value;

    std::string line;
    while(getline(cin, line, ',')) {
        std::stringstream ss(line);
        ss >> value
        v.push_back(value);
    }
    typedef std::vector<int>::iterator iter;
    iter end = v.end();
    for(iter it = v.begin(); it != end; ++it) {
        std::cout << *it << endl;
    }
}
andre
  • 7,018
  • 4
  • 43
  • 75
0

this is only a mistake you did:

for (int j=0;j<v.size();i++) 
{
    cout << v.at(i) << " " ;
}

but the implement is too inefficient here:

for (int i=0;i<stringword.length();i++)
{
    if (stringword.find(','))
    {
        int value;
        istringstream (stringword) >> value;
        v.push_back(value);
        stringword.erase(0, stringword.find(','));
    }
}

you may do like this, just a suggestion:

#include <iostream>
#include <string>
#include <vector>
#include <stdlib.h>

int ConvertStringToInt(const std::string &str, std::vector<int> &ints)
{
    int count_int = 0;
    std::string string_int;

    size_t start = 0;
    size_t end   = 0;

    while ((end = str.find(',', start)) != std::string::npos)
    {
        string_int.assign(str, start, end - start);
        ints.push_back(atoi(string_int.c_str()));
        start = end + 1;
        ++count_int;
    }
    if (start != str.size())
    {
        ints.push_back(atoi(str.c_str() + start));
        ++count_int;
    }
    return count_int;
}

int main(int argc, char *const argv[]) 
{
    std::vector<int> ints;
    std::string str = "123,456,789 ";
    std::cout << ConvertStringToInt(str, ints) << std::endl;
    for (size_t i = 0; i != ints.size(); ++i)
    {
        std::cout << ints[i] << std::endl;
    }
    return 0;
}
0

You can make your programs simpler:

#include <algorithm>
#include <fstream>
#include <iostream>
#include <iterator>
#include <vector>

// output
int main()
{
    // my compiler doesn't support initializer lists yet :(
    std::vector<int> v(4);
    v[0] = 10;
    v[1] = 200;
    v[2] = 3000;
    v[3] = 40000;

    std::ofstream fout("mytestfile.txt");
    std::copy(v.begin(), v.end(), std::ostream_iterator<int>(fout, ","));
    fout.close();
    return 0;
}

// input
struct int_reader : std::ctype<char>
{
    int_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[','] = std::ctype_base::space;
        rc['\n'] = std::ctype_base::space;
        return &rc[0];
    }
};

int main()
{
    std::vector<int> v;
    std::ifstream fin("mytestfile.txt", std::ifstream::in);
    fin.imbue(std::locale(std::locale(), new int_reader()));
    std::copy(std::istream_iterator<int>(fin), std::istream_iterator<int>(), std::back_inserter<std::vector<int>>(v));
    fin.close();

    std::cout << "You read in:  ";
    std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
    return 0;
}
Zac Howland
  • 15,777
  • 1
  • 26
  • 42
0

Though this is handcrafted instead of using std::stringstream, I find it quite easy to understand.

std::vector<std::string> StringToVector (const std::string s,
                                         const char token)
{
  std::vector<std::string> v;

  size_t posLast = 0, pos = 0;
  while((pos = s.find(token, pos)) != std::string::npos)
  {
    if(s[pos] != s[posLast])
      v.push_back(s.substr(posLast, pos - posLast));
    posLast = ++pos;
  }
  if(s[posLast] != 0)  // If there is no terminating token found
    v.push_back(s.substr(posLast));

  return v;
}

Demo with various test cases.

iammilind
  • 68,093
  • 33
  • 169
  • 336