When using boost_filesystem, Boost keeps adding quotation marks to the filenames.
foo.cpp:
#include <iostream>
#include <boost/filesystem.hpp>
int main( int argc, char * argv[] )
{
std::cout << argv[0] << std::endl;
boost::filesystem::path p( argv[0] );
std::cout << p << std::endl;
std::cout << p.filename() << std::endl;
return 0;
}
Compiled:
g++ foo.cpp -o foo -lboost_filesystem -lboost_system
Output:
./foo
"./foo"
"foo"
This is somewhat unexpected, and inconvenient in my case. Is this really intentional, or is my somewhat older version of Boost (1.46.1) buggy in this respect? Is there some way I could avoid them being added?
I perused the documentation, but aside from the tutorials not showing those quotation marks in their example output, I was not enlightened.
This is actually a bug filed on the Boost framework on version 1.47.0.
The proposed workaround is:
std::cout << path("/foo/bar.txt").filename().string()
It's intentional because unexpected embedded spaces and confuse related code. The best you can do is probably:
boost::replace_all(yourquotedstring, "\"", "");
EDIT
Although, according to this link, you can try something like:
std::cout << path("/foo/bar.txt").filename().string();
Related
Let's talk about this simple example:
#include <iostream>
int main(int argc, char *argv[])
{
std::cout << "started " << argv[0] << " with " << argc << " params." << std::endl;
return 0;
}
We have a minimal .clang-tidy file which looks like this:
Checks:
'-*,
cppcoreguidelines-*,
-cppcoreguidelines-pro-bounds-pointer-arithmetic'
WarningsAsErrors:
'*'
Even though I get the following warning:
src/main.cpp:5:30: error: do not use pointer arithmetic [cppcoreguidelines-pro-bounds-pointer-arithmetic,-warnings-as-errors]
std::cout << "started " << argv[0] << " with " << argc << " params." << std::endl;
^
I don't want to mess around with NOLINT in my code and I don't want to add some additional flags to the CMakeLists.txt file just because of clang-tidy.
Is there a clean way, to mask some single checks in the .clang-tidy file?
I'm using gcc/g++ and clang-tidy in version 6.0.0 on Linux. I'm aware of How to disable a clang-tidy check? - but it doesn't answer my question and the duplicate link is simply wrong.
In my case, I think the problem had to do with glob expansion order. Originally, the Checks line in my .clang-tidy looked like this:
Checks: 'clang-diagnostic-*,clang-analyzer-*,*'
I wanted to disable the altera-unroll-loops diagnostic. The fix was to add it after that sneaky glob-all at the end:
Checks: 'clang-diagnostic-*,clang-analyzer-*,*,-altera-unroll-loops'
Initially, I had it placed before the *, which, I think, caused it to be overridden. I also had no problem with it being split across multiple lines, like you have above.
Currently when I print an address of a variable,
cout << &a, its displayed as a simple hexadecimal number, let's say: 008FFBB8.
How can I print an address with the 0x notation? e.g. 0x6FFDF4.
I tried doing:
cout << hex << &a;
but it doesn't seem to work.
There are many different solutions, the first two that came into my mind are the following:
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
int main()
{
std::cout << std::hex
<< "showbase: " << std::showbase<< 42 << '\n'
<< "noshowbase: " << std::noshowbase << 42 << '\n';
//2nd solution
std::string a{"008FFBB8"};
std::cout << "Given: " << a << '\n';
a.erase(0,2);
a = "0x"+a;
std::cout << "Edited: "<< a <<'\n';
//3rd string to int so you can use standard arithmetics
int b = std::stoul(a, nullptr, 16);
std::cout << "Represented as int: " << b << '\n';
std::cin.get();
}
Edit:
This is how it is printed after compilation with GNU GCC(g++) compiler.
The reason visual studio isn't printing it as shown on the screenshot is because visual studio tend not to use GNU GCC but its Microsoft compiler MSVC.(There are other things MSVC isn't doing as you may expect btw.) But good news: you can make it! or here:)
It is just how hex is presented in your configuration with "MSVC"
I hope that answers your question, else leave a comment :)
A simple approach
cout << "0x" << &a;
That said, given that other systems do inlude 0x in &a, in order to make it portable, you should make cout << "0x" conditional based on predefined macro that detects the systems where 0x isn't included.
A portable solution is to insert into a string stream first, then check whether the prefix was added, and concatenate if it wasn't. this also prevents possibility of 0x and the address being separated by concurrent output.
I just wanted to know why Visual Studio is not displaying this notation by default,
Because the authors of their standard library chose to do so.
so I don't have to manually do it.
I'm not sure if there is a way to change their implementation. Before asking how, I recommend considering why you think that you have to do it.
Taking inspiration ;) from MSDN and trying it on VS 2019:
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
ios state(nullptr);
int a;
state.copyfmt(cout); // save current formatting
cout << "In hex: 0x" // now load up a bunch of formatting modifiers
<< hex
<< uppercase
<< setw(8)
<< setfill('0')
<< &a // the actual value we wanted to print out
<< endl;
cout.copyfmt(state); // restore previous formatting
}
Output:
In hex: 0x00AFFB44
And as for why, well...you could raise an issue on MSVC and claim parity with all other compilers and platforms if you have the data. But given that they themselves manually slipped in the 0x I'm guessing they are already comfortable with the behavior.
I was parsing stackoverflow dump and came up on this seemingly innocent question with small, almost invisible detail that it has 22311 spaces at the end of text.
I'm using std::regex (somehow they work better for me than boost::regex) to replace all continuous whitespaces with single space like this:
std::regex space_regex("\\s+", std::regex::optimize);
...
std::regex_replace(out, in, in + strlen(in), space_regex, " ");
SIGSEGV shows up and I have begun to investigate.
Test code:
#include <regex>
...
std::regex r("\\s+", std::regex::optimize);
const char* bomb2 = "Small text\n\nwith several\n\nlines.";
std::string test(bomb2);
for (auto i = 0; i < N; ++i) test += " ";
std::string out = std::regex_replace(test.c_str(), r, " ");
std::cout << out << std::endl;
for (gcc 5.3.0)
$ g++ -O3 -std=c++14 regex-test.cpp -o regex-test.out
maximum N before SIGSEGV shows up is 21818 (for this particular string), and for
$ g++ -O0 -std=c++14 regex-test.cpp -o regex-test.out
it's 12180.
'Ok, let's try clang, it's trending and aims to replace gcc' - never have I been so wrong. With -O0 clang (v. 3.7.1) crashes on 9696 spaces - less then gcc, but not much, yet with -O3 and even with -O2 it crashes on ZERO spaces.
Crash dump presents huge stacktraces (35k frames) of recursive calls of
std::__detail::_Executor<char*, std::allocator<std::__cxx11::sub_match<char*> >, std::__cxx11::regex_traits<char>, true>::_M_dfs
Question 1: Is this a bug? If so, should I report it?
Question 2: Is there smart way to overcome the problem (other than increasing system stack size, trying other regex libraries and writing own function to replace whitespaces)?
Amendment: bug report created for libstdc++
Is this a bug? If so, should I report it?
Yes this is a bug.
cout << '"' << regex_replace("Small text\n\nwith several\n\nlines." + string(22311, ' '), regex("\\s+", regex::optimize), " ") << '"' << endl;
Runs fine with libc++: http://coliru.stacked-crooked.com/a/f9ee5438745a5b22
Runs fine with Visual Studio 2015, you can test by copying and running the code at: http://webcompiler.cloudapp.net/
Fails with libstdc++: http://coliru.stacked-crooked.com/a/3f4bbe5c46b6b627
This has been bugged in libstdc++ here.
Is there smart way to overcome the problem?
If you're asking for a new regex that works, I've tried a handful of different versions, and all of them fail on libstdc++, so I'd say, if you want to use a regex to solve this, you'll need to compile against libc++.
But honestly if you're using a regex to strip duplicate white space, "Now you have two problems"
A better solution could use adjacent_find which runs fine with libstdc++ as well:
const auto func = [](const char a, const char b){ return isspace(a) && isspace(b); };
for(auto it = adjacent_find(begin(test), end(test), func); it != end(test); it = adjacent_find(it, end(test), func)) {
*it = ' ';
it = test.erase(next(it), find_if_not(next(it), end(test), [](const auto& i) { return isspace(i); }));
}
This will return the same thing your regex would:
"Small text with several lines. "
But if you're going for simplicity, you could also use unique:
test.resize(distance(test.begin(), unique(test.begin(), test.end(), [](const auto& a, const auto& b) { return isspace(a) && isspace(b); })));
Which will return:
"Small text
with several
lines. "
Question 2 (smart way to overcome the problem)
Not really smart but... you can iterate a limited replace.
An example
#include <regex>
#include <iostream>
int main()
{
constexpr int N = 22311;
//std::regex r("\\s+");
std::regex r("\\s{2,100}");
const char* bomb2 = "Small text\n\nwith several\n\nlines.";
std::string test(bomb2);
for (auto i = 0; i < N; ++i)
test += " ";
std::string out = test;
std::size_t preSize;
do
{
preSize = out.size();
out = std::regex_replace(out, r, " ");
}
while ( out.size() < preSize );
std::cout << '\"' << out << '\"' << std::endl;
return 0;
}
I am trying to match all files that have the extension .nef - The match must be case insensitive.
regex e("(.*)(\\.NEF)",ECMAScript|icase);
...
if (regex_match ( fn1, e )){
//Do Something
}
here fn1 is a string with a file name.
However, this "does something" only with files with .NEF (upper case) extensions. .nef extensions are ignored.
I also tried -
regex e("(.*)(\\.[Nn][Ee][Ff])");
and
regex e("(.*)(\\.[N|n][E|e][F|f])");
both of which resulted in a runtime error.
terminate called after throwing an instance of 'std::regex_error'
what(): regex_error
Aborted (core dumped)
My code is compiled using -
g++ nefread.cpp -o nefread -lraw_r -lpthread -pthread -std=c++11 -O3
What am I doing wrong? This is my basic code. I want to extend it to match more file extensions .nef, .raw, .cr2 etc.
Your original expression is correct, and should produce the desired result. The problem is with the gcc implementation of <regex>, which is broken. This answer explains the historical reasons why it so, and also says that gcc4.9 will ship with a working <regex> implementation.
Your code works using Boost.Regex
#include <iostream>
#include <string>
#include <boost/regex.hpp>
int main()
{
// Simple regular expression matching
boost::regex expr(R"((.*)\.(nef))", boost::regex_constants::ECMAScript |
boost::regex_constants::icase);
// ^^^ ^^
// no need escape the '\' if you use raw string literals
boost::cmatch m;
for (auto const& fname : {"foo.nef", "bar.NeF", "baz.NEF"}) {
if(boost::regex_match(fname, m, expr)) {
std::cout << "matched: " << m[0] << '\n';
std::cout << " " << m[1] << '\n';
std::cout << " " << m[2] << '\n';
}
}
}
Live demo
I'm having troubles with std regex. I can't make the question mark quantifier work. The call to regex_match will always return 0.
I also tried with {0,1} which doesn't behave like I expected either: it behaves like a + quantifier.
Here is my code :
#include <iostream>
#include <regex>
using namespace std;
int main(int argc, char **argv){
regex e1("ab?c");
cout << regex_match("ac", e1) << endl; // expected : 1, output 0
cout << regex_match("abc", e1) << endl; // expected : 1, output 0
cout << regex_match("abbc", e1) << endl; // expected : 0, output 0
regex e2("ab{0,1}c");
cout << regex_match("ac", e2) << endl; // expected : 1, output 0
cout << regex_match("abc", e2) << endl; // expected : 1, output 1
cout << regex_match("abbc", e2) << endl; // expected : 0, output 1
return 0;
}
I used the following command to compile:
g++ -std=c++11 main.cpp -o regex_test
Am i doing something wrong here? Or why isn't it working?
Your regular expression code is fine. The implementation that you're using is not. It provides a header that declares a bunch of things that the library implements badly. If a commercial package did that it would be roundly criticized, and rightly so. You get what you pay for.
str::regex is mostly not implemented in gcc (at the time of writing). See section 28 at:
http://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#status.iso.2011
The POSIX standard for regular expressions defines two type, basic and extended. The ? operator is an extended feature. Apparently you use
std::regex re2(".*(a|xayy)", std::regex::extended)
to get the extended features.