在c++中用两个分隔符分隔字符串
Splitting a string on two delimitators in C++
我有一个文件cities.txt,包含:
Hayward - San Lorenzo
San Lorenzo - Oakland
Dublin - San Jose
San Mateo - Hayward
San Francisco - Daly City
San Mateo - Oakland
San Francisco - Oakland
Freemont - Hayward
San Lorenzo - Dublin
San Jose - San Mateo
Daly City - San Raphael
我看了比赛的文件:
#include <iostream>
#include <fstream>
#include <string>
#include <iterator>
int main( ) {
std::ifstream infile( "cities.txt" ) ;
if ( infile ) {
std::string fileData( ( std::istreambuf_iterator<char> ( infile ) ) ,
std::istreambuf_iterator<char> ( ) ) ;
infile.close( );
std::cout << fileData <<"nn";
return 0 ;
}
else {
std::cout << "Where is cities.txt?n" ;
return 1 ;
}
}
并将内容保存在fileData字符串中。我需要将该字符串分解为一个只包含城市名称的字符串列表。像这样:
list = {"Hayward","San Lorenzo", "San Lorenzo", "Oakland"......}
我打算把字符串转换成char*并使用strtok,但这似乎是很多工作,可以使用标准字符串函数完成。有没有一种既快速又简洁的方法?
我可能会使用std::getline
,指定-
作为元素之间的分隔符:
std::string city;
while (std::getline(i, city, '-'))
cities.push_back(city);
一个小细节:这将保持空白完整,所以如果前导和/或尾随空白是一个问题,你必须分别修剪它。
您可以通过几个步骤来完成。
-
将文件的内容拆分为字符串向量-因此,向量的每个元素将包含文件的单行
-
将文件的每一行拆分为两个元素(一行中的两个城市)
-
削减内容
拆分函数可以这样实现:
vector<string> split (string str, string seq) {
vector<string> ret {};
size_t pos {};
while ((pos = str.find (seq)) != string::npos) {
ret.push_back (str.substr (0, pos));
str = str.substr (pos+seq.size ());
}
ret.push_back (str);
return ret;
}
微调函数可以这样实现:
string ltrim (string s) {
s.erase (s.begin (), find_if (s.begin (), s.end (), not1 (ptr_fun<int, int> (isspace))));
return s;
}
string rtrim (string s) {
s.erase (find_if (s.rbegin (), s.rend (), not1 (ptr_fun<int, int> (isspace))).base (), s.end ());
return s;
}
string trim (string s) {
return ltrim (rtrim (s));
}
那么,基本上你已经有了所有你需要的,让我们准备一个result函数。
vector<string> result (vector<string>&& content) {
vector<string> ret {};
for (const auto& c : content) {
auto vec = split (c, "-"); // (2)
for (const auto& v : vec) {
ret.push_back (trim (v));
}
}
return ret;
}
void show (const vector<string>& vec) {
for (const auto& v : vec) {
cout << "|" << v << "|" << endl;
}
}
的用法是这样的,假设文件的内容在content对象中。
auto vec = result (split (content, "n")); // (1)
show (vec);
现在,需要一些解释。让我们看一下(1)我们获取文件的整个内容(我错过了从文件中检索内容)并创建字符串向量,在本例中它是行向量(来自文件,因为seq序列是"n")。因此,我们将来自文件的行向量传递给结果函数向量。好,很简单,我们继续。现在我们必须将这一行拆分为两个字符串(城市)(2),但是我们的seq序列现在是"-"。这个(2)调用将产生包含城市名称的字符串向量。现在,我们所要做的就是将这些名称添加到将返回的向量ret中,但首先修剪内容以使左侧和右侧的所有空白都消失。
结果是:
|Hayward|
|San Lorenzo|
|San Lorenzo|
|Oakland|
|Dublin|
|San Jose|
|San Mateo|
|Hayward|
|San Francisco|
|Daly City|
|San Mateo|
|Oakland|
|San Francisco|
|Oakland|
|Freemont|
|Hayward|
|San Lorenzo|
|Dublin|
|San Jose|
|San Mateo|
|Daly City|
|San Raphael|
您可以使用string::find, string::erase和string::substr
使用像这样的while循环
found = input.find("-");
while(found != string::npos){... }
在while子字符串中添加城市名称,然后使用。erase(position, length)
您可以使用boost regex_split。我已经修改了您的代码来演示相同的。粘贴如下:
#include <iostream>
#include <fstream>
#include <string>
#include <iterator>
#include <boost/regex.hpp>
#include <vector>
int main( ) {
std::ifstream infile( "cities.txt" ) ;
if ( infile ) {
std::string fileData( ( std::istreambuf_iterator<char> ( infile ) ) ,
std::istreambuf_iterator<char> ( ) ) ;
infile.close( );
std::cout << fileData <<"nn";
std::vector<std::string> out;
// Delimeter regular expression
boost::regex delims("\s+-\s+|n|r");
boost::regex_split(std::back_inserter(out), fileData, delims);
for (auto &city : out) {
std::cout << city << std::endl;
}
}
else {
std::cout << "Where is cities.txt?n" ;
return 1 ;
}
}
- 如何在C++中从两个单独的for循环中添加两个数组
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 当在同一名称空间中有两个具有相同签名的函数时,会发生什么
- 如何返回一个类的两个对象相加的结果
- 如何在C++中将一个无符号的 int 转换为两个无符号的短裤?
- 如何将两个不同矢量的同一位置的两个元素组合在一起
- C++获取两个分隔符之间的字符串并替换它
- 如何使用两个不同的分隔符拆分字符串
- 使用 C++ 读取具有两个连续分隔符的 csv 文件
- 具有两个分隔符的字符串流
- 将 strtok 分隔符设置为两个字符
- C++ 获取两个分隔符字符串之间的字符串
- 带有字符串分隔符或两个字符的fstream
- 从c++中的字符串中提取两个分隔符之间的子字符串
- 使用两个字符串分隔符选择文本文件的一部分
- QSplitter显示两个小部件之间的分隔符或边距
- 如何在C++中声明两个相互包含(循环依赖)的类,并使用分隔符
- 如何将字符指针数组拆分为两个带有分隔符的新字符指针数组
- 在c++中用两个分隔符分隔字符串
- Getline忽略'-用两个分隔符getline