我一直在探索C++ 11的新Unicode功能,虽然其他C++ 11编码问题非常有用,但我对cppreference的以下代码片段有疑问 .代码写入然后立即读取以UTF-8编码保存的文本文件.
// Write
std::ofstream("text.txt") << u8"z\u6c34\U0001d10b";
// Read
std::wifstream file1("text.txt");
file1.imbue(std::locale("en_US.UTF8"));
std::cout << "Normal read from file (using default UTF-8/UTF-32 codecvt)\n";
for(wchar_t c; file1 >> c; ) // ?
std::cout << std::hex << std::showbase << c << '\n';
Run Code Online (Sandbox Code Playgroud)
我的问题非常简单,为什么循环中wchar_t需要for?一个u8文本字符串可以使用一个简单的声明char *和UTF-8编码的位布局应告诉系统字符的宽度.似乎有一些从UTF-8到UTF-32的自动转换(因此wchar_t),但如果是这种情况,为什么转换是必要的?
我怎么可以转换wchar_t('9')到一个数字中的形式int(9)?
我有以下代码,我检查是否peek是一个数字:
if (iswdigit(peek)) {
// store peek as numeric
}
Run Code Online (Sandbox Code Playgroud)
我可以减去'0'或者是否有一些我应该担心的Unicode细节?
我的C程序粘贴在下面.在bash中,程序打印"char is",Ω不打印.我的语言环境都是en_US.utf8.
#include <stdio.h>
#include <wchar.h>
#include <stdlib.h>
int main() {
int r;
wchar_t myChar1 = L'?';
r = wprintf(L"char is %c\n", myChar1);
}
Run Code Online (Sandbox Code Playgroud) 我正在读这本书:C:在一个坚果壳中,在阅读了关于宽字符的字符集部分之后,我写了这个程序:
#include <stdio.h>
#include <stddef.h>
#include <wchar.h>
int main() {
wchar_t wc = '\x3b1';
wprintf(L"%lc\n", wc);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
然后我用gcc编译它,但是gcc给了我这个警告:
main.c:7:15:警告:十六进制转义序列超出范围[默认启用]
并且程序不输出字符α(其unicode为U + 03B1),这是我想要它做的.
如何更改程序以打印字符α?
我主要对类Unix系统(例如便携式POSIX)感兴趣,因为看起来Windows对于广泛的字符做了奇怪的事情.
读取和写入宽字符函数(例如getwchar()和putwchar())总是"做正确的事",例如从utf-8读取并在设置区域设置时写入utf-8,或者我是否必须手动调用wcrtomb()和打印使用例如字符串fputs()?在我的系统(openSUSE 12.3)中$LANG设置为en_GB.UTF-8它们似乎做了正确的事情(检查输出我看到看起来像UTF-8,即使字符串是使用wchar_t存储并使用宽字符函数编写的).
但我不确定这是否有保证.例如cprogramming.com声明:
[宽字符]不应该用于输出,因为虚假零字节和其他具有共同含义的低ASCII字符(例如'/'和'\n')可能会散布在整个数据中.
这似乎表明输出宽字符(大概使用宽字符输出功能)可能会造成严重破坏.
由于C标准似乎根本没有提及编码,因此在使用wchar_t时我真的不知道是谁/何时/如何应用编码.所以我的问题基本上是当我的应用程序不需要知道所使用的编码时,如果只读取,编写和使用宽字符是正确的事情.我只需要字符串长度和控制台宽度(wcswidth()),所以在处理文本时使用wchar_t到处都是理想的.
我无法弄清楚Valgrind Invalid read of size 8在使用时打印的原因wchar_t.我正在使用valgrind-3.7.0和gcc 4.7.2运行64位Ubuntu(3.5.0-25)系统.
#include <stdio.h>
#include <wchar.h>
#include <stdlib.h>
#include <string.h>
int main()
{
// const wchar_t *text = L"This is a t"; // no Valgrind error
// const wchar_t *text = L"This is a teeeeeeee"; // no Valgrind error
const wchar_t *text = L"This is a test"; // Valgrind ERRROR
wchar_t *new_text = NULL;
new_text = (wchar_t*) malloc( (wcslen(text) + 1) * sizeof(wchar_t));
wcsncpy(new_text, text, wcslen(text));
new_text[wcslen(text)] = L'\0';
printf("new_text: %ls\n", new_text); …Run Code Online (Sandbox Code Playgroud) 该功能towlower()似乎在Visual Studio 2012中不起作用.以下是一个示例:
#include <string>
#include <iostream>
#include <io.h>
#include <fcntl.h>
#include <wctype.h>
using namespace std;
int main()
{
_setmode(_fileno(stdout), _O_U8TEXT);
wcout << (wchar_t)towlower(L'?') << endl;
system("pause");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
角色仍然是大写字母.之前已经问过类似的问题,但我找不到任何解决方案.
我可以使用另一种方法来改变小写吗?
在C/C++中,如果一个多字节宽字符(wchar_t)值从big-endian系统传输到little-endian系统(反之亦然),它会在另一端出现相同的值吗?或者需要交换字节?
我正在进行一个项目,我有许多由连接(数字等)形成的常量字符串.
例如,我有一个LOCATION格式化的宏,__FILE__并且__LINE__在打印消息或错误时,我可以用它来知道我在代码中的位置:
#define _STR(x) # x
#define STR(x) _STR(x)
#define LOCATION __FILE__ "(" STR(__LINE__) ")"
Run Code Online (Sandbox Code Playgroud)
因此,这将格式化像"file.cpp(42)"的位置.问题是当我尝试将结果转换为宽字符串时:
#define _WIDEN(x) L ## x
#define WIDEN(x) _WIDEN(x)
#define WLOCATION WIDEN(LOCATION)
Run Code Online (Sandbox Code Playgroud)
这适用于GCC,并导致L"file.cpp(42)"插入到我的代码中.但是,当使用MSVC++(使用Visual C++ 2008 Express)尝试此操作时,我收到一个错误:
error: Concatenating wide "file.cpp" with narrow "("
Run Code Online (Sandbox Code Playgroud)
我知道L前缀只会添加到我的表达式的第一个术语中.我也试过这个:
#define _WIDEN(x) L ## #x
Run Code Online (Sandbox Code Playgroud)
哪个"有用",但是给出了L"\"file.cpp\" \"(\" \"42\" \")\""显然不太方便的字符串(而不是我想要的),特别是考虑到这个宏与其他宏相比很简单.
所以,我的问题是:如何才能将它应用于MSVC++中的整个表达式,这样我可以得到与GCC相同的结果?我宁愿不用全宽标记创建第二个字符串,因为我必须为每个标记维护两个宏,这不是很方便并且可能导致错误.另外,我也需要每个字符串的窄版本,所以不幸的是,使用全宽字符串也不是一种选择.
我想将 wstring 转换为 wchar_t*。我已经尝试了我所知道的一切,请帮忙。我想将 wstring 转换为 wchar_t*。