除了引号之外,删除字符串中的空格,转换大小写

时间:2013-04-12 14:21:02

标签: c++

我正在使用没有Boost的C ++ 03。

假设我有一个字符串如......日子是“星期一”

我想将其处理为

THEDAYISMon日

也就是说,转换为大写不在引号中的内容,并删除引号中没有的空格。

字符串可能不包含引号,但如果包含引号,则只有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);

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

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

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) ; 
}

Full code here.

答案 2 :(得分:0)

您可以将stringstreamgetline\"字符一起用作分隔符,而不是换行符。 将您的字符串拆分为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));
          }

    }
}