1

今後の作業のために、C++ を使用して文字列を「シンボル」に分割しようとしています。私は長い間 C++ で何も書いていないので、このコードに本質的な問題がある場合はご容赦ください。

以下の関数の目的は、 "5+5" などの文字列を文字列symbolize()に分割することです。動いていない。コードが乱雑すぎると思われる場合は、単純化する方法を提案してください。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;
}

ご覧いただきありがとうございます。

編集:ところで、関数が最初の「トークン」を返すことに言及する必要があります。たとえば、「5 + 5」->「5」です。

編集2:私は間違っていました。「5 + 5」を試したところ、 が返され{"5","5+","5+5"}ました。ただし、スペースの前の最初のもののみを返します。混乱させて申し訳ありません!

Edit3: ありがとうございました! 将来このページに出くわす可能性がある人のために、すべてが完了したときのコードを次に示します。

#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;
}
4

3 に答える 3

3

stringstream::clear は文字列バッファをクリアしません (エラー状態のみ)。

stringstream::str(x)文字列バッファを設定するために使用できるので、s.str(string())またはs.str("")代わりにs.clear()文字列バッファをクリアします。

また、operator<<(istream, ...)空白までのみ読み取ります。

読むには、次を使用してみてください。

  • istream::get で一度に 1 文字を読み取る; また;
  • std::getline(istream,...) で一度に 1 行ずつ読み取ります。また;
  • istream::read を使用して、任意の数の文字をバッファーに読み込みます。

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

于 2012-04-27T22:27:13.527 に答える
3

1 単語ではなく行全体を読みたい場合は、operator>> の代わりに getline を使用します。詳細については、 http://www.cplusplus.com/reference/string/getline/を参照するか、14 行目を「getline(cin, input);」に変更してください。

また、"5"、"5+"、"5+5" の代わりに "5"、"+"、"5" を出力したい場合は、ループのたびに stringstream をリセットする必要があり、クリアは行いません。それをしないでください。これを回避する最も簡単な方法は、外側のループで stringstream を宣言し、clear 呼び出しを取り除くことです。

于 2012-04-27T22:35:47.180 に答える
1

stringstream s;最初のループ内に移動whileすると、目的を達成する必要があります。

s.clear()文字列ストリームのエラー状態フラグをリセットするだけで、似ていませんstd::string::clear()

于 2012-04-27T22:32:20.493 に答える