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

只是为了一笑而过,使用自定义迭代器std::copy和 a std::back_insert_iterator,以及operator++知道跳过空格并在引号字符上设置标志的 an:

CustomStringIt& CustomStringIt::operator++ ()
{
    if(index_<originalString_.size())
        ++index_;

    if(!inQuotes_ && isspace(originalString_[index_]))
        return ++(*this);

    if('\"'==originalString_[index_])
    {
        inQuotes_ = !inQuotes_;
        return ++(*this);
    }

    return *this;
}

char CustomStringIt::operator* () const
{
    char c = originalString_[index_];
    return inQuotes_ ? c : std::toupper(c) ; 
}

完整代码在这里。

于 2013-04-12T15:23:01.403 回答
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

您可以使用andstringstream字符作为分隔符而不是换行符。将您的字符串分成 3 种情况:第一个引号之前的字符串部分、引号中的部分和第二个引号之后的部分。getline\"

您将在添加到输出之前处理第一部分和第三部分,但添加第二部分而不进行处理。

如果您的字符串不包含引号,则整个字符串将包含在第一部分中。第二和第三部分将是空的。

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 回答