我正在使用没有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);
答案 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::copy
和std::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) ;
}
答案 2 :(得分:0)
您可以将stringstream
和getline
与\"
字符一起用作分隔符,而不是换行符。
将您的字符串拆分为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));
}
}
}