Convert a char16_t to long/integer, (atoi / atol equivalent) - c++11

I want to convert a char16_t to an integer and/or a long.
const char16_t* t = u"12";
long lt = atol( t);
Does such a function not exist?

Try this function: (it's not necessarily the most efficient solution, but it gets the job done if you have no choice (i.e. you have to have a char16_t* as input) and you're sure that you actually have a valid sequence of digits in your char16_t* string)
Run It Online
#include <codecvt>
#include <locale>
#include <string>
int char16_to_int(const char16_t* s16)
{
// https://stackoverflow.com/a/7235204/865719
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
std::string str = convert.to_bytes(s16);
return std::stoi(str);
}
long char16_to_long(const char16_t* s16)
{
// https://stackoverflow.com/a/7235204/865719
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
std::string str = convert.to_bytes(s16);
return std::stol(str);
}
EDIT: I've refactored the solution just a little bit to reduce repetition:
Run It Online
#include <codecvt>
#include <locale>
#include <string>
std::string char16_to_string(const char16_t* s16)
{
// https://stackoverflow.com/a/7235204/865719
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
return convert.to_bytes(s16);
}
long char16_to_long(const char16_t* s16)
{
return stol(char16_to_string(s16));
}
int char16_to_int(const char16_t* s16)
{
return stoi(char16_to_string(s16));
}

Related

Error E0146 : Too many initializer values C++

I have a school project and I have to use the AM in the Student.h as a char*.The AM have to have numbers in it. I can't understand why what I am doing is not working.
Student.cpp
#include <iostream>
#include <string>
#include "Student.h"
using namespace std;
int main()
{
Student dlg;
dlg.AM[10]={2,1,3,9,0,2,6,6};
}
Student.h
#pragma once
#include <string>
using namespace std;
class Student
{
public:
char *AM[20];
string Name;
unsigned int Semester = 1;
};
If you really need your student number to be a char string, then you need to convert your ints to char* before assigning them to the array.
int main()
{
Student dlg;
int j = 0;
for (auto i : {2,1,3,9,0,2,6,6})
{
auto strInt { std::to_string(i) }; // create a C++ string containing a int
// next copy the internal memory of the C++ string to a read-writable memory buffer
// and assign a pointer to that buffer casted to a char* to the appropriate slot in the array
dlg.AM[j++] = static_cast<char*> (std::memcpy (new char[16], strInt.c_str(), strInt.size()));
}
// test
for (int i = 0; i < 8; i++)
{
cout << dlg.AM[i] << ' ';
}
}
Are you sure the student number should be a char* ?

Getting Enviroment Variable with cpp

So I have been trying to figure out how to find an environment variable and print it out on the screen in c++
but for the last 3 hours or so, I have been stuck. When I print out the currentDesktop variable it only prints out "/Desktop". But what I'm looking for is the username in front of it.
I have been reading the documentation on the GetEnviromentVariable function from Microsoft's forum and this is what I have come up with so far.
Help would be greatly appreciated since I'm not so experienced yet, Thx.
#include <iostream>
#include <string>
#include <windows.h>
#include <fstream>
#define BUFSIZE 4096
using namespace std;
int main()
{
LPCWSTR Env = L"%USERPROFILE";
LPTSTR pszOldVal;
string IPADD;
pszOldVal = (LPTSTR)malloc(BUFSIZE * sizeof(TCHAR));
if (NULL == pszOldVal)
{
printf("Out of memory\n");
return FALSE;
}
string currentDesktop = GetEnvironmentVariable(Env,pszOldVal,BUFSIZE) + "\\Desktop";
cout << currentDesktop;
return 0;
}
You are misusing the GetEnvironmentVariable() function. For one thing, you are missing the trailing % on the variable name L"%USERPROFILE". For another thing, the return value is the number of characters copied into the supplied buffer. You are adding that integer to the string literal "\\Desktop", which is not what you want.
Try this instead:
#include <iostream>
#include <string>
#include <windows.h>
std::wstring GetEnv(const std::wstring &varName)
{
std::wstring str;
DWORD len = GetEnvironmentVariableW(varName.c_str(), NULL, 0);
if (len > 0)
{
str.resize(len);
str.resize(GetEnvironmentVariableW(varName.c_str(), &str[0], len));
}
return str;
}
std::wstring GetUserDesktopPath()
{
std::wstring path = GetEnv(L"%USERPROFILE%");
if (!path.empty()) path += L"\\Desktop";
return path;
}
int main()
{
std::wstring currentDesktop = GetUserDesktopPath();
std::wcout << currentDesktop;
return 0;
}
That being said, if you just want the username, use %USERNAME% instead of %USERPROFILE%. Or better, use GetUserName() instead of GetEnvironmentVariable():
#include <iostream>
#include <string>
#include <windows.h>
std::wstring GetUserName()
{
std::wstring str;
DWORD len = 0;
if (!GetUserNameW(NULL, &len))
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
str.resize(len);
if (GetUserNameW(&str[0], &len))
str.resize(len-1);
else
str = L"";
}
}
return str;
}
int main()
{
std::wstring currentUser = GetUserName();
std::wcout << currentUser;
return 0;
}
However, the correct way to get the path to the user's desktop is to just ask Windows for that specific path, don't assume it is in the root of the user's profile, or that is is named Desktop. Use SHGetFolderPath() or SHGetKnownFolderPath() for that query, eg:
#include <iostream>
#include <string>
#include <windows.h>
#include <shlobj.h>
std::wstring GetFolderPath(CSIDL folderID)
{
WCHAR path[MAX_PATH] = {};
SHGetFolderPathW(NULL, folderID, NULL, SHGFP_TYPE_CURRENT, path);
return path;
}
/* or:
std::wstring GetFolderPath(REFKNOWNFOLDERID folderID)
{
std::wstring str;
PWSTR path = NULL;
if (SHGetKnownFolderPath(folderID, 0, NULL, &path) == S_OK)
str = path;
CoTaskMemFree(path);
return str;
}
*/
std::wstring GetUserDesktopPath()
{
return GetFolderPath(CSIDL_DESKTOPDIRECTORY);
// or: return GetFolderPath(FOLDERID_Desktop);
}
int main()
{
std::wstring currentDesktop = GetUserDesktopPath();
std::wcout << currentDesktop;
return 0;
}

Boost asio: including <arpa/inet.h> causes socket to always output 0 bytes

I'm trying to include <arpa/inet.h> in a low-level library so that I have access to hton* and ntoh* functions in the library. The low-level library gets called into by higher-level code running a Boost asio socket. I'm aware Boost asio contains the hton* and ntoh* functions, but i'd like to avoid linking all of Boost asio to the library since hton*/ntoh* are all I need.
However, if I simply include <arpa/inet.h> in the low-level library, 0 bytes always will be sent from the Boost asio socket. Confirmed by Wireshark.
Here's the class where i'd like to include <arpa/inet.h> but not Boost. If <arpa/inet.h> is included, 0 bytes will be sent.
#pragma pack(push, 1)
#include "PduHeader.h"
#include <arpa/inet.h>
class ClientInfoPdu
{
public:
ClientInfoPdu(const uint16_t _client_receiver_port)
{
set_client_receiver_port(_client_receiver_port);
}
PduHeader pdu_header{CLIENT_INFO_PDU, sizeof(client_receiver_port)};
inline void set_client_receiver_port(const uint16_t _client_receiver_port)
{
//client_receiver_port = htons(_client_receiver_port);
client_receiver_port = _client_receiver_port;
}
inline uint16_t get_client_receiver_port()
{
return client_receiver_port;
}
inline size_t get_total_size()
{
return sizeof(PduHeader) + pdu_header.get_pdu_payload_size();
}
private:
uint16_t client_receiver_port;
};
#pragma pack(pop)
Here's the higher level code that includes Boost and attempts to send the data via a socket. The printout indicates 5 bytes were sent, however 0 bytes were actually sent.
#include "ServerConnectionThread.h"
#include "config/ClientConfig.h"
#include "protocol_common/ClientInfoPdu.h"
#include <boost/asio.hpp>
#include <unistd.h>
using boost::asio::ip::udp;
void ServerConnectionThread::execute()
{
boost::asio::io_service io_service;
udp::endpoint remote_endpoint =
udp::endpoint(boost::asio::ip::address::from_string(SERVER_IP), SERVER_PORT);
udp::socket socket(io_service);
socket.open(udp::v4());
ClientInfoPdu client_info_pdu = ClientInfoPdu(RECEIVE_PORT);
while (true)
{
uint16_t total_size = client_info_pdu.get_total_size();
socket.send_to(boost::asio::buffer(&client_info_pdu, total_size), remote_endpoint);
printf("sent %u bytes\n", total_size);
usleep(1000000);
}
}
Again, simply removing "#include <arpa/inet.h>" will cause this code to function as expected and send 5 bytes per packet.
How is ClientInfoPdu defined? This looks like it is likely UB:
boost::asio::buffer(&client_info_pdu, total_size)
The thing is total size is sizeof(PduHeader) + pdu_header.get_pdu_payload_size() (so sizeof(PduHeader) + 2);
First problem is that you're mixing access modifiers, killing the POD/standard_layout properties of your types.
#include <type_traits>
static_assert(std::is_standard_layout_v<PduHeader> && std::is_trivial_v<PduHeader>);
static_assert(std::is_standard_layout_v<ClientInfoPdu> && std::is_trivial_v<ClientInfoPdu>);
This will fail to compile. Treating the types as POD (as you do) invokes
Undefined Behaviour.
This is likely the explanation for the fact that "it stops working" with some changes. It never worked: it might just accidentally have appeared to work, but it was undefined behaviour.
It's not easy to achieve POD-ness while still getting the convenience of the
constructors. In fact, I don't think that's possible. In short, if you want to
treat your structs as C-style POD types, make them... C-style POD types.
Another thing: a possible implementation of `PduHeader I
can see working for you looks a bit like so:
enum MsgId{CLIENT_INFO_PDU=0x123};
struct PduHeader {
MsgId id;
size_t payload_size;
size_t get_pdu_payload_size() const { return payload_size; }
};
Here, again you might have/need endianness conversions.
Suggestion
In short, if you want this to work, I'd say keep it simple.
Instead of creating non-POD types all over the place that are responsible for endianness conversion by adding getters/setters for each value, why not create a simple user-defined-type that does this always, and use them instead?
struct PduHeader {
Short id; // or e.g. uint8_t
Long payload_size;
};
struct ClientInfoPdu {
PduHeader pdu_header; // or inheritance, same effect
Short client_receiver_port;
};
Then just use it as a POD struct:
while (true) {
ClientInfoPdu client_info_pdu;
init_pdu(client_info_pdu);
auto n = socket.send_to(boost::asio::buffer(&client_info_pdu, sizeof(client_info_pdu)), remote_endpoint);
printf("sent %lu bytes\n", n);
std::this_thread::sleep_for(1s);
}
The function init_pdu can be implemented with overloads per submessage:
void init_pdu(ClientInfoPdu& msg) {
msg.pdu_header.id = CLIENT_INFO_PDU;
msg.pdu_header.payload_size = sizeof(msg);
}
There are variations on this where it can become a template or take a
PduHeder& (if your message inherits instead of aggregates). But the basic
principle is the same.
Endianness Conversion
Now you'll noticed I avoided using uint32_t/uint16_t directly (though uint8_t is fine because it doesn't need byte ordering). Instead, you could define Long and Short as simple POD wrappers around them:
struct Short {
operator uint16_t() const { return ntohs(value); }
Short& operator=(uint16_t v) { value = htons(v); return *this; }
private:
uint16_t value;
};
struct Long {
operator uint32_t() const { return ntohl(value); }
Long& operator=(uint32_t v) { value = htonl(v); return *this; }
private:
uint32_t value;
};
The assignment and conversions mean that you can use it as just another
int32_t/int16_t except that the necessary conversions are always done.
If you want to satnd on the shoulder of giants instead, you can use the better types from Boost Endian, which also has lots more advanced facilities
DEMO
Live On Coliru
#include <type_traits>
#include <cstdint>
#include <thread>
#include <arpa/inet.h>
using namespace std::chrono_literals;
#pragma pack(push, 1)
enum MsgId{CLIENT_INFO_PDU=0x123};
struct Short {
operator uint16_t() const { return ntohs(value); }
Short& operator=(uint16_t v) { value = htons(v); return *this; }
private:
uint16_t value;
};
struct Long {
operator uint32_t() const { return ntohl(value); }
Long& operator=(uint32_t v) { value = htonl(v); return *this; }
private:
uint32_t value;
};
static_assert(std::is_standard_layout_v<Short>);
static_assert(std::is_trivial_v<Short>);
static_assert(std::is_standard_layout_v<Long>);
static_assert(std::is_trivial_v<Long>);
struct PduHeader {
Short id; // or e.g. uint8_t
Long payload_size;
};
struct ClientInfoPdu {
PduHeader pdu_header; // or inheritance, same effect
Short client_receiver_port;
};
void init_pdu(ClientInfoPdu& msg) {
msg.pdu_header.id = CLIENT_INFO_PDU;
msg.pdu_header.payload_size = sizeof(msg);
}
static_assert(std::is_standard_layout_v<PduHeader> && std::is_trivial_v<PduHeader>);
static_assert(std::is_standard_layout_v<ClientInfoPdu> && std::is_trivial_v<ClientInfoPdu>);
#pragma pack(pop)
#include <boost/asio.hpp>
//#include <unistd.h>
using boost::asio::ip::udp;
#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 6767
#define RECEIVE_PORT 6868
struct ServerConnectionThread {
void execute() {
boost::asio::io_service io_service;
udp::endpoint const remote_endpoint =
udp::endpoint(boost::asio::ip::address::from_string(SERVER_IP), SERVER_PORT);
udp::socket socket(io_service);
socket.open(udp::v4());
while (true) {
ClientInfoPdu client_info_pdu;
init_pdu(client_info_pdu);
auto n = socket.send_to(boost::asio::buffer(&client_info_pdu, sizeof(client_info_pdu)), remote_endpoint);
printf("sent %lu bytes\n", n);
std::this_thread::sleep_for(1s);
}
}
};
int main(){ }

STD::FUNCTION C++

I'm still learning Modern C++ and I would like to clarify STD:FUNCTION,
Here is my sample code that works fine :
#include <iostream>
#include <functional>
using namespace std;
int func(function<bool()> foo) {
return 2;
}
struct fee {
bool operator()() {
return true;
}
};
int main() {
cout << func(fee());
}
It will display "2" on the console.
What I am wondering is why this does not work. I changed bool operator()() to bool operator()(int i).
#include <iostream>
#include <functional>
using namespace std;
int func(function<bool()> foo) {
return 2;
}
struct fee {
bool operator()(int i) {
return true;
}
};
int main() {
cout << func(fee());
}
The error says:
In function 'int main()':
18:20: error: could not convert 'fee()' from 'fee' to 'std::function<bool()>'
What should be the right thing to do ?
In the second example, the fee operator() function now takes an int as a parameter.
Therefore you need to change
int func(function<bool()> foo) {
return 2;
}
to
int func(function<bool(int)> foo) {
return 2;
}
to reflect that.

inserting a range of struct vector into a vector of a struct member type

Is it possible to insert range of struct directly into vector of the same type (same type of a member of struct).
Let's have a struct and vectors like this:
struct pnt {
char _name;
int _type;
bool _aux;
};
std::vector<pnt> pnts;
std::vector<int> pntType;
The question is that how to insert a range of pnts into pntType using single standard line of C++98:
void insert (iterator position, InputIterator first, InputIterator last);
or even Boost library.
Since I am using this often in different parts of my code, I am trying to avoid doing this in a loop. The last option is defining a function for that.
EDIT:
I know the insert syntax. What I cannot do is how to insert from pnts (only _type of each member) into pntType
UPDATE: There is a better way than my first suggestion (see bottom), since we're already using Boost. The problem with std::transform and std::insert_iterator is that v2 is resized several times, which is wasteful considering that we know the width of the range in advance. Using boost::transform_iterator and boost::bind, it is possible to avoid the problem like this:
#include <boost/bind.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
struct A {
int x;
};
int main() {
A arr[] = {
{ 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }
};
std::vector<A> v1(arr, arr + 6);
std::vector<int> v2;
v2.insert(v2.begin(),
boost::make_transform_iterator(v1.begin() + 2, boost::bind(&A::x, _1)),
boost::make_transform_iterator(v1.begin() + 4, boost::bind(&A::x, _1)));
std::copy(v2.begin(), v2.end(), std::ostream_iterator<int>(std::cout, "\n"));
}
OLD SUGGESTION:
boost::bind works with data member pointers, so using C++98 and Boost, you could do something like this without changing your struct:
#include <boost/bind.hpp>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
struct A {
int x;
};
int main() {
A arr[] = {
{ 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }
};
std::vector<A> v1(arr, arr + 6);
std::vector<int> v2;
// one-liner here:
std::transform(v1.begin() + 2,
v1.begin() + 4,
std::insert_iterator<std::vector<int> >(v2, v2.begin()),
boost::bind(&A::x, _1));
std::copy(v2.begin(), v2.end(), std::ostream_iterator<int>(std::cout, "\n"));
}
Using boost range:
boost::copy(pnts | transformed(std::mem_fn(&pnt::_type)), std::back_inserter(pntType));
Or even
boost::copy_range<std::vector<int>>(pnts | transformed(std::mem_fn(&pnt::_type)));
See it Live on Coliru
Note you can use boost::bind(&pnt:_type,_1) instead of mem_fn to allow for your compiler version
Updated To show with specific first/last iterators, and compiling in c++03 mode:
Live On Coliru
#include <boost/range/algorithm.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/bind.hpp>
using namespace boost::adaptors;
using namespace boost;
struct pnt {
char _name;
int _type;
bool _aux;
};
int main() {
std::vector<pnt> pnts(6);
std::vector<int> pntType;
boost::copy(
make_iterator_range(pnts.begin(), pnts.begin()+3) | transformed(bind(&pnt::_type, _1)),
std::back_inserter(pntType));
}
Inserting one container into the other works like this:
pntType.insert(pntType.begin(),pnts.begin(),pnts.end());
To be able to insert the correct type, you should add a conversion operator to int to your struct.
struct pnt {
char _name;
int _type;
bool _aux;
operator int (){
return _type;
}
};

Resources