C ++ Преобразовать вектор с адресом в виде строки в новый вектор - PullRequest
0 голосов
/ 20 сентября 2018

Могу ли я получить совет?Вместо того, чтобы возвращать вектор из функции в виде указателя или ссылки, я возвращаю его в виде строки, содержащей адрес.(У меня была веская причина для этого).

^ Эта часть была успешной, часть, которую я не могу понять, состоит в том, как взять эту возвращенную строку (которая содержит адрес вектора) и сделатьновый вектор с ним.

Это вектор (типа struct), который был передан из функции в строке, содержащей адрес ее памяти:

vector<intructor> intruct;

Преобразование адреса вектора в строку: успешно

string address;
stringstream ss;
ss << &depart;
ss >> address;
return address;

Моя попытка преобразовать его обратно в новый вектор: не удалось

    vector<intructor> getIntructorVector(string filePath)
{
stringstream ss;
string address = VectorCreator(filePath);
vector<intructor> intruct;

ss << address;
ss >> &intruct;

return intruct;
}

Если вам нужно знать, что этот вектор содержит:

struct intructor {
string name;
string dept;
int id;
};

Ответы [ 3 ]

0 голосов
/ 20 сентября 2018

Все это кажется немного неортодоксальным.Это может работать, но только если вы уверены, что исходный вектор останется действительным на протяжении всей процедуры.Адрес внутри строки только указывает на исходный вектор после всех.

struct intructor {
    std::string name;
    std::string dept;
    int id;
};

std::string vec_to_address(std::vector<intructor> const& v)
{
    std::ostringstream oss;
    oss << &v;
    return oss.str();
}

std::vector<intructor>* address_to_vec_ptr(std::string const& s)
{
    void* vp;
    std::istringstream(s) >> vp;
    return reinterpret_cast<std::vector<intructor>*>(vp);
}

int main()
{
    std::vector<intructor> v;
    v.push_back({"Name A", "Dept A", 1});
    v.push_back({"Name B", "Dept B", 2});
    v.push_back({"Name C", "Dept C", 3});

    auto address = vec_to_address(v);

    auto pointer = address_to_vec_ptr(address);

    for(auto const& i: *pointer)
        std::cout << i.name << '\n';

    // if you want a copy of the original vector you can do that
    // like this:
    auto copy_of_original = *pointer;
}

Выход:

Name A
Name B
Name C
0 голосов
/ 20 сентября 2018

Я приведу традиционное предупреждение StackOverflow о том, что «вы, вероятно, на самом деле не хотите этого делать» - ручная манипуляция с указателями вообще не рекомендуется в современном C ++, и есть много плохих вещей, которые могут произойти междувыделение вашего объекта и передача строки, содержащей его адрес.При этом, вот ваша проблема:

& intruct, адрес intruct, является значением - вы не можете писать в него.Ваш текущий код по существу делает следующее:

{
stringstream ss;
string address = VectorCreator(filePath);
vector<intructor> intruct;
vector<intructor>* intructPtr = &intruct;

ss << address;
ss >> intructPtr; // intruct has not been changed

return intruct;
}

Поскольку ваша функция возвращает вектор (а не ссылку или указатель на вектор), кажется, что вы хотите создать копию существующего вектора.указал на.В этом случае вам нужно разделить его на два этапа:

{
stringstream ss;
string address = VectorCreator(filePath);
vector<intructor>* intructPtr;

ss << address;
ss >> intructPtr; // intructPtr now points to the resource from VectorCreator

return *intructPtr; // returns a copy of the resource from VectorCreator
}

Если вы не хотите делать копию, ваша функция должна вернуть ссылку vector<intructor>& или указатель vector<intructor>*- хотя все, что вы делаете, довольно опасно и может в конечном итоге ссылаться или указывать на неверное местоположение, сегментируя вашу программу.

Если вы не можете заставить VectorCreator возвращать умный указатель или сам вектор, будьте очень осторожны, чтобы вектор не удалялся или не увеличивался (что может привести к перераспределению) до того, как высделал копию.

0 голосов
/ 20 сентября 2018

Попробуйте что-то вроде этого:

std::vector<intructor> getIntructorVector(std::string filePath)
{
    std::string address = VectorCreator(filePath);
    std::istringstream iss(address);

    void *intruct;
    ss >> intruct;

    return *static_cast<std::vector<intructor>*>(intruct);
}

Предполагая:

  1. вы НЕ пропускаете std::string через границы процесса.Адрес памяти, принадлежащий одному процессу, НЕ действителен в другом процессе.

  2. оригинал std::vector все еще жив в памяти при вызове getIntructorVector(), в противном случае у вас будет висячий указательпоэтому разыменование будет неопределенным поведением.

Если любое из этих предположений НЕ соответствует действительности, то то, что вы пытаетесь сделать, НЕ МОЖЕТ быть сделано таким образом.Вам нужно будет сериализовать все данные vector в string, а затем десериализовать строку в new vector, например:

std::ostream& quoted(std::ostream &out, const std::string &s)
{
    out << '"';
    for(size_t x = 0; x < s.size(); ++x)
    {
        char c = s[x];
        if ((c == '"') || (c == '\\'))
            out << '\\';            
        out << c;
    }
    out << '"';
    return out;
}

...

size_t size = intruct.size();

std::ostringstream oss;
oss << size;

for(size_t x = 0; x < size; ++x)
{
    intructor &i = intruct[x];
    out << ' '; quoted(out, i.name);
    out << ' '; quoted(out, i.dept);
    out << ' ' << i.id;
}

return oss.str();

std::istream& unquoted(std::istream &in, std::string &s)
{
    if (in >> std::ws)
    {
        if (in.peek() == '"')
        {
            in.ignore();

            s.clear();

            char c;
            while (in.get(c))
            {
                if (c == '\\')
                {
                    if (!in.get(c))
                        break;
                }
                else if (c == '"')
                    break;
                s += c;
            }
        }
        else
            in >> s;
    }

    return in;
}

vector<intructor> getIntructorVector(string filePath)
{
    string data = VectorCreator(filePath);
    istringstream iss(data);
    string s;

    size_t size = 0;
    iss >> size;

    vector<intructor> intruct;
    intruct.reserve(size);

    for(size_t x = 0; x < size; ++x)
    {
        intructor i;

        unquoted(iss, i.name);
        unquoted(iss, i.dept);
        iss >> i.id;
        if (!iss) break;

        intruct.push_back(i);
    }

    return intruct;
}
...