Printing Unicode Japanese characters with WriteConsoleW [duplicate] - c++

This question already has answers here:
printing Unicode characters C++
(3 answers)
Closed 6 years ago.
So, I'm trying to print some Japanese characters. I tried every possible thing. What am I missing?
#include <windows.h>
#include <string>
template<typename T>
void printW(const T* text) {
WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), text, std::char_traits<T>::length(text), 0, 0);
}
template<typename T>
void print(const T* text) {
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), text, std::char_traits<T>::length(text), 0, 0);
}
int main()
{
//const char* text = "こんにちは\n";
const wchar_t* textL = L"こんにちは\n";
const char16_t* textu = u"こんにちは\n";
const char32_t* textU = U"こんにちは\n";
//printW(text);
printW(textL);
printW(textu);
printW(textU);
}

WinAPI not needed, also you're using the wrong types.
#include <iostream>
#include <string>
int main()
{
std::string text{u8"こんにちは"};
std::cout << text;
}
Live example
If you need to use the WinAPI, minimal modification is needed:
#include <windows.h>
#include <string>
template<typename T>
void print(const T* text) {
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), text, std::char_traits<T>::length(text), 0, 0);
}
int main()
{
auto text = u8"こんにちは\n";
print(text);
}
disclaimer: not tested on actual windows machine

Related

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.

C and C++ : data file with error "Expected unqualified-id" [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I would like to run C code in C++, using Xcode 8.33 on MacOS Sierra 10.12. I am new to C/C++, compilers, etc so please bear with me. The C code, when compiled and ran with make via Terminal, works. But when I throw all the same files into a XCode C++ project, there is an error with the data file. Note: I did change main.c to main.cpp.
//**** main.cpp *****
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
extern "C" {
#include "msclib.h"
}
int main(int argc, char** argv)
{
assert(argc >= 1);
return msc_get_no(argv[1]);
}
The file msclib.c calls on the data file mscmix_dat.c. Here is also msclib.h
// ***** msclib.h *****
extern size_t msc_get_no(const char*);
// ***** msclib.c *****
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <ctype.h>
#include "msclib.h"
struct msc_data
{
const char* code;
const char* desc;
};
typedef struct msc_data MSCDat;
static const MSCDat mscdat[] =
#include "mscmix_dat.c"
;
static const size_t msccnt = sizeof(mscdat) / sizeof(mscdat[0]);
static int msc_cmp(const void* a, const void* b)
{
const char* msc_code = a;
const MSCDat* p = b;
return strcmp(msc_code, p->code);
}
size_t msc_get_no(const char* msc_code)
{
assert(NULL != msc_code);
assert(strlen(msc_code) == 5);
MSCDat* p = bsearch(msc_code, &mscdat[0], msccnt, sizeof(mscdat[0]), msc_cmp);
if (NULL == p)
{
fprintf(stderr, "MSC \"%s\" not valid\n", msc_code);
return 0;
}
assert(NULL != p);
return p - &mscdat[0];
}
When running/compiling, the mscmix_dat.c file gets the error Expected identifier or ( - which is what I need help with. Even when I replace mscmix_dat.c with .cpp, I get the error Expected unqualified-id
// ***** mscmix_dat.c *****
{ //<-- Xcode highlights this line and gives the error
{ "*****", "Error" },
{ "00-01", "Instructional exposition (textbooks, tutorial papers, etc.)" },
{ "00-02", "Research exposition (monographs, survey articles)" },
{ "00A05", "General mathematics" },
.
.
.
}
I would appreciate explanations as to why this error is occurring, suggestions on how to fix it, and if necessary alternatives to processing this data file. Thank you!
OP here. These are the steps I took to resolve my issue, based on the last edit of my question:
With the separate files, as given in my question, the error was Expected identifier in mscmix_dat.c.
Per #LightnessRacesinOrbit's suggestion, I consolidated the multiple main.cpp, msclib.h, msclib.c, and mscmix_dat.c files into two files: main.cpp and msclib.c, by replacing the #include thisfile.c with the actual file code content. I also changed msclib.c to .cpp via simple rename. This eliminated the original error of Expected identifier, but a new one arose.
Compiling the two files gave multiple errors in msclib.cpp, all wrt variable type conversions.
Because of C++ differences from C, I handled the type conversion issue via casting, but also respecting const.
Below is my final, successfully compiling code.
// **** main.cpp ****
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include<string>
#include<iostream>
using namespace std;
extern size_t msc_get_no(const char*);
int main(int argc, char** argv)
{
assert(argc >= 0);
return (int)msc_get_no(argv[1]); // casting
}
// **** msclib.cpp ****
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <ctype.h>
extern size_t msc_get_no(const char*);
struct msc_data
{
const char* code;
const char* desc;
};
typedef struct msc_data MSCDat;
static const MSCDat mscdat[] =
{
{ "*****", "Error" },
{ "00-01", "Instructional exposition (textbooks, tutorial papers, etc.)" },
{ "00-02", "Research exposition (monographs, survey articles)" },
{ "00A05", "General mathematics" }
}
;
static const size_t msccnt = sizeof(mscdat) / sizeof(mscdat[0]);
static int msc_cmp(const void* a, const void* b)
{
const char* msc_code = static_cast<const char*>(a); //<----
const MSCDat* p = static_cast<const MSCDat*>(b); // (const MSCDat*)b also works
return strcmp(msc_code, p->code);
}
size_t msc_get_no(const char* msc_code)
{
assert(NULL != msc_code);
assert(strlen(msc_code) == 5);
MSCDat* p; // changed initialization of p
p = (MSCDat*) bsearch(msc_code, &mscdat[0], msccnt, sizeof(mscdat[0]), msc_cmp);
if (NULL == p)
{
fprintf(stderr, "MSC \"%s\" not valid\n", msc_code);
return 0;
}
assert(NULL != p);
return p - &mscdat[0];
}

Left shift bit operator overloading

Hello guys,
I am trying to overload the left shift bit operator, <<, to do something like:
char value[] = "Hello";
value << 2;
when doing this I would like to have it printed like: "val", so to delete the last two character; My problem is I can't manage to declare my overloading function properly.
My code is:
//the .h file
#pragma once
#include <iostream>
class Operators
{
public:
char *word;
int number;
Operators(void);
Operators(char str[], int num);
~Operators(void);
void Print(void);
friend char & operator<<(char &stream, int &nr);
};
#include "StdAfx.h"
#include "Operators.h"
#include <iostream>
Operators::Operators(void)
{
word = "";
number = 0;
}
Operators::Operators(char *str, int num)
{
word = str;
number = num;
}
Operators::~Operators(void)
{
}
void Operators::Print(void)
{
printf("\nThe String: %s", word);
}
friend char & operator<<(char &stream, int &nr)
{
return stream;
}
// Operator_Overloading.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "Operators.h"
#include <conio.h>
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
char value[] = "Hello";
Operators op(value, 2);
op.Print();
_getch();
return 0;
}
You cannot overload any of the operators if they don't involve, at least, one user defined type. Your use case involves a char[N] and an int, i.e., you can't overload any operators for these arguments.

human-readable type_info.name() [duplicate]

This question already has answers here:
Is it possible to print a variable's type in standard C++?
(25 answers)
Closed 3 years ago.
I've compiled the following code with g++, and got output, which written in comments.
template<class T>
void foo(T t) { cout << typeid(t).name() << endl; }
int main() {
foo("f"); //emits "PKc"
foo(string()); //emits "Ss"
}
I know, that type_info.name() isn't standartized, but is there any way to get human-readable results?
Something like the following would be good enought
const char *
class string
You can use abi::__cxa_demangle for that (demangle function taken from here), just remember that the caller is responsible for freeing the return:
#include <cxxabi.h>
#include <typeinfo>
#include <iostream>
#include <string>
#include <memory>
#include <cstdlib>
std::string demangle(const char* mangled)
{
int status;
std::unique_ptr<char[], void (*)(void*)> result(
abi::__cxa_demangle(mangled, 0, 0, &status), std::free);
return result.get() ? std::string(result.get()) : "error occurred";
}
template<class T>
void foo(T t) { std::cout << demangle(typeid(t).name()) << std::endl; }
int main() {
foo("f"); //char const*
foo(std::string()); //std::string
}
Example on ideone.

passing struct parameter by reference c++

how can i pass a struct parameter by reference c++, please see below the code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;
struct TEST
{
char arr[20];
int var;
};
void foo(char * arr){
arr = "baby"; /* here need to set the test.char = "baby" */
}
int main () {
TEST test;
/* here need to pass specific struct parameters, not the entire struct */
foo(test.arr);
cout << test.arr <<endl;
}
The desired output should be baby.
I would use std::string instead of c arrays in c++
So the code would look like this;
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <iostream>
using namespace std;
struct TEST
{
std::string arr;
int var;
};
void foo(std::string& str){
str = "baby"; /* here need to set the test.char = "baby" */
}
int main () {
TEST test;
/* here need to pass specific struct parameters, not the entire struct */
foo(test.arr);
cout << test.arr <<endl;
}
That's not how you want to assign to arr.
It's a character buffer, so you should copy characters to it:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;
struct TEST
{
char arr[20];
int var;
};
void foo(char * arr){
strncpy(arr, "Goodbye,", 8);
}
int main ()
{
TEST test;
strcpy(test.arr, "Hello, world");
cout << "before: " << test.arr << endl;
foo(test.arr);
cout << "after: " << test.arr << endl;
}
http://codepad.org/2Sswt55g
It looks like you are using C-strings. In C++, you should probably look into using std::string. In any case, this example is passed a char array. So in order to set baby, you will need to do it one character at a time (don't forget \0 at the end for C-strings) or look into strncpy().
So rather than arr = "baby" try strncpy(arr, "baby", strlen("baby"))
It won't work for you beause of the reasons above, but you can pass as reference by adding a & to the right of the type. Even if we correct him at least we should answer the question. And it wont work for you because arrays are implicitly converted into pointers, but they are r-value, and cannot be converted into reference.
void foo(char * & arr);