1
\$\begingroup\$

Are there any issues with below implementation?
Input: from STDIN, a list of strings
Output: serialize to a file called "out.txt" and then unserialize into a list of strings, and output to STDOUT

Goal is not here too much about code organization, but I would like to know if this code can fail for certain types of inputs

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <cstdlib>

using namespace std;

int main()
{
    std::vector<std::string> input;

    std::string tmp;
    while (std::cin >> tmp)
    {
        input.push_back(tmp);
    }

    std::ofstream out("out.txt", std::ios::out);
    for (std::vector<std::string>::const_iterator iter = input.begin();
         iter != input.end();
         ++iter)
    {
        out << (*iter).size() << "|" << *iter;
    }
    out.close();

    std::vector<std::string> output;
    std::ifstream in("out.txt", std::ios::in);
    if (in.is_open())
    {
        std::string tmp;
        if (!in.eof())
        {
            getline(in, tmp);
            size_t pos;
            int length = 0;
            std::string str;

            while (!tmp.empty())
            {
                pos = tmp.find('|');
                if (pos != std::string::npos)
                {
                    length = atoi(tmp.substr(0, pos).c_str());
                    str = tmp.substr(pos+1, length);     
                    tmp = tmp.substr(pos+str.size() + 1);

                    output.push_back(str);
                }
            }
        }

        in.close();
    }

    for (std::vector<std::string>::const_iterator iter = output.begin();
         iter != output.end();
         ++iter)
    {
        std::cout << *iter << "\n";
    }

    return 0;
}
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

Looks like it will work fine.
You preserve the string integrity in the file by maintaining its length as a separate entity that you can check independently. So it should work fine.

Not sure why you copy it to intermediate arrays.
Why not copy directly from input to file then from file to output?

You implement most of the other loops so precisely. But the main loop to read from the file is a bit a bit bulky and messey. With an extra class you can make it look just like the others.

std::vector<std::string> output;
std::ifstream in("out.txt", std::ios::in);
MyStringReader    reader;

while(in >> reader)
{
    output.push_back(reader);
}
in.close();

So now you just need to define the MyClassReader

struct MyStringReader
{
    std::string   data;
    operator std::string const&() {return data;}  // This is used in the line
};                                                // output.push_back(reader) and converts
                                                  // the reader object into a string before
                                                  // it is pushed

std::istream& operator>>(std::istream& stream, MyStringReader& value)
{
    size_t length;
    char   sep    = 'X';

    // Use the stream operators to get the size (and separator)
    // Much nicer than using tha atoi() function.
    //
    if ((stream >> length >> sep) && (sep == '|'))
    {
        // Resize the string to the correct size and put the word into it.
        value.data.resize(length);
        stream.read(&value.data[0], length);
    }
    return stream;
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.