2012-04-27 2 views
1

Я пытаюсь разбить строку на «символы» с помощью C++ для дальнейшей работы. Я давно ничего не писал на C++, так что простите меня, если что-то по сути не так с этим кодом.Почему эта функция не разбивает эту входную строку?

Целью функции symbolize() является разбиение строки, например «5 + 5», на строки vector, например {"5","+","5"}. Это не работает. Если вы считаете, что код слишком грязный, попробуйте упростить его.

Вот мой код до сих пор:

#include <iostream> 
#include <string> 
#include <vector> 
#include <ctype.h> 
#include <sstream> 

using namespace std; 

vector<string> symbolize(string); 

int main(int argc, const char * argv[]) 
{ 

    string input; 
    cin >> input; 

    vector<string> symbols; 

    symbols = symbolize(input); 

    for(int i=0;i<symbols.size();i++){ 
     cout<<symbols.at(i) << endl; 
    } 

    return 0; 
} 


vector<string> symbolize(string input){ 
    int position = 0; 
    char c; 
    stringstream s; 
    vector<string> symbols; 
    enum symbolType {TEXT,OPERATOR}symbolType,charType; 

    while(position < input.size()){ 
     c = input.at(position); 
     if(isalnum(c))symbolType = TEXT; 
     else symbolType = OPERATOR; 
     charType = symbolType; 

     while(symbolType == charType){ 
      s << c; 
      position++; 
      if(position>=input.length())break; 
      c = input.at(position); 
      if(isalnum(c)) charType = TEXT; 
      else charType = OPERATOR; 
     } 

     symbols.push_back(s.str()); 
     s.clear(); 
    } 

    return symbols; 
} 

Спасибо за взглянуть.

Edit: Кстати, я должен отметить, что функция возвращает кулак "маркер", например, "5 + 5" -> "5"

Edit2: Я ошибся. Я просто попробовал «5 + 5», и он вернулся {"5","5+","5+5"}. Однако он возвращает только первый пробел. Извините за беспорядок!

Редактировать3: Спасибо всем! Для тех, кто может прийти на эту страницу, в будущем, вот код, когда все сказано и сделано:

#include <iostream> 
#include <string> 
#include <vector> 
#include <ctype.h> 
#include <sstream> 

using namespace std; 

vector<string> symbolize(string); 

int main(int argc, const char * argv[]) 
{ 

    string input; 
    getline(cin,input); 

    vector<string> symbols; 

    symbols = symbolize(input); 

    for(int i=0;i<symbols.size();i++){ 
     cout<<symbols.at(i) << endl; 
    } 

    return 0; 
} 


vector<string> symbolize(string input){ 
    int position = 0; 
    char c; 
    //stringstream s; 
    vector<string> symbols; 
    enum symbolType {TEXT,OPERATOR}symbolType,charType; 

    while(position < input.size()){ 
     stringstream s; 
     c = input.at(position); 
     if(isalnum(c))symbolType = TEXT; 
     else symbolType = OPERATOR; 
     charType = symbolType; 

     while(symbolType == charType){ 
      s << c; 
      position++; 
      if(position>=input.length())break; 
      c = input.at(position); 
      if (isspace(c)||c=='\n'){position++; break;} 
      if(isalnum(c)) charType = TEXT; 
      else charType = OPERATOR; 
     } 

     symbols.push_back(s.str()); 
    } 

    return symbols; 
} 
+0

Что такое _supposed_, чтобы вернуться.Из вашего последнего комментария, «он возвращает только первый перед пробелом», похоже, ваша жалоба заключается в том, что «5 + 5 6 + 6» только анализирует пространство и останавливается. Если это так, это потому, что вы только делаете «cin >> input» один раз и читаете до пробела. – abarnert

+0

Должен ли быть тест на пробелы? Логика предполагает, что ничего, кроме буквенно-цифрового, не является оператором. – wallyk

+0

@abarnert Да, это была моя оригинальная проблема. Каким другим способом я могу использовать пробелы? – Hassan

ответ

3

Если вы хотите, чтобы прочитать всю строку, а не только одного слова, использовать GetLine вместо оператора >>. См. http://www.cplusplus.com/reference/string/getline/ для получения дополнительной информации или просто измените строку 14 на «getline (cin, input);».

Кроме того, если вы хотите вывести «5», «+», «5» вместо «5», «5+», «5 + 5», вам необходимо каждый раз переустанавливать строковый поток через цикл , и ясно это не делает. Самый простой способ - просто объявить строковый поток во внешнем цикле и избавиться от ясного вызова.

+0

Код as-is будет обрабатывать пробелы как операторы (потому что они являются символами, которые не являются alnum). Если вы хотите игнорировать их, вам нужно добавить для этого логику, например if (isspace (c)) {position ++; Продолжать; }. Или вы можете просто вернуться к чтению слова за раз с оператором >>, но оберните его в цикле. – abarnert

+0

@abarnet Спасибо. Однако, я думаю, вы имели в виду: 'if (isspace (c)) {position ++; break;} ', так как он должен быть разбит на внешний цикл в пространстве. Я пробовал это, он работает. – Hassan

3

stringstream :: ясно не очищает буфер строки (только состояние ошибки).

вы можете использовать stringstream::str(x) установить буфер строки, так s.str(string()) или s.str("") вместо s.clear() очистит буфер строки.

Кроме того, operator<<(istream, ...) только читает до пробела.

Для чтения вы можете попробовать использовать:

  • IStream :: прочтешь один символ за один раз; или;
  • std :: getline (istream, ...) читать по одной строке за раз; или;
  • istream :: read читать произвольное количество символов в буфер.

http://en.cppreference.com/w/cpp/io/basic_istream

+0

istream :: читать, вероятно, не то, что он хочет. Он считывает размер вашего буфера. Предположительно, он заранее не знает размер ввода, что означает, что ему придется перебирать чтение и накапливать буфер (поскольку токен может пересекать границу между чтениями), что намного сложнее. – abarnert

+0

чтение в ringbuffer является наиболее эффективным способом, а также сложнее всего реализовать. Я переведу его до конца списка. –

+0

Это все еще слишком сложно. istream :: getline по-прежнему требует выделения буфера и может читать только столько символов, сколько вы выделили. Намного проще просто вызвать std :: getline (istream &, string &), если вы не беспокоитесь о патологически длинных строках. – abarnert

1

При перемещении stringstream s; внутри первого while цикла, вы должны достичь своей цели.

s.clear() только resets the error state flags для stringstream, это не так, как std::string::clear()

+0

Спасибо за ответ! Извините, я не могу принять более одного. – Hassan

+0

@ Hassan no probs :) – Fraser

Смежные вопросы