【问题标题】:Replace back slashes with forward slashes in string (std::replace works on windows but not on linux)用字符串中的正斜杠替换反斜杠(std::replace 适用于 Windows,但不适用于 linux)
【发布时间】:2026-01-22 05:45:01
【问题描述】:

我在 Windows 中开发一个小型应用程序,其中一个步骤是通过命令行 (CMD.exe) 向它发送一个路径,如下所示:

c:\> my_environment_var catch folder/sub_folder/file.txt

程序接收路径并执行一个进程。为此,我被要求控制两种情况:

  1. 将用户输入的字符串转换为小写。
  2. 将用户在路由中输入的反斜杠 (\) 替换为正斜杠 (/)。

例如,如果用户输入:

c:\> my_environment_var catch FOLDER\sub_Folder\fiLE.txt

我的“控制”函数应该处理字符串并返回如下结果:

folder/sub_folder/file.txt

全部小写并带有正斜杠。

为了实现这一点,我在“控制”函数中使用了以下内容:

std::transform(argument.begin(), argument.end(), argument.begin(), ::tolower);

std::replace(argument.begin(), argument.end(), '\\', '/');

在 Windows 中,这两个功能都可以正常工作。然而,在 Linux (Ubuntu) 中,只有小写转换才能正常工作,替换功能“删除”反斜杠,如下所示

用户输入:

c:\> my_environment_var catch FOLDER\sub_Folder\FiLe.txt

应用程序打印:

foldersub_folderfile.txt

我已经用谷歌搜索了几个小时,但根据我阅读的内容,std::replace 应该可以正常工作。

我很欣赏任何想法。


编辑: ************************************** *


感谢您的支持,我读到有必要分享更多代码,嗯,这里是:

第一步: 用户在控制台中写入环境变量以及命令(要执行的操作)和要应用此操作的文件。对于这种情况,我使用catch 命令将文件名复制到另一个文件(索引)。

c:\> my_env_var catch FOLDER\sub_Folder\FiLe.txt

第二步:应用程序通过main函数接收参数,创建一个字符串向量,并将该向量发送给一个函数进行处理(Starter类初始化为argc的值和 argv)。

#include "Starter.h"
// more includes
namespace fs = std::filesystem;

int main(int argc, char* argv[]) {
    std::string current_path = fs::current_path().string();
    std::vector<std::string> arg_container;
    Starter starter(current_path, argc, argv);
    starter.input_formatter(arg_container);
    // more code...
}

第三步: input_formatter()函数接收到这个数据并做处理,本质上很简单:

  • 复制存储在变量argv中的值,并将它们添加到之前创建的向量中。
  • 遍历向量(最近填充了来自 argv 的数据)执行两个操作:第一个是将文本转换为小写,第二个是将反斜杠替换为正斜杠。

`

//some includes
using std::string;
using std::vector;
namespace fs = std::filesystem;

Starter::Starter(string current_path, int argument_count, char* argument_values[])
    : current_path{current_path},
      argument_count{argument_count},
      argument_values{argument_values} {}

void Starter::input_formatter(vector<string>& arg_container) {
    std::copy(argument_values, argument_values + argument_count, std::back_inserter(arg_container));
    for (auto& argument : arg_container) {
        std::transform(argument.begin(), argument.end(), argument.begin(), ::tolower);
        std::replace(argument.begin(), argument.end(), '\\', '/');
    }
}

第四步:假设一旦修改了数据,就遍历并打印向量。实际上,其他操作是通过向量执行的,但这并不重要,因为这些操作是根据结果执行的。

问题:打印向量时,用户输入的路径对应的字符串,没有斜杠。 (即,无论文件夹和/或文件的名称如何。)。像这样:

foldersub_folderfile.txt

这只发生在 Linux 上(我只尝试过 Ubuntu),在 Windows 上一切正常。

PD。我确定这是一个愚蠢的错误,但我真的在寻找解决方案,但仍然找不到。谢谢!

【问题讨论】:

  • 如果您尝试使用字符串文字对其进行测试,问题可能是因为FOLDER\sub 中的\s 被认为是某种转义字符。尝试使用原始字符串文字,如本例中的 godbolt.org/z/W4rrzr
  • @PetokLorand 转义字符仅适用于阅读源代码时的编译器。如果字符串是在运行时出现的,在这种情况下,从命令行,什么都不会被转义。
  • 你需要展示完整的代码,但我的猜测和@petoklorand 一样。
  • @Fareanor 是的,我知道这一点,但是在给定运行时字符串输入的情况下,代码应该按预期运行。只有在使用字符串文字时,问题才会显现。 godbolt.org/z/6ze53c
  • 它应该可以正常工作,并且确实可以正常工作。问题确实出在您的代码中。但是我敢打赌,当您将代码简化为最小示例时,问题就会消失。您可以创建一个 3 行的 main 函数来读取输入、替换斜线并输出结果。

标签: c++


【解决方案1】:

根据您的描述,我的猜测是问题不在于您的代码:而在于您为程序提供输入的方式。与 Windows 不同的是,Linux 不使用 \ 作为路径分隔符,而是通常将其作为“转义字符”赋予特殊含义——就像在 C++ 中一样。因此,您的 shell 可能会在反斜杠到达您的程序之前对其进行解析。

特别是,如果您使用bash,则反斜杠会保留后面字符的字面含义(并且反斜杠被删除)。如果您想在输入中保留反斜杠,请尝试转义它们:

my_environment_var catch FOLDER\\sub_Folder\\fiLE.txt

另一种方法是将字符串括在单引号中,这会禁用其中所有字符的特殊行为:

my_environmnent_var catch 'FOLDER\sub_Folder\fiLE.txt'

(有关 POSIX shell 中反斜杠行为的详细信息,请参阅 here。)

【讨论】:

    最近更新 更多