На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
  
> Split - разделить строку
    Мне нужно разделить строку, но в С++ метода split нет. Поэтому посмотрев информацию в интернете, я нашла альтернативу, самописный метод split.
    ExpandedWrap disabled
      namespace proj5 {
      ...
      inline bool space(char c){
                  return std::isspace(c);
              }
              
              inline bool notspace(char c){
                  return !std::isspace(c);
              }
              //break a sentence into words
              std::vector<std::string> split(const std::string& s){
                  typedef std::string::const_iterator iter;
                  std::vector<std::string> ret;
                  iter i = s.begin();
                  while(i!=s.end()){
                      i = std::find_if(i, s.end(), notspace); // find the beginning of a word
                      iter j= std::find_if(i, s.end(), space); // find the end of the same word
                      if(i!=s.end()){
                          ret.push_back(std::string(i, j)); //insert the word into vector
                          i = j; // repeat 1,2,3 on the rest of the line.
                      }
                  }
                  return ret;
              }
      ...
      public ref class Form1 : public System::Windows::Forms::Form
      {
      ...
      private: System::Void buildWordList()
               {
                  std::string line;
                  //String ^line = "";
                  setlocale(LC_ALL, "En_US");
                  
                  
       
                  String ^path;
       
                  path = Application::StartupPath+"\\fstream.txt";
                  pin_ptr<const wchar_t> wch = PtrToStringChars(path);
                  std::ifstream in(wch);
                  
       
                  while (getline(in, line))
                  {
                      
                      vector<string> line = split("|");
                      clue_window->label1->Text = gcnew System::String(line[0].c_str());
                      
                  }
       
       }
      ...
      }
      }


    Метод buildWordList() открывает документ считывает его и строки пытается разделить в тех местах, где встречается прямая черта "|". И потом после такого разделения должно произойти вот, что при написании line[0] появляется первый текст до черты, потом line[1], второй текст и т.д. На самом деле у меня вот что получается при line[0] - прямая черта, при line[1] ошибка скриншот. Как правильно объявить метод slpit?
      ExpandedWrap disabled
        std::vector<std::string> split(const std::string &s, char sep)
        {
            std::vector<std::string> items;
            size_t i = 0, j = 0;
            for (;;)
            {
                j = s.find(sep, j);
                if (j == std::string::npos)
                {
                    items.emplace_back(s.substr(i, s.size() - i));
                    break;
                }
         
                items.emplace_back(s.substr(i, j - i));
                i = ++j;
            }
         
            return items;
        }
         
        void main()
        {
                for (auto &item: split("111|222|3333|44444", '|'))
                    std::cout << item << std::endl;
        }
      Сообщение отредактировано: Олег М -
        ExpandedWrap disabled
          std::istringstream iss(s_command);
          std::vector<std::string> vec_c((std::istream_iterator<std::string>{iss}),
                  std::istream_iterator<std::string>());
          Не работает эта строчка
          ExpandedWrap disabled
            items.emplace_back(s.substr(i, s.size() - i));

          Выдаёт ошибку
          error C2039: emplace_back: не является членом "std::vector<_Ty>"
          Попыталась переделать используя этот пример http://qaru.site/questions/220221/emplaceb...orstdmapint-int.
          ExpandedWrap disabled
            items.emplace_back(std::initializer_list<std::pair<std::string>>(s.substr(i, s.size() - i)));

          Всё равно выдаёт ошибку.
          Сообщение отредактировано: Katerina1993 -
            Цитата Katerina1993 @
            Мне нужно разделить строку, но в С++ метода split нет.

            Вариант:
            ExpandedWrap disabled
              // --------------------------------------------------------------------------
              int  split (char* pTarget, const char* pSource, size_t sizeSource, char sep, size_t num)
              {
               int iRetC=-1;
               size_t size = sizeSource; if(size==0) { size = strlen(pSource); }
               
               size_t ind=0, numt=0;
               for(size_t i=0;i<size;++i)
               {
                if(numt != num)      { if(pSource[i]==sep) { ++numt;}  continue; }
                if(pSource[i]==sep)  {                            iRetC=0; break; }
                if(i==(size-1))      { pTarget[ind++]=pSource[i]; iRetC=0; break; }
                pTarget[ind++]=pSource[i];
               }
               if(iRetC==0) {pTarget[ind]=0; iRetC = (int)strlen(pTarget);}
               return iRetC;
              }
              // --------------------------------------------------------------------------
               
              // ...
              // ...
               char target[80];
               const char* pSource = "||||222|3333|44444|QWERTY|||||";
               
               for(size_t i=0;;++i)
               {
                int iRetC = split(target,pSource,0,'|',i); if(iRetC < 0) break;
                printf("%02d:%02d %s\n",i,iRetC,target);
               }
              Не работает
              ExpandedWrap disabled
                for(size_t i=0;;++i)
                 {
                    int iRetC = split(target,pSource,0,'|',i);
                    if(iRetC < 0) break;
                    clue_window->label1->Text = gcnew System::String(iRetC[0].c_str());
                            
                }


              Добавлено
              Ошибка:
              error C2109: для индекса требуется массив или указатель
                Цитата Katerina1993 @
                Выдаёт ошибку
                error C2039: emplace_back: не является членом "std::vector<_Ty>"


                Какой версии у тебя студия? Похоже, что-то древнее.
                Сделай items.push_back(s.substr(i, s.size() - i));
                  У меня Visual Studio 2008
                    Цитата Katerina1993 @
                    У меня Visual Studio 2008

                    Да уж. Зачем она тебе? Поставь 2017
                      Выводит те же самые ошибки, что и были. Я не буду повторятся так как тут уже достаточно информации просто укажу какие посты.

                      Я использовала код из Сообщ. #2 и пытаюсь вызвать этот метод:
                      ExpandedWrap disabled
                        while (getline(in, line))
                        {
                                        
                                vector<string> l = split(line,(char)"|");
                                clue_window->label1->Text = gcnew System::String(l[0].c_str());
                                        
                        }

                      И в итоге я получаю те же самые ошибки, что в Сообщ. #1. Там ещё скриншот прикреплён.
                        Цитата Katerina1993 @
                        vector<string> l = split(line,(char)"|");

                        Что означает (char)"|"? Это ты указатель на строку приводишь к char, так нельзя. Здесь надо '|' - в одинарных кавычках
                          Теперь работает
                          ExpandedWrap disabled
                            while (getline(in, line))
                            {
                                            
                                    vector<string> l = split(line,'|');
                                    clue_window->label1->Text = gcnew System::String(l[2].c_str());
                                            
                            }

                          Цитата
                          Да уж. Зачем она тебе? Поставь 2017

                          Мне тогда придётся менять всё железо, так как у меня Windows XP SP 3.0. С выходом последних операционок все программы стали делать по 64 разрядную систему.

                          P.S.
                          Язык С++ такой сложный раньше на других языках писала программы и не встречала таких тонкостей, что для char нужно ставить одинарные кавычки. Что строки бывают двух типов std и system. Что для системного стринга обязательно нужно ставить крышечку "^". Для разбивки строки нужен свой метод который есть в языке С#, а в С++ нет.

                          Добавлено
                          Он вообще где нибудь используется? Я его например стала изучать лишь потому, что на этом языке есть очень много крутых алгоритмов.
                          Сообщение отредактировано: Katerina1993 -
                            Цитата Katerina1993 @
                            Мне тогда придётся менять всё железо, так как у меня Windows XP SP 3.0. С выходом последних операционок все программы стали делать по 64 разрядную систему.


                            Поставь тогда 2010, он поддерживает стандарт c++ 0x11 и работет на XP

                            Добавлено
                            Цитата Katerina1993 @
                            Язык С++ такой сложный раньше на других языках писала программы и не встречала таких тонкостей, что для char нужно ставить одинарные кавычки.


                            Наверное потому что ты раньше только на скриптах писала, там вообще с типизацией не заморачиваются. Здесь двойные кавычки это указатель на массив char, const char *, а одинарные - char (8-битное число).
                              Цитата
                              Поставь тогда 2010, он поддерживает стандарт c++ 0x11 и работет на XP

                              У меня была такая идея поставить 2010 года, даже копия есть, но я не уверена, что она не битая VS 2008 я уже протестировала много раз, а изучать стала только сейчас. Поэтому в 2008 я уверена на 100 %.
                                Цитата Katerina1993 @
                                Что для системного стринга обязательно нужно ставить крышечку "^".

                                Потому что ты пытаешься программировать на managed c++, не знаю зачем. Он нужен только для совместимости с C#
                                  Katerina1993 вы с этого начинайте, со студии 2008, тогда конечно и мой код не рабочий.

                                  напишите сами функцию сплит

                                  ExpandedWrap disabled
                                    void GetSplitStrings(std::string s, std::vector<std::string>& v_s)
                                    {
                                        unsigned int begin = 0xFFFFFFFF;
                                        unsigned int i = 0;
                                        for (i; i<s.length(); i++)
                                        {
                                            if (begin == 0xFFFFFFFF && s[i] != ' ') begin = i;
                                            if (begin != 0xffffffff && s[i] == ' ')
                                            {
                                                v_s.push_back(s.substr(begin, (i-begin)));
                                                begin = 0xffffffff;
                                            }
                                        }
                                     
                                        if (begin < i)
                                        {
                                            v_s.push_back(s.substr(begin, (i - 1)));
                                        }
                                    }
                                    Цитата Katerina1993 @
                                    Для разбивки строки нужен свой метод который есть в языке С#, а в С++ нет.

                                    Нет, потому что этот split довольно неэффективная штука, соответственно он мало кому пригодится. Ести функция strtok


                                    Цитата Katerina1993 @
                                    У меня была такая идея поставить 2010 года, даже копия есть, но я не уверена,

                                    Это хорошая идея, поставь. Тем более они могут стоять одновременно
                                      Цитата Katerina1993 @
                                      Не работает
                                      ExpandedWrap disabled
                                        for(size_t i=0;;++i)
                                         {
                                            int iRetC = split(target,pSource,0,'|',i);
                                            if(iRetC < 0) break;
                                            clue_window->label1->Text = gcnew System::String(iRetC[0].c_str());
                                                    
                                        }

                                      Тяжёлый случай.
                                      Результат преобразования находится в target.
                                      И это массив байт, а не массив строк.
                                      -----
                                      Если взять исходную строку "111|222|333",
                                      то в target последовательно в цикле
                                      будут находиться "111", "222", "333"

                                      Должно быть как-то так:
                                      ExpandedWrap disabled
                                        clue_window->label1->Text = gcnew System::String(target);


                                      Добавлено
                                      Цитата Олег М @
                                      Это хорошая идея, поставь. Тем более они могут стоять одновременно

                                      А я думаю, это очень плохая идея.
                                      У студента проблемы с синтаксисом С и вообще с самыми основами, а ты предлагаешь
                                      в качестве помощи начать сносить и переустанавливать софт.
                                      Если решение задачи вроде "перебрать символы в строке" зависит от версии студии,
                                      то такое решение не выглядит очень разумным.
                                      Сообщение отредактировано: ЫукпШ -
                                      0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                      0 пользователей:


                                      Рейтинг@Mail.ru
                                      [ Script execution time: 0,0507 ]   [ 17 queries used ]   [ Generated: 29.03.24, 02:06 GMT ]