繁体   English   中英

如何让std :: istringstream将给定字符视为空白?

[英]How to let std::istringstream treat a given character as white space?

使用std::istringstream可以轻松读取由空格分隔的单词。 但是要解析以下行,我需要将字符/视为空白。

f 104/387/104 495/574/495 497/573/497

如何读取以斜杠或空格分隔的值?

一种方法是定义将/分类为空白的ctype构面:

class my_ctype : public std::ctype<char> {
public:
    mask const *get_table() { 
        static std::vector<std::ctype<char>::mask> 
            table(classic_table(), classic_table()+table_size);
        table['/'] = (mask)space;
        return &table[0];
    }
    my_ctype(size_t refs=0) : std::ctype<char>(get_table(), false, refs) { }
};

从那里,使用该ctype构面为流添加语言环境,然后读取单词:

int main() { 
    std::string input("f 104/387/104 495/574/495 497/573/497");
    std::istringstream s(input);
    s.imbue(std::locale(std::locale(), new my_ctype));

    std::copy(std::istream_iterator<std::string>(s),
              std::istream_iterator<std::string>(),
              std::ostream_iterator<std::string>(std::cout, "\n"));
}

如果可以使用boost,那么boost::split()可能是一种解决方案。 使用std::getline()填充std::string ,然后分割行:

#include <iostream>
#include <vector>
#include <string>

#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/split.hpp>

int main()
{
    std::vector<std::string> tokens;
    std::string line("f 104/387/104 495/574/495 497/573/497");
    boost::split(tokens, line, boost::is_any_of("/ "));

    for (auto& token: tokens) std::cout << token << "\n";

    return 0;
}

输出:

f
104
387
104
495
574
495
497
573
497

如果您知道何时用斜线或空格分隔,则可以使用std::getline

std::istringstream is("f 104/387/104 495/574/495 497/573/497");
std::string f, i, j, k;
std::getline(is, f, ' ');
std::getline(is, i, '/');
std::getline(is, j, '/');
std::getline(is, k, ' ');

或者,您可以使用格式化的输入并手动丢弃斜杠

std::string f;
int i, j, k;
char slash;
is >> f >> i >> slash >> j >> slash >> k;

我确信这根本不是最好的方法,但是我正在使用《使用C ++ 2nd Ed编程原理和实践 》一书中的练习。 由Bjarne Stroustrup提出 ,我想出了一个可能对您有用的解决方案。 我四处搜寻,看看其他人是怎么做的(这就是我发现这个线程的方式),但我真的什么也没找到。

首先,这是本书的练习:

编写一个函数vector <string> split(const string&s,const string&w),该函数从参数s返回由空格分隔的子字符串的向量,其中空格定义为“普通空格”加上w中的字符。

这是我想出的解决方案,似乎很好用。 我尝试对其进行评论以使其更加清晰。 只想提一下我对C ++还是很陌生(这就是为什么我正在读这本书的原因),所以不要太在意我。 :)

// split a string into its whitespace-separated substrings and store
// each string in a vector<string>. Whitespace can be defined in argument
// w as a string (e.g. ".;,?-'")
vector<string> split(const string& s, const string& w)
{
    string temp{ s };
    // go through each char in temp (or s)
    for (char& ch : temp) {     
        // check if any characters in temp (s) are whitespace defined in w
        for (char white : w) {  
            if (ch == white)
                ch = ' ';       // if so, replace them with a space char ('')
        }
    }

    vector<string> substrings;
    stringstream ss{ temp };

    for (string buffer; ss >> buffer;) {
        substrings.push_back(buffer);
    }
    return substrings;
}

然后,您可以执行以下操作来使用它:

cout << "Enter a string and substrings will be printed on new lines:\n";
string str;
getline(cin, str);
vector<string> substrings = split(str, ".;,?-'");

cout << "\nSubstrings:\n";
for (string s : substrings)
    cout << s << '\n';

我知道您不想分割字符串,但这只是如何将其他字符视为空格的一个示例。 基本上,我只是将这些字符替换为',因此它们确实会变成空白。 与流一起使用时,效果很好。 for循环可能是与您的情况相关的代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM