0

Boost なしで C++03 を使用しています。

次のような文字列があるとします。その日は「月曜日」です

これを処理したい

THEDAYIS月曜日

つまり、引用符に含まれていないものは大文字に変換し、引用符に含まれていない空白は削除します。

文字列に引用符が含まれていない場合がありますが、含まれている場合は 2 つしかありません。

STL アルゴリズムを使用してみましたが、引用符内にあるか、要素間にないかを覚える方法に行き詰まります。

もちろん、古き良き for ループでそれを行うこともできますが、気の利いた C++ の方法があるかどうか疑問に思っていました。

ありがとう。

これは私がforループを使用しているものです

while (getline(is, str))
{
    // remove whitespace and convert case except in quotes
    temp.clear();
    bool bInQuote = false;
    for (string::const_iterator it = str.begin(), end_it = str.end(); it != end_it; ++it)
    {
        char c = *it;

        if (c == '\"')
        {
            bInQuote = (! bInQuote);
        }
        else
        {
            if (! ::isspace(c))
            {
                temp.push_back(bInQuote ? c : ::toupper(c));
            }
        }
    }
    swap(str, temp);
4

3 に答える 3

1

次のような STL アルゴリズムで何かを行うことができます。

#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>

using namespace std;

struct convert {
   void operator()(char& c) { c = toupper((unsigned char)c); }
};

bool isSpace(char c)
{
  return std::isspace(c);
}

int main() {

    string input = "The day is \"Mon Day\" You know";
    cout << "original string: " << input <<endl;

    unsigned int firstQuote = input.find("\"");
    unsigned int secondQuote = input.find_last_of("\"");

    string firstPart="";
    string secondPart="";
    string quotePart="";
    if (firstQuote != string::npos)
    {
       firstPart = input.substr(0,firstQuote);
       if (secondQuote != string::npos)
       {
          secondPart = input.substr(secondQuote+1);
          quotePart = input.substr(firstQuote+1, secondQuote-firstQuote-1);
                                   //drop those quotes
       }

       std::for_each(firstPart.begin(), firstPart.end(), convert());
       firstPart.erase(remove_if(firstPart.begin(), 
                firstPart.end(), isSpace),firstPart.end());
       std::for_each(secondPart.begin(), secondPart.end(), convert());
       secondPart.erase(remove_if(secondPart.begin(), 
                    secondPart.end(), isSpace),secondPart.end());
       input = firstPart + quotePart + secondPart;
    }
    else //does not contains quote
    {
        std::for_each(input.begin(), input.end(), convert());
        input.erase(remove_if(input.begin(), 
                          input.end(), isSpace),input.end());
    }
     cout << "transformed string: " << input << endl;
     return 0;
}

次の出力が得られました。

original string: The day is "Mon Day" You know
transformed string: THEDAYISMon DayYOUKNOW

あなたが示したテストケースでは:

original string: The day is "Mon Day"
transformed string: THEDAYISMon Day
于 2013-04-12T14:59:40.167 に答える
0

改行の代わりにstringstreamandgetlineを区切り文字として使用できます。\"文字列を 3 つのケースに分割します。文字列の最初の引用符の前の部分、引用符で囲まれた部分、2 番目の引用符の後の部分です。

出力に追加する前に最初と 3 番目の部分を処理しますが、2 番目の部分は処理せずに追加します。

文字列に引用符が含まれていない場合、文字列全体が最初の部分に含まれます。2 番目と 3 番目の部分は空になります。

while (getline (is, str)) {

  string processed;
  stringstream line(str);
  string beforeFirstQuote;
  string inQuotes;

  getline(line, beforeFirstQuote, '\"');
  Process(beforeFirstQuote, processed);

  getline(line, inQuotes, '\"');
  processed += inQuotes;

  getline(line, afterSecondQuote, '\"');
  Process(afterFirstQuote, processed);

}

void Process(const string& input, string& output) {
    for (string::const_iterator it = input.begin(), end_it = input.end(); it != end_it; ++it)
    {
      char c = *it;

        if (! ::isspace(c))
          {
            output.push_back(::toupper(c));
          }

    }
}
于 2013-04-12T14:59:25.263 に答える