gpt4 book ai didi

c++ - 用空格分割字符串路径

转载 作者:行者123 更新时间:2023-11-27 22:50:15 27 4
gpt4 key购买 nike

我正在编写一个程序,它应该由用户接收 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:\dir\file
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
}
}

我的问题是:第二个和第三个参数是目录,那么名称中可以包含空格。如何让split函数不改变第二个和第三个参数的空格?

我想在目录中加上引号并创建一个函数来识别,但不是 100% 有效,因为该程序还有其他函数,这些函数只需要 2 个参数而不是三个。任何人都可以帮忙吗?

编辑:/home/user/Space Dir/file.out <-- 带空间名称的路径。

如果发生这种情况, vector 大小大于预期,目录路径将被破坏。这不可能发生。

vector 将包含如下内容:

vector [1] =/home/user/Space

vector[2] = Dir/file.out

我想要的是:

vector[1] =/home/user/Space Dir/file.out

最佳答案

由于您需要接受来自单个字符串输入的三个值,因此这是 encoding 的问题.

编码有时是通过对某些或所有字段施加固定宽度要求来完成的,但这显然不适合这里,因为我们需要支持可变宽度的文件系统路径,并且第一个值(看起来是某种模式说明符)也可以是可变宽度的。这样就结束了。

这为可变宽度编码留下了 4 种可能的解决方案:


1:明确的分隔符。

如果您可以选择一个保证永远不会出现在定界值中的分隔符,那么您可以以此为基础进行拆分。例如,如果保证 NUL 永远不会成为模式值或路径值的一部分,那么我们可以这样做:

std::vector<std::string> v_input = split(input,'\0');

或者管道字符:

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

关于c++ - 用空格分割字符串路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37978924/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com