2

I want to create a dynamic vector and each vector element is an array of strings.

The data structure I have in mind is something like this:

VECTOR: 
[0] = [str1, str2, str3]
[1] = [str1, str2, str3]
[2] = [str1, str2, str3]

I correctly insert the values in the res variable BUT my code doesn't work properly: the printing loop is executed 4 times but every time it prints only the LAST element. I believe the problem could be: 1) I don't push the strings array properly in the vector; 2) I don't manage correctly the iteration over the vector and over all the string when I want to print it.

This is my code:

std::vector<std::string*> DatabaseConnector::ExecuteQuery(std::string query, std::vector <std::string> columns)
{
    std::vector<std::string*> results;
    std::string res[columns.size() + 1]; // last value = '\0' to signal end of array

    db_params.res = db_params.stmt->executeQuery(query);
    while (db_params.res->next()) // Access column data by alias or column name
    {
        int i = 0;
        for(std::string s : columns)
            res[i++] = db_params.res->getString(s);

        res[i] = "\0";

        results.push_back(res);
    }

    for(auto el :results)
    {
        int i=0;
        while(el[i].compare("") != 0)
             std::cout << el[i++] << " ";

        std::cout << std::endl;
    }

    return results;
};
2
  • 3
    You're pushing the address of a function local variable into your vector. This is undefined behavior. furthermore youre pushing the same array multiple times? My suggestion to you: use a vector<vector<string>> (also: std::string res[columns.size() + 1]; is not portable code because VLAs are not standardized, they're an extension of your compiler) Commented Sep 14, 2018 at 12:15
  • 1
    I want to create a dynamic vector -- Then just by those words, a "dynamic" vector would be a std::vector<std::vector<whatever>>. The whole purpose of vector is that it can be dynamic, and nothing stops you from having a vector of vectors. Commented Sep 14, 2018 at 12:50

1 Answer 1

5

std::string res[columns.size() + 1]; is a variable length array and you are pushing a pointer to the first element into the vector. You should use std::vector<std::string> res; and std::vector<std::vector<std::string>> results;

std::vector<std::vector<std::string>> DatabaseConnector::ExecuteQuery(std::string query, const std::vector <std::string> &columns)
{
    std::vector<std::vector<std::string>> results;

    db_params.res = db_params.stmt->executeQuery(query);
    while (db_params.res->next()) // Access column data by alias or column name
    {
        std::vector<std::string> res;
        for(std::string s : columns)
            res.push_back(db_params.res->getString(s));

        results.push_back(res);
    }

    for(const auto &el :results)
    {
        for (const auto &res : el)
             std::cout << res << " ";

        std::cout << std::endl;
    }

    return results;
}
Sign up to request clarification or add additional context in comments.

3 Comments

P.S: Minor nitpick but there are a lot of unnecessary copies in that code for(std::string s : columns) should probably be be for(const std::string& s : columns) same for for(auto el :results) and for (auto res : el).
@Borgleader I did not want to change the s loop, because I do not know what getString does with it. I changed the other ones already.
Fair enough. You had my upvote already but I thought I'd point out the (potential) innefficiencies as it's likely that "getString" doesn't modify it's input.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.