带有空间的拆分字符串路径
Split string path with space
我正在编写一个程序,该程序应通过用户接收3个参数:file_upload" local_path" remote_path"
代码示例:
std::vector split(std::string str, char delimiter) {
std::vector<string> v;
std::stringstream src(str);
std::string buf;
while(getline(src, buf, delimiter)) {
v.push_back(buf);
}
return v;
}
void function() {
std::string input
getline(std::cin, input);
// user input like this: file_upload /home/Space Dir/file c:dirfile
std::vector<std::string> v_input = split(input, ' ');
// the code will do something like this
if(v_input[0].compare("file_upload") == 0) {
FILE *file;
file = fopen(v_input[1].c_str(), "rb");
send_upload_dir(v_input[2].c_str());
// bla bla bla
}
}
我的问题是:第二参数和第三个参数是目录,然后它们可以包含名称的空格。如何使拆分函数不更改第二个参数的空间?
我认为将引号放入目录中,并创建一个函数以识别,但不能100%起作用,因为该程序具有其他功能,仅采用2个参数而不是三个参数。任何人都可以帮助吗?
编辑:/home/user/user/space dir/file.out&lt; - 带有空间名称的路径。
如果发生这种情况,则向量的大小大于预期,并且目录的路径将被打破..这不会发生。
向量将包含类似的内容:
vector [1] =/home/user/space
vector [2] = dir/file.out
我想要的是:
vector [1] =/home/home/user/space dir/file.out
由于您需要从单个字符串输入中接受三个值,因此这是编码的问题。
编码有时是通过对某些或所有字段施加固定宽度要求来完成的,但这显然是不合适的,因为我们需要支持可变宽度的文件系统路径和第一个值(这似乎是某种形式模式说明符)也可能是可变宽度。所以那是出来的。
这留下了4个可能的解决方案,用于可变宽度编码:
1:明确的定界符。
如果您可以选择一个保证永远不会在划界值中显示的分离器字符,则可以在其中拆分。例如,如果保证NUL永远不会成为模式值或路径值的一部分,那么我们可以做到这一点:
std::vector<std::string> v_input = split(input,' ');
或管道字符:
std::vector<std::string> v_input = split(input,'|');
因此,必须给出这样的输入(对于管道字符):
file_upload|/home/user/Space Dir/file.out|/home/user/Other Dir/blah
2:逃脱。
您可以将代码写入迭代,并在分离器字符的未阐明实例上正确拆分。逃脱的实例不会被视为分离器。您可以参数化逃生字符。例如:
std::vector<std::string> escapedSplit(std::string str, char delimiter, char escaper ) {
std::vector<std::string> res;
std::string cur;
for (size_t i = 0; i < str.size(); ++i) {
if (str[i] == delimiter) {
res.push_back(cur);
cur.clear();
} else if (str[i] == escaper) {
++i;
if (i == str.size()) break;
cur.push_back(str[i]);
} else {
cur.push_back(str[i]);
} // end if
} // end for
if (!cur.empty()) res.push_back(cur);
return res;
} // end escapedSplit()
std::vector<std::string> v_input = escapedSplit(input,' ','');
输入为:
file_upload /home/user/Space Dir/file.out /home/user/Other Dir/blah
3:引用。
您可以将代码写入迭代,并在分隔符字符的无引用实例上正确拆分。引用的实例将不会被视为分离器。您可以参数化报价字符。
这种方法的一种并发症是,除非引入逃避机制,否则不可能在引用范围内包含引用字符本身,类似于解决方案#2。一个共同的策略是允许重复报价字符逃脱它。例如:
std::vector<std::string> quotedSplit(std::string str, char delimiter, char quoter ) {
std::vector<std::string> res;
std::string cur;
for (size_t i = 0; i < str.size(); ++i) {
if (str[i] == delimiter) {
res.push_back(cur);
cur.clear();
} else if (str[i] == quoter) {
++i;
for (; i < str.size(); ++i) {
if (str[i] == quoter) {
if (i+1 == str.size() || str[i+1] != quoter) break;
++i;
cur.push_back(quoter);
} else {
cur.push_back(str[i]);
} // end if
} // end for
} else {
cur.push_back(str[i]);
} // end if
} // end for
if (!cur.empty()) res.push_back(cur);
return res;
} // end quotedSplit()
std::vector<std::string> v_input = quotedSplit(input,' ','"');
输入为:
file_upload "/home/user/Space Dir/file.out" "/home/user/Other Dir/blah"
甚至只是:
file_upload /home/user/Space" "Dir/file.out /home/user/Other" "Dir/blah
4:长度值。
最后,您可以编写代码以在每个值之前进行长度,只抓住许多字符。我们可能需要固定宽度的长度指示符,或者在长度说明符后跳过划界字符。例如(注意:错误检查的光):
std::vector<std::string> lengthedSplit(std::string str) {
std::vector<std::string> res;
size_t i = 0;
while (i < str.size()) {
size_t len = std::atoi(str.c_str());
if (len == 0) break;
i += (size_t)std::log10(len)+2; // +1 to get base-10 digit count, +1 to skip delim
res.push_back(str.substr(i,len));
i += len;
} // end while
return res;
} // end lengthedSplit()
std::vector<std::string> v_input = lengthedSplit(input);
输入为:
11:file_upload29:/home/user/Space Dir/file.out25:/home/user/Other Dir/blah
几天前我也有类似的问题,然后这样解决:
首先,我已经创建了一个副本,然后用一些填充物替换副本中的引用字符串以避免白色空间,最后我根据副本的白空间索引将原始字符串拆分。
这是我的完整解决方案:
您可能还需要删除双引号,修剪原始字符串等:
#include <sstream>
#include<iostream>
#include<vector>
#include<string>
using namespace std;
string padString(size_t len, char pad)
{
ostringstream ostr;
ostr.fill(pad);
ostr.width(len);
ostr<<"";
return ostr.str();
}
void splitArgs(const string& s, vector<string>& result)
{
size_t pos1=0,pos2=0,len;
string res = s;
pos1 = res.find_first_of(""");
while(pos1 != string::npos && pos2 != string::npos){
pos2 = res.find_first_of(""",pos1+1);
if(pos2 != string::npos ){
len = pos2-pos1+1;
res.replace(pos1,len,padString(len,'X'));
pos1 = res.find_first_of(""");
}
}
pos1=res.find_first_not_of(" trn",0);
while(pos1 < s.length() && pos2 < s.length()){
pos2 = res.find_first_of(" trn",pos1+1);
if(pos2 == string::npos ){
pos2 = res.length();
}
len = pos2-pos1;
result.push_back(s.substr(pos1,len));
pos1 = res.find_first_not_of(" trn",pos2+1);
}
}
int main()
{
string s = "234 "5678 91" 8989";
vector<string> args;
splitArgs(s,args);
cout<<"original string:"<<s<<endl;
for(size_t i=0;i<args.size();i++)
cout<<"arg "<<i<<": "<<args[i]<<endl;
return 0;
}
这是输出:
original string:234 "5678 91" 8989
arg 0: 234
arg 1: "5678 91"
arg 2: 8989
- 如何从路径字符串加载Gdiplus::位图
- 如何在C++的路径中插入字符串?
- 如何将文件系统路径转换为字符串
- 返回混合 \ 和 / 的文件系统路径字符串方法
- 无法使用 Poco 获取字符串的路径
- C++ 如何使用字符串中保存的文件路径创建带时间戳的目录
- 如何在 Qt/C++ 中仅将文件路径作为字符串访问文件
- GCC Bug,使用尖括号通过宏包含标头时"linux"路径中的字符串"<>"替换为 "1"
- 使函数接受字符串变量内的路径
- 如何确定具有文件路径的字符串中是否有任何非 ASCII 字符
- C 使用字符串作为打开文件路径的ifstream错误
- 从变量字符串中提升文件系统路径
- C++字符串到字符串打印不正确,无法获取 unicode 路径
- 使用Android NDK从字符串路径打开文件
- 带有空间的拆分字符串路径
- 从设备实例路径字符串获取设备实例 DWORD
- 使用字符串作为打开文件路径时出现ifstream错误
- c++将文件的路径组合为字符串和文件名
- 使用字符串在C++中指定文件路径(将文件存储在文件夹中)
- 如何对字符串执行路径操作