Как перебрать слова строки?

Как упоминалось Ларсом Нощинским, вам нужно исправить выход Out-File. Вы можете установить DefaultParameter Out-File, используя следующие команды.

$PSDefaultParameterValues['Out-File:Encoding'] = 'ASCII'
$PSDefaultParameterValues['Out-File:Width'] = '2147483647'

После настройки параметров по умолчанию вы можете использовать > для экспорта файла патча.

После добавив эти две строки в файл моего профиля, все работает так, как ожидалось.

λ git stash show -p > test3
C:\Users\..\Source\.. [master +1 ~0 -0 !]
λ git apply test3
C:\Users\..\Source\.. [master +1 ~2 -0 !]
2854
задан 27 revs, 14 users 30% 13 October 2018 в 19:34
поделиться

14 ответов

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

#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <iterator>

int main() {
    using namespace std;
    string sentence = "And I feel fine...";
    istringstream iss(sentence);
    copy(istream_iterator<string>(iss),
         istream_iterator<string>(),
         ostream_iterator<string>(cout, "\n"));
}

Вместо того, чтобы копировать извлеченные маркеры в поток вывода, можно было вставить их в контейнер, с помощью того же дженерика copy алгоритм.

vector<string> tokens;
copy(istream_iterator<string>(iss),
     istream_iterator<string>(),
     back_inserter(tokens));

... или создают vector непосредственно:

vector<string> tokens{istream_iterator<string>{iss},
                      istream_iterator<string>{}};
1299
ответ дан 9 revs, 9 users 70% 13 October 2018 в 19:34
поделиться

Для смехотворно большого и вероятно избыточная версия, попробуйте много из за циклы.

string stringlist[10];
int count = 0;

for (int i = 0; i < sequence.length(); i++)
{
    if (sequence[i] == ' ')
    {
        stringlist[count] = sequence.substr(0, i);
        sequence.erase(0, i+1);
        i = 0;
        count++;
    }
    else if (i == sequence.length()-1)  // Last word
    {
        stringlist[count] = sequence.substr(0, i+1);
    }
}

Это не симпатично, но в общем и целом (Запрещающий пунктуацию и убивание других ошибок), это работает!

-8
ответ дан 2 revs, 2 users 98% 13 October 2018 в 19:34
поделиться
  • 1
    полагается на числовые отношения между номерами версий и правильным порядком элементов в списке – necromancer 30 October 2011 в 02:04

Мне нравится следующее, потому что это помещает результаты в вектор, поддерживает строку как delim и дает контроль над хранением пустых значений. Но, это не смотрит как хорошее тогда.

#include <ostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;

vector<string> split(const string& s, const string& delim, const bool keep_empty = true) {
    vector<string> result;
    if (delim.empty()) {
        result.push_back(s);
        return result;
    }
    string::const_iterator substart = s.begin(), subend;
    while (true) {
        subend = search(substart, s.end(), delim.begin(), delim.end());
        string temp(substart, subend);
        if (keep_empty || !temp.empty()) {
            result.push_back(temp);
        }
        if (subend == s.end()) {
            break;
        }
        substart = subend + delim.size();
    }
    return result;
}

int main() {
    const vector<string> words = split("So close no matter how far", " ");
    copy(words.begin(), words.end(), ostream_iterator<string>(cout, "\n"));
}

, Конечно, Повышение имеет split() , который работает частично как этот. И, если 'пробелом', Вы действительно подразумеваете, что любой тип пробела, с помощью разделения Повышения с is_any_of() работает отлично.

66
ответ дан 3 revs, 2 users 70% 13 October 2018 в 19:34
поделиться
  • 1
    Это было действительно полезно, благодарит объяснить. – Mohammad AbuShady 12 February 2014 в 08:55

STL уже не имеет такой метод в наличии.

Однако можно или использовать C strtok() функция при помощи std::string::c_str() участник, или можно записать собственное. Вот пример кода, который я нашел после быстрого поиска Google ( "строковое разделение STL" ):

void Tokenize(const string& str,
              vector<string>& tokens,
              const string& delimiters = " ")
{
    // Skip delimiters at beginning.
    string::size_type lastPos = str.find_first_not_of(delimiters, 0);
    // Find first "non-delimiter".
    string::size_type pos     = str.find_first_of(delimiters, lastPos);

    while (string::npos != pos || string::npos != lastPos)
    {
        // Found a token, add it to the vector.
        tokens.push_back(str.substr(lastPos, pos - lastPos));
        // Skip delimiters.  Note the "not_of"
        lastPos = str.find_first_not_of(delimiters, pos);
        // Find next "non-delimiter"
        pos = str.find_first_of(delimiters, lastPos);
    }
}

Взятый от: http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html

, Если у Вас есть вопросы о примере кода, оставьте комментарий, и я объясню.

И просто потому что это не реализует typedef названный итератором или перегружается <<, оператор не означает, что это - плохой код. Я использую функции C вполне часто. Например, printf и scanf и быстрее, чем [1 115] std::cin и std::cout (значительно), fopen , синтаксис является намного более дружественным для двоичных типов, и они также имеют тенденцию производить меньший EXEs.

не становятся проданными на этом "Элегантность по производительности" соглашение.

52
ответ дан 3 revs, 2 users 82%user19302 13 October 2018 в 19:34
поделиться

Это подобно Stack  вопрос о Переполнении , Как я маркирую строку в C++? .

#include <iostream>
#include <string>
#include <boost/tokenizer.hpp>

using namespace std;
using namespace boost;

int main(int argc, char** argv)
{
    string text = "token  test\tstring";

    char_separator<char> sep(" \t");
    tokenizer<char_separator<char>> tokens(text, sep);
    for (const string& t : tokens)
    {
        cout << t << "." << endl;
    }
}
79
ответ дан 5 revs, 3 users 77% 13 October 2018 в 19:34
поделиться
  • 1
    Да, that' d работа. Однако I' d как он, чтобы быть направленным к localhost:5000/1. I' m пытающийся запросить тот URI, когда загрузка завершена. I' ve расширил мой исходный вопрос теперь и надо надеяться it' ll быть более ясным. – Kar 9 February 2014 в 18:34

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

string line = "a line of text to iterate through";
string word;

istringstream iss(line, istringstream::in);

while( iss >> word )     
{
    // Do something on `word` here...
}
115
ответ дан 4 revs, 2 users 86% 13 October 2018 в 19:34
поделиться
  • 1
    @Kate хорошо. Таким образом, это работает. You' d как он, чтобы быть направленным к localhost:5000/1.. позвольте мне проверить. – newTag 9 February 2014 в 18:38

Я использую это для разделения строки разделителем. Первое помещает результаты в предварительно созданный вектор, вторые возвраты новый вектор.

#include <string>
#include <sstream>
#include <vector>
#include <iterator>

template<typename Out>
void split(const std::string &s, char delim, Out result) {
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim)) {
        *(result++) = item;
    }
}

std::vector<std::string> split(const std::string &s, char delim) {
    std::vector<std::string> elems;
    split(s, delim, std::back_inserter(elems));
    return elems;
}
<час>

Примечание, что это решение не пропускает пустые маркеры, таким образом, следующее найдет 4 объекта, один из которых пуст:

std::vector<std::string> x = split("one:two::three", ':');
2380
ответ дан 20 revs, 15 users 43% 13 October 2018 в 19:34
поделиться

Используя std::stringstream, поскольку Вы имеете превосходные работы, и делаете точно, что Вы хотели. Если Вы просто ищете различный способ сделать вещи, хотя, можно использовать std::find() / std::find_first_of() и std::string::substr() .

Вот пример:

#include <iostream>
#include <string>

int main()
{
    std::string s("Somewhere down the road");
    std::string::size_type prev_pos = 0, pos = 0;

    while( (pos = s.find(' ', pos)) != std::string::npos )
    {
        std::string substring( s.substr(prev_pos, pos-prev_pos) );

        std::cout << substring << '\n';

        prev_pos = ++pos;
    }

    std::string substring( s.substr(prev_pos, pos-prev_pos) ); // Last word
    std::cout << substring << '\n';

    return 0;
}
25
ответ дан 2 revs, 2 users 81% 13 October 2018 в 19:34
поделиться
  • 1
    Зависит от Ваших потребностей и других деталей реализации. Отдельные реализации обновления являются легко тестируемыми, несут единственную ответственность, и Вы могли настроить контейнер МОК для автоматического введения всех лиц, осуществляющих внедрение IUpgradeCommand< > так Вы don' t должны управлять списком вручную. Вы действительно просили решение OO...;) – dahlbyk 28 October 2010 в 13:05

Возможное решение с помощью Повышения могло бы быть:

#include <boost/algorithm/string.hpp>
std::vector<std::string> strs;
boost::split(strs, "string to split", boost::is_any_of("\t "));

Этот подход мог бы быть еще быстрее, чем эти stringstream подход. И так как это - универсальная шаблонная функция, она может использоваться для разделения других типов строк (wchar, и т.д. или UTF-8) использующий все виды разделителей.

Посмотрите документация для деталей.

821
ответ дан 3 revs, 3 users 67% 13 October 2018 в 19:34
поделиться

В общем, не рекомендуется смешивать универсальные шаблоны и массивы в Java, лучше использовать ArrayList.

Если вам необходимо использовать массив, лучший способ справиться с этим - поставить создание массива (ваш пример 2 или 3) отдельным методом и аннотируйте его с помощью @SuppressWarnings ("unchecked").

Также с помощью идеальных типов параметров вы можете удалить все копии строк и списков для дополнительного увеличения скорости.

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

Наконец, он позволяет указать, следует ли вырезать пустые токены из результатов с помощью последнего необязательного параметра.

Все, что ему нужно, это std :: string ... остальные необязательны. Он не использует потоки или библиотеку ускорения, но достаточно гибок, чтобы принимать некоторые из этих внешних типов естественным образом.

но скорее он передает токены в качестве ссылки, что также позволяет вам создавать токены, используя несколько вызовов, если вы того пожелаете.

Наконец, он позволяет указать, следует ли вырезать пустые токены из результатов с помощью последнего необязательного параметра.

Все, что ему нужно, это std :: string ... остальные необязательны. Он не использует потоки или библиотеку ускорения, но достаточно гибок, чтобы принимать некоторые из этих внешних типов естественным образом.

но скорее он передает токены в качестве ссылки, что также позволяет вам создавать токены, используя несколько вызовов, если вы того пожелаете.

Наконец, он позволяет указать, следует ли вырезать пустые токены из результатов с помощью последнего необязательного параметра.

Все, что ему нужно, это std :: string ... остальные необязательны. Он не использует потоки или библиотеку ускорения, но достаточно гибок, чтобы принимать некоторые из этих внешних типов естественным образом.

179
ответ дан 22 November 2019 в 19:47
поделиться

Вот еще один способ...

void split_string(string text,vector<string>& words)
{
  int i=0;
  char ch;
  string word;

  while(ch=text[i++])
  {
    if (isspace(ch))
    {
      if (!word.empty())
      {
        words.push_back(word);
      }
      word = "";
    }
    else
    {
      word += ch;
    }
  }
  if (!word.empty())
  {
    words.push_back(word);
  }
}
9
ответ дан 22 November 2019 в 19:47
поделиться

Еще один гибкий и быстрый способ

template<typename Operator>
void tokenize(Operator& op, const char* input, const char* delimiters) {
  const char* s = input;
  const char* e = s;
  while (*e != 0) {
    e = s;
    while (*e != 0 && strchr(delimiters, *e) == 0) ++e;
    if (e - s > 0) {
      op(s, e - s);
    }
    s = e + 1;
  }
}

Использовать его с вектором строк (Edit: Since someone pointed not to inherit STL classes... hrmf ;) ) :

template<class ContainerType>
class Appender {
public:
  Appender(ContainerType& container) : container_(container) {;}
  void operator() (const char* s, unsigned length) { 
    container_.push_back(std::string(s,length));
  }
private:
  ContainerType& container_;
};

std::vector<std::string> strVector;
Appender v(strVector);
tokenize(v, "A number of words to be tokenized", " \t");

Вот и все! И это только один из способов использования токенизатора, например, как просто считать слова:

class WordCounter {
public:
  WordCounter() : noOfWords(0) {}
  void operator() (const char*, unsigned) {
    ++noOfWords;
  }
  unsigned noOfWords;
};

WordCounter wc;
tokenize(wc, "A number of words to be counted", " \t"); 
ASSERT( wc.noOfWords == 7 );

Ограничено воображением ;)

36
ответ дан 22 November 2019 в 19:47
поделиться

Существует функция с именем strtok .

#include<string>
using namespace std;

vector<string> split(char* str,const char* delim)
{
    char* saveptr;
    char* token = strtok_r(str,delim,&saveptr);

    vector<string> result;

    while(token != NULL)
    {
        result.push_back(token);
        token = strtok_r(NULL,delim,&saveptr);
    }
    return result;
}
20
ответ дан 22 November 2019 в 19:47
поделиться

Я использую этот простак, потому что мы получили наш класс String "специальный" (т.е. не стандартный):

void splitString(const String &s, const String &delim, std::vector<String> &result) {
    const int l = delim.length();
    int f = 0;
    int i = s.indexOf(delim,f);
    while (i>=0) {
        String token( i-f > 0 ? s.substring(f,i-f) : "");
        result.push_back(token);
        f=i+l;
        i = s.indexOf(delim,f);
    }
    String token = s.substring(f);
    result.push_back(token);
}
7
ответ дан 22 November 2019 в 19:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: