Normalize slashes in path on Linux - c++

What is the recommended way to specify to use native separators in filesystem path object?
Below is a simple example with a static string.
std::string str = "/tmp\\foo";
std::filesystem::path path(str);
std::cout << "Generic_string:" << path.generic_string() << std::endl;
std::cout << "Make_preferred:" << path.make_preferred() << std::endl;
This will output
Generic_string:/tmp\foo
Make_preferred:/tmp\foo
The make_preferred method does not appear to make any change to path. Do I really need to use std::replace to fix the issue?

Related

filesystem::* strange results in windows filesystem paths with extended chars

Code doesn't do anything useful. It's just try & error code to figure out what's going on:
fs::path path("e:\\Σtest");
cout<<path << " exsits="<< fs::exists(path) << " is dir=" << fs::is_directory(path) << std::endl;
fs::path pathL(L"e:\\Σtest");
cout<<pathL << " exsits="<< fs::exists(pathL) << " is dir=" << fs::is_directory(pathL) << std::endl;
fs::path pathu(u"e:\\Σtest");
cout<<pathu << " exsits="<< fs::exists(pathu) << " is dir=" << fs::is_directory(pathu) << std::endl;
Output:
e:\Σtest exsits=0 is dir=0
e:\Σtest exsits=0 is dir=0
e:\Σtest exsits=0 is dir=0
I sure that folder Σtest exists. I guess there is encoding involve somehow. I can't figure out what sophisticated problem we have encounter here, someone can explain output?
EDIT:
Following #cpplearner advice to pass /utf-8 to compiler output changes (also code page for console was changed to utf-8 by chcp 65001):
e:\Σtest exsits=0 is dir=0
e:\?test exsits=1 is dir=1
e:\?test exsits=1 is dir=1
Question remain the same, what magic happen here?

Given a H5::Group, how do I print its full path within its hdf5 file?

I have some code that takes some random H5::Group. My understanding is that from this object, I should be able to learn what file it is in and what the path to it is within that file.
void PrintPathTo(const H5::Group& group){
std::stringstream path;
path << group.getFileName() << ":/" << group.getPath() // this doesn't work. Is there something like it?
std::cout << path.str() << std::endl;
}
Is this possible without searching the whole file?

c++ untyped value object/variable library with defined operation overloads

I don't know exactly how to define what I am searching, but, here I go:
Since the library libjsoncpp exists and lets us hold a value in an object that is "json based", which means, an integer, an unsigned number, double, string or null... (also arrays and objects that can be seen -or I perceive- as pointer based objects to other objects),
... is there any kind of library in which we could operate with those data, more or less as we do in javascript?
#include "somemagiclib.h"
magicnamespace::jsonlike_o value1=10;
int integervalue=15;
magicnamespace::jsonlike_o value2="hello_world";
std::string anything="anything";
magicnamespace::jsonlike_o value3="10.3";
magicnamespace::jsonlike_b result;
value3=value2+value1;
std::cout << "value3 is: " << value3.asString() << std::endl;
/*value3 is: 21*/
std::cout << (value2+value1).asString() << std::endl;
/*hello_world10*/
std::cout << (value1+value3).asString() << std::endl;
/*20*/
std::cout << (value3+value1).asString() << std::endl;
/*10.310*/
std::cout << (value1<value3).asString() << std::endl;
/*true*/
std::cout << (value1+integervalue).asString() << std::endl;
/*25*/
std::cout << (value1+anything).asString() << std::endl;
/*18*/
std::cout << (value1>=integervalue).asString() << std::endl;
/*false*/
std::cout << (value2+integervalue).asString() << std::endl;
/*hello_world15*/
std::cout << (value2+anything).asString() << std::endl;
/*hello_worldanything*/
We could easily reach to the ask "what for?" (...or even "wtf for?"). In fact, I am working on a project that requires a part of json processing to compare values that are obtained from part based ports transmitting in serial protocols, compared with values that are obtained from json based configured files.
Being able to code or preview the future scenarios is becoming difficult, since we also have to preview incoming values from JsonRPC based objects, so the code may become expensive to generate or to maintain.
Do you know if there's any kind of library that implements this kind of "non-typed" type in C++?
In case of not knowing, do you think that this kind of library deserves the efforts to be created?
Thank you very much for your attention.
Look into crow c++. its not just json stuff, its pretty much flask for c++. might be useful. it's also just a header file, so no installation etc is needed

Setting the content of a std::stringstream with str(const char*) has strange consequences

I use std::stringstream extensively to generate code. I have run into some querious behavior when setting the content with the str() function followed by using the operator<<. Can someone explain this behavior to me. I would very much appreciate it - Thanks.
Example One:
std::stringstream ssa;
ssa.str("Setting string");
std::cout << ssa.str() << std::endl;
ssa << " adding to string";
std::cout << ssa.str() << std::endl;
Output:
Setting string
adding to string
Expected:
Setting string
Setting string adding to string
So after a bit of reading up on the documentation I found that I should set the open mode to ios_base::ate:
std::stringstream ssb(std::ios_base::ate);
ssb.str("Setting string");
std::cout << ssb.str() << std::endl;
ssb << " adding to string";
std::cout << ssb.str() << std::endl;
Output:
Setting string
Setting string
Again (or now) I would expect:
Setting string
Setting string adding to string
Why am I getting the results I am, and how do I get the result I want? E.i. Being able to set the initial string of a stringstream and the append to that string ?
I am aware that I can just set the content to the empty string("") and then only use the <<operator. This is in fact the workaround I am using. I just don't understand the observed behavior. And the workaround makes my code more messy.
The default open mode for a std::stringstream object is in | out. Using a different mode overrides these options. Since the stream cannot be written to, the insertion operator cannot be used to write to the stream. This is why str() gives the same output twice.
You need to manually open the stream in output mode as well:
std::stringstream ssb("Setting string", std::ios_base::out | std::ios_base::ate);
Live Demo
Alternatively, use an std::ostringstream, which initializes the internal std::stringbuf subobject with out | mode.
std::ostringstream("Setting string", std::ios_base::ate);
Live Demo
You forgot to set flag mode: std::ios_base::out.
This will work:
std::stringstream ssb(std::ios_base::out | std::ios_base::ate);
ssb.str("Setting string");
std::cout << ssb.str() << std::endl;
ssb << " adding to string";
std::cout << ssb.str() << std::endl;
Output:
Setting string
Setting string adding to string

Getting a directory name from a filename

I have a filename (C:\folder\foo.txt) and I need to retrieve the folder name (C:\folder) in C++. In C# I would do something like this:
string folder = new FileInfo("C:\folder\foo.txt").DirectoryName;
Is there a function that can be used in C++ to extract the path from the filename?
Using Boost.Filesystem:
boost::filesystem::path p("C:\\folder\\foo.txt");
boost::filesystem::path dir = p.parent_path();
Example from http://www.cplusplus.com/reference/string/string/find_last_of/
// string::find_last_of
#include <iostream>
#include <string>
using namespace std;
void SplitFilename (const string& str)
{
size_t found;
cout << "Splitting: " << str << endl;
found=str.find_last_of("/\\");
cout << " folder: " << str.substr(0,found) << endl;
cout << " file: " << str.substr(found+1) << endl;
}
int main ()
{
string str1 ("/usr/bin/man");
string str2 ("c:\\windows\\winhelp.exe");
SplitFilename (str1);
SplitFilename (str2);
return 0;
}
In C++17 there exists a class std::filesystem::path using the method parent_path.
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main()
{
for(fs::path p : {"/var/tmp/example.txt", "/", "/var/tmp/."})
std::cout << "The parent path of " << p
<< " is " << p.parent_path() << '\n';
}
Possible output:
The parent path of "/var/tmp/example.txt" is "/var/tmp"
The parent path of "/" is ""
The parent path of "/var/tmp/." is "/var/tmp"
There is a standard Windows function for this, PathRemoveFileSpec. If you only support Windows 8 and later, it is highly recommended to use PathCchRemoveFileSpec instead. Among other improvements, it is no longer limited to MAX_PATH (260) characters.
Why does it have to be so complicated?
#include <windows.h>
int main(int argc, char** argv) // argv[0] = C:\dev\test.exe
{
char *p = strrchr(argv[0], '\\');
if(p) p[0] = 0;
printf(argv[0]); // argv[0] = C:\dev
}
auto p = boost::filesystem::path("test/folder/file.txt");
std::cout << p.parent_path() << '\n'; // test/folder
std::cout << p.parent_path().filename() << '\n'; // folder
std::cout << p.filename() << '\n'; // file.txt
You may need p.parent_path().filename() to get name of parent folder.
Use boost::filesystem. It will be incorporated into the next standard anyway so you may as well get used to it.
I'm so surprised no one has mentioned the standard way in Posix
Please use basename / dirname constructs.
man basename
_splitpath is a nice CRT solution.
Standard C++ won't do much for you in this regard, since path names are platform-specific. You can manually parse the string (as in glowcoder's answer), use operating system facilities (e.g. http://msdn.microsoft.com/en-us/library/aa364232(v=VS.85).aspx ), or probably the best approach, you can use a third-party filesystem library like boost::filesystem.
Just use this: ExtractFilePath(your_path_file_name)