Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.224.38.3] |
|
Сообщ.
#1
,
|
|
|
Мне нужно разделить строку, но в С++ метода split нет. Поэтому посмотрев информацию в интернете, я нашла альтернативу, самописный метод split.
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? |
Сообщ.
#2
,
|
|
|
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; } |
Сообщ.
#3
,
|
|
|
std::istringstream iss(s_command); std::vector<std::string> vec_c((std::istream_iterator<std::string>{iss}), std::istream_iterator<std::string>()); |
Сообщ.
#4
,
|
|
|
Не работает эта строчка
items.emplace_back(s.substr(i, s.size() - i)); Выдаёт ошибку error C2039: emplace_back: не является членом "std::vector<_Ty>" Попыталась переделать используя этот пример http://qaru.site/questions/220221/emplaceb...orstdmapint-int. items.emplace_back(std::initializer_list<std::pair<std::string>>(s.substr(i, s.size() - i))); Всё равно выдаёт ошибку. |
Сообщ.
#5
,
|
|
|
Цитата Katerina1993 @ Мне нужно разделить строку, но в С++ метода split нет. Вариант: // -------------------------------------------------------------------------- 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); } |
Сообщ.
#6
,
|
|
|
Не работает
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: для индекса требуется массив или указатель |
Сообщ.
#7
,
|
|
|
Цитата Katerina1993 @ Выдаёт ошибку error C2039: emplace_back: не является членом "std::vector<_Ty>" Какой версии у тебя студия? Похоже, что-то древнее. Сделай items.push_back(s.substr(i, s.size() - i)); |
Сообщ.
#8
,
|
|
|
У меня Visual Studio 2008
|
Сообщ.
#9
,
|
|
|
Цитата Katerina1993 @ У меня Visual Studio 2008 Да уж. Зачем она тебе? Поставь 2017 |
Сообщ.
#10
,
|
|
|
Выводит те же самые ошибки, что и были. Я не буду повторятся так как тут уже достаточно информации просто укажу какие посты.
Я использовала код из Сообщ. #2 и пытаюсь вызвать этот метод: while (getline(in, line)) { vector<string> l = split(line,(char)"|"); clue_window->label1->Text = gcnew System::String(l[0].c_str()); } И в итоге я получаю те же самые ошибки, что в Сообщ. #1. Там ещё скриншот прикреплён. |
Сообщ.
#11
,
|
|
|
Цитата Katerina1993 @ vector<string> l = split(line,(char)"|"); Что означает (char)"|"? Это ты указатель на строку приводишь к char, так нельзя. Здесь надо '|' - в одинарных кавычках |
Сообщ.
#12
,
|
|
|
Теперь работает
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. Что для системного стринга обязательно нужно ставить крышечку "^". Для разбивки строки нужен свой метод который есть в языке С#, а в С++ нет. Добавлено Он вообще где нибудь используется? Я его например стала изучать лишь потому, что на этом языке есть очень много крутых алгоритмов. |
Сообщ.
#13
,
|
|
|
Цитата Katerina1993 @ Мне тогда придётся менять всё железо, так как у меня Windows XP SP 3.0. С выходом последних операционок все программы стали делать по 64 разрядную систему. Поставь тогда 2010, он поддерживает стандарт c++ 0x11 и работет на XP Добавлено Цитата Katerina1993 @ Язык С++ такой сложный раньше на других языках писала программы и не встречала таких тонкостей, что для char нужно ставить одинарные кавычки. Наверное потому что ты раньше только на скриптах писала, там вообще с типизацией не заморачиваются. Здесь двойные кавычки это указатель на массив char, const char *, а одинарные - char (8-битное число). |
Сообщ.
#14
,
|
|
|
Цитата Поставь тогда 2010, он поддерживает стандарт c++ 0x11 и работет на XP У меня была такая идея поставить 2010 года, даже копия есть, но я не уверена, что она не битая VS 2008 я уже протестировала много раз, а изучать стала только сейчас. Поэтому в 2008 я уверена на 100 %. |
Сообщ.
#15
,
|
|
|
Цитата Katerina1993 @ Что для системного стринга обязательно нужно ставить крышечку "^". Потому что ты пытаешься программировать на managed c++, не знаю зачем. Он нужен только для совместимости с C# |
Сообщ.
#16
,
|
|
|
Katerina1993 вы с этого начинайте, со студии 2008, тогда конечно и мой код не рабочий.
напишите сами функцию сплит 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))); } } |
Сообщ.
#17
,
|
|
|
Цитата Katerina1993 @ Для разбивки строки нужен свой метод который есть в языке С#, а в С++ нет. Нет, потому что этот split довольно неэффективная штука, соответственно он мало кому пригодится. Ести функция strtok Цитата Katerina1993 @ У меня была такая идея поставить 2010 года, даже копия есть, но я не уверена, Это хорошая идея, поставь. Тем более они могут стоять одновременно |
Сообщ.
#18
,
|
|
|
Цитата Katerina1993 @ Не работает 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" Должно быть как-то так: clue_window->label1->Text = gcnew System::String(target); Добавлено Цитата Олег М @ Это хорошая идея, поставь. Тем более они могут стоять одновременно А я думаю, это очень плохая идея. У студента проблемы с синтаксисом С и вообще с самыми основами, а ты предлагаешь в качестве помощи начать сносить и переустанавливать софт. Если решение задачи вроде "перебрать символы в строке" зависит от версии студии, то такое решение не выглядит очень разумным. |