Bug in gcc wstring_convert? - c++

I use MinGW 8.1.0 64-bit. This code snippet:
#include <clocale>
#if __has_include(<codecvt>)
#include <codecvt>
#endif
#include <cstdlib>
#include <locale>
#include <string>
#include <wchar.h>
#include <iostream>
int main() {
auto utf8_decode = [](const std::string &str) -> std::wstring {
std::wstring_convert<std::codecvt_utf8<wchar_t>> myconv;
return myconv.from_bytes(str);
};
std::string test = "=";
auto s = utf8_decode(test);
std::wcout << s << std::endl;
return 0;
}
outputs a hieroglyphic (or some gibberish) on Windows, but outputs = (as expected) on Linux.
Is this a bug in standard library or am I missing something?

Looks like this is indeed a bug in MinGW libstdc++.dll; codecvt incorrectly chooses big endian so = (0x3d) becomes 㴀 (0x3d00).
Proposed workaround - manually force little-endian by using codecvt_utf8<wchar_t, 0x10ffff, std::little_endian>

Related

compile c++ file in linux terminal: string_view : No such file or directory

I have gcc (Cadence) 4.8.3. And I want to compile a c++ file which has an include string_view. When I compile the file:
g++ script.cpp
the following error occurs:
script.cpp:4:23: fatal error: string_view: No such file or directory
#include <string_view>
^
compilation terminated.
I tried upgrading my gcc version but I couldn't.
sudo apt-get install gcc-5
sudo: apt-get: command not found
My question is how can I fix this problem, how can I upgrade my gcc version or is there an alternative that can replace the string_view library.
The .cpp script is the following:
#include <iostream>
#include <string>
#include <map>
#include <string_view>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include<cmath>
#include <fstream>
#include <string>
#include <sstream>
#include <iomanip>
#define FEATURE 27
double get_value(std::string_view value_str,double* smons) {
std::map<std::string, double *> arrays_names {
{"smons", smons}
};
auto name_end_pos = value_str.find('[');
auto name = value_str.substr(0, name_end_pos);
auto index_end_pos = value_str.find(']');
auto index_len = index_end_pos - name_end_pos - 1;
std::string index_str{value_str.substr(name_end_pos + 1, index_len)};
auto index = std::stoi(index_str);
return arrays_names[std::string(name)][index];
}
double evaluate_expression(const std::string& expr,double* smons) {
double a;
if (expr.size()==8)
{
a=get_value(expr.substr(0, 8),smons);
}
else if (expr.size()==9)
{
a=get_value(expr.substr(0, 9),smons);
}
else if (expr.size()==17)
{
a=get_value(expr.substr(0, 8),smons) * get_value(expr.substr(9, 8),smons);
}
else if (expr.size()==18)
{
a=get_value(expr.substr(0, 8),smons) * get_value(expr.substr(9, 9),smons);
}
else if (expr.size()==19)
{
a=get_value(expr.substr(0, 9),smons) * get_value(expr.substr(10, 9),smons);
}
return
a;
}
You'll need to update your compiler. std::string_view is not available in GCC until version 7.

How to convert const std::filesystem::directory_entry to tchar?

I'm trying to convert const std::filesystem::directory_entry (dirent) to tchar but I don't understand how it an be done. I tried a lot of ways. Can you help me?
Edited:
#include "pch.h"
#include <memory>
#include <filesystem>
#include <algorithm>
#include <iostream>
#include <tchar.h>
#include <string.h>
typedef wchar_t WCHAR;
namespace fs = std::filesystem;
int main() try
{
std::for_each(fs::recursive_directory_iterator("./foo/"), {},
[](fs::directory_entry const& dirent)
{
if (fs::is_regular_file(dirent) &&
dirent.path().filename() == "black.txt")
{
std::wstring = path.wstring();
}
});
}
catch (fs::filesystem_error const& e)
{
std::cerr << "error: " << e.what() << '\n';
}
You can convert std::filesystem::path to any form using these functions:
std::string string() const;
std::wstring wstring() const;
std::u16string u16string() const;
std::u32string u32string() const;
TCHAR is somewhat of a relic as mentioned in the comments, and you're much better off using any of the above alternatives.
If you're going to pass it to Win32 API functions, I would either suggest using wstring explicitly and not bother with the shape-shifting TCHAR at all.
What your code should look like is this:
if (fs::is_regular_file(dirent) &&
dirent.path().filename() == "black.txt")
{
std::wstring path_as_string = path.wstring();
}
No TCHAR, no C-style arrays no C-style memory copying.

using std::string disables program output

Whenever I use std::string to declare a string variable in c++ it prevents the program from outputting anything. for example:
#include <cstdlib>
#include <iostream>
#include <string>
int main() {
std::cout << "Hello";
// std::string s;
return 0;
}
This will output Hello to the command-line as it should do.
#include <cstdlib>
#include <iostream>
#include <string>
int main() {
std::cout << "Hello";
std::string s;
return 0;
}
This will not output anything (and no errors) since i'm declaring a variable using std::string
I'm using the minGW compiler on a Windows 10 64bit machine

Is <iostream> needed to use a string in c++?

This code works for me:
#include <string>
#include <iostream>
int main()
{
std::string s;
s = "hello world";
cout << s;
return 0;
}
But this one doesn't:
#include <string>
int main()
{
string s;
s = "hello world";
return 0;
}
Is the include of <iostream> needed as well as the <string> one?
I'm using Eclipse CDT IDE.
Iostream is not needed to use string. You are missing using namespace std (or alternatively using the std:: prefix) in the second example, that's why it's not working.

BOOST.IOstreams: trouble to write to bzip2

Hello I am would like to store my data in to bzip2 file using Boost.IOstreams.
void test_bzip()
{
namespace BI = boost::iostreams;
{
string fname="test.bz2";
{
BI::filtering_stream<BI::bidirectional> my_filter;
my_filter.push(BI::combine(BI::bzip2_decompressor(), BI::bzip2_compressor())) ;
my_filter.push(std::fstream(fname.c_str(), std::ios::binary|std::ios::out)) ;
my_filter << "test" ;
}//when my_filter is destroyed it is trowing an assertion.
}
};
What I am doing wrong?
I am using boost 1.42.0.
kind regards
Arman.
EDIT
The code is working if I remove the bidirectional option:
#include <fstream>
#include <iostream>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/bzip2.hpp>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <string>
void test_bzip()
{
namespace BI = boost::iostreams;
{
std::string fname="test.bz2";
{
std::fstream myfile(fname.c_str(), std::ios::binary|std::ios::out);
BI::filtering_stream<BI::output> my_filter;
my_filter.push(BI::bzip2_compressor()) ;
//my_filter.push(std::fstream(fname.c_str(), std::ios::binary|std::ios::out)) ; //this line will work on VC++ 2008 V9 but not in G++ 4.4.4
my_filter.push(myfile);
my_filter << "test";
}
}
};
maybe some one can explain why?
An fstream can not be copied, so you must use the reference version of push
template<typename StreamOrStreambuf>
void push( StreamOrStreambuf& t,
std::streamsize buffer_size = default value,
std::streamsize pback_size = default value );
So your function should look something like
std::fstream theFile(fname.c_str(), std::ios::binary | std::ios::out);
// [...]
my_filter.push(theFile) ;
I'm suprised you compiler allows your code, I'd think it complain about a reference to temporary... which compiler are you using?