JulioZaravia
JulioZaravia

Reputation: 79

Replace back slashes with forward slashes in string (std::replace works on windows but not on linux)

I was working on a small application in Windows, one of the steps is to send it a path through the command line (CMD.exe), something like this:

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

The program receives the path and executes a process. For this, I was asked to control two cases:

  1. Transform the string entered by the user to lowercase.
  2. Replace the back slashes (\) that the user enters in the route with forward slashes (/).

For example, if the user entesrs:

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

My "control" function should process the string and return a result like this:

folder/sub_folder/file.txt

All in lowercase and with forward slashes.

To achieve this I use the following within my "control" function:

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

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

In Windows both functions work correctly. However in Linux (Ubuntu) only the lowercase transformation works correctly, the replace function "removes" the back slash, something like this:

User enters:

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

Application prints:

foldersub_folderfile.txt

I've been googling for several hours now but based on what I read the std::replace should work fine.

I appreciate any ideas.


EDIT: ***************************************


Thanks for the support, I read that it would be necessary to share some more code, and, well, here it is:

First step: The user writes in the console the environment variable together with the command (the action to be performed) and the file to which this action should be applied. For this case I use the catch command which copies the file name to another file (indexing).

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

Step two: The application receives the parameters through the main function, creates a vector of strings, and sends the vector to a function to be processed (The Starter class is initialized with the values of argc and 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...
}

Step three: The input_formatter () function receives this data and does the process, which is essentially simple:

`

//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(), '\\', '/');
    }
}

Step four: Let's say that once the data is modified, the vector is traversed and printed. Actually, other actions are performed with the vector but that is not important since these actions are performed with the result.

Problem: When the vector is printed, The string corresponding to the path that the user entered, does not have any slash. (that is, regardless of the names of the folders and / or files.). Like this:

foldersub_folderfile.txt

This only happens on Linux (I have only tried Ubuntu), on Windows everything works as it should.

PD. I'm sure it's a silly mistake, but I've really searched for the solution and still can't find it. Thank you!

Upvotes: 2

Views: 965

Answers (1)

N. Shead
N. Shead

Reputation: 3938

From your description, my guess would be that the issue is not with your code: it's with the way you are providing input to your program. Unlike on Windows, Linux doesn't use \ as a path separator, and instead it's usually given special meaning as an "escape character"—much like in C++. As such, your shell is likely parsing out the backslashes before they ever reach your program.

In particular, if you are using bash, then a backslash preserves the literal meaning of the following character (and the backslash is removed). If you want to preserve backslashes in your input, try escaping them:

my_environment_var catch FOLDER\\sub_Folder\\fiLE.txt

An alternative method is to enclose your string in single-quotes, which disables the special behaviour of all characters within them:

my_environmnent_var catch 'FOLDER\sub_Folder\fiLE.txt'

(See here for precise details on the behaviour of backslashes in POSIX shells.)

Upvotes: 3

Related Questions