Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Special Interest Groups
  3. C++ Gurus
  4. Convert QStringList to QVector<const char*>
Forum Updated to NodeBB v4.3 + New Features

Convert QStringList to QVector<const char*>

Scheduled Pinned Locked Moved Unsolved C++ Gurus
7 Posts 4 Posters 2.7k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • magrifM Offline
    magrifM Offline
    magrif
    wrote on last edited by
    #1

    I'm trying convert QStringList to const char**. I decide make copy to QVector<const char*> and next invoke data() member func. But somthing went wrong :)
    Can you explain next behavior:

    1. At code snippet 1 I'm get output ENDING, ENDING, ENDING, ENDING, but in 2 as expected - wordFirst , Second, 123456789 , ENDING???

      QStringList qtStrings{};
      qtStrings << "wordFirst" << "Second"<< "123456789" << "ENDING";
      vector<std::string> stlStrings { "wordFirst" , "Second", "123456789" , "ENDING"};
      
      // 1
      QVector<const char*> v4;
      for(const auto& qtSt : qtStrings) {
          v4.push_back(qtSt.toStdString().c_str());
      }
      for(int i(0); i < v4.size() ; ++i) {
          cout << " "  << v4.at(i) << endl;
      }
      
      //2
      QVector<const char*> v6;
      for(const auto& stlSt: stlStrings) {
          v6.push_back(stlSt.c_str());
      }
      for(int i(0); i < v6.size() ; ++i) {
          cout << " " << v6.at(i) << endl;
      }
      
    2. What is the gaps after elements in vector in next code?

    qt.png

        QVector<const char*> v6;
        for(const auto& stlSt : stlStrings) {
            v6.push_back(stlSt.c_str());
        }
        for(int i(0); i < v6.size() ; ++i) {
            cout << " " << v6.at(i) << endl;
        }
    
    1. And, what is correct way convert QStringList to const char**?

    Thanks.

    1 Reply Last reply
    0
    • fcarneyF Offline
      fcarneyF Offline
      fcarney
      wrote on last edited by fcarney
      #2

      c strings are null terminated. This is represented by the character int value 0.

      In 1. you are copying only the pointer to a location in memory and not the string itself. If you want to copy the memory you will to create a structure that can hold that memory. Then copy the string into that memory. Later you will have to delete that memory as well.

      c_str() is returning a pointer that on last call is pointing to ENDING. Apparently the temporary buffer it is using is the same for the pointers you get.

      new char[str_length+1] // need the +1 for the null termination
      std::memcpy to copy data into that location

      Later you will need to delete that memory you allocated.

      C++ is a perfectly valid school of magic.

      1 Reply Last reply
      1
      • magrifM Offline
        magrifM Offline
        magrif
        wrote on last edited by
        #3

        But why vector does not allocate memory for const char* by themselves? Why I need stoop to C-style? I think memory allocation by hands breaks down adjacent memory locations.

        My implementation for 3

           const auto stringCount { qtStrings.size() };
           std::size_t size {
               std::accumulate(qtStrings.begin(), qtStrings.end(), 0,
                   [](std::size_t sz, const QString& str) {
                       return std::plus<std::size_t>()(sz, str.size());
                   })
               + static_cast<std::size_t>(stringCount) //for '\0'
           };
        
           QScopedArrayPointer<char> array { new char[size] };
           std::memset(array.data(), '\0', size);
           char* index { array.data() };
           char* resultArray[stringCount];
           quint16 k{0};
           std::for_each(qtStrings.begin(), qtStrings.end(), [&resultArray, &k, &index] (const QString& str) {
               resultArray[k++] = index;
               const auto strSz { str.size() };
               std::memcpy(index, qUtf8Printable(str), strSz);
               index += strSz + 1;
           });
        
        aha_1980A 1 Reply Last reply
        0
        • magrifM magrif

          But why vector does not allocate memory for const char* by themselves? Why I need stoop to C-style? I think memory allocation by hands breaks down adjacent memory locations.

          My implementation for 3

             const auto stringCount { qtStrings.size() };
             std::size_t size {
                 std::accumulate(qtStrings.begin(), qtStrings.end(), 0,
                     [](std::size_t sz, const QString& str) {
                         return std::plus<std::size_t>()(sz, str.size());
                     })
                 + static_cast<std::size_t>(stringCount) //for '\0'
             };
          
             QScopedArrayPointer<char> array { new char[size] };
             std::memset(array.data(), '\0', size);
             char* index { array.data() };
             char* resultArray[stringCount];
             quint16 k{0};
             std::for_each(qtStrings.begin(), qtStrings.end(), [&resultArray, &k, &index] (const QString& str) {
                 resultArray[k++] = index;
                 const auto strSz { str.size() };
                 std::memcpy(index, qUtf8Printable(str), strSz);
                 index += strSz + 1;
             });
          
          aha_1980A Offline
          aha_1980A Offline
          aha_1980
          Lifetime Qt Champion
          wrote on last edited by
          #4

          Hi @magrif,

          I'm trying convert QStringList to const char**.

          Maybe you should start explaining us why you want to do this resp. what you want to achive.

          I guess you already know that QStringListis a QList<QString> and QString is an array of QChar, which is not compatible to char.

          I decide make copy to QVector<const char*>

          So far so good.

          and next invoke data() member func. But somthing went wrong :)

          Yeah, because you used the data from an temporary object, which is destroyed and therefore the memory your pointer points to is no longer valid.

          As @fcarney already said, when working with pointers you have to take care of the memory yourself.

          Regards

          Qt has to stay free or it will die.

          magrifM 1 Reply Last reply
          2
          • aha_1980A aha_1980

            Hi @magrif,

            I'm trying convert QStringList to const char**.

            Maybe you should start explaining us why you want to do this resp. what you want to achive.

            I guess you already know that QStringListis a QList<QString> and QString is an array of QChar, which is not compatible to char.

            I decide make copy to QVector<const char*>

            So far so good.

            and next invoke data() member func. But somthing went wrong :)

            Yeah, because you used the data from an temporary object, which is destroyed and therefore the memory your pointer points to is no longer valid.

            As @fcarney already said, when working with pointers you have to take care of the memory yourself.

            Regards

            magrifM Offline
            magrifM Offline
            magrif
            wrote on last edited by
            #5

            @aha_1980
            Thanks for reply.
            I'm doing simple wrapper around one C interface. And one func take in const char** . Code above works fine.
            But in process of work and this topic discussion was appeared some questions:
            When we push const char* (or som pointer) to QVector it creates deep copy of data or not? In particular, when push null-terminated char*.
            If not, how is achieved sequential memory locations when we push pointers to various sections of dynamically allocated memory?
            Thanks!

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              Hi,

              You have a QVector of pointers to chars. There's no reason for QVector to do any deep copy of the data stored behind these pointers.

              Beside the fact that you are responsible for the data handling, you should also take into account that QString is not a wrapper around a char*. It stores strings in utf-16.

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              1
              • fcarneyF Offline
                fcarneyF Offline
                fcarney
                wrote on last edited by
                #7

                Since qtSt.toStdString() is returning a temporary why not just turn QStringList into a std::vector<string> and maintain for the lifetime or your pointers. That way the pointer returned by c_str remains valid. Probably better than managing the memory with new/delete.

                C++ is a perfectly valid school of magic.

                1 Reply Last reply
                1

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved