一个简单的问题:我正在用C ++编写一个聊天室程序(但它主要是C风格),我正在尝试打印“#help - 显示一个命令列表...”到输出窗口。虽然我可以使用两个连字符( - )来实现大致相同的效果,但我宁愿使用em-dash( - )。但是,printf()
似乎不支持打印em-dashes。相反,控制台只是在其位置打印出字符ù,尽管直接在提示符中输入em-dashes工作正常。
如何显示这个简单的Unicode字符?
查看Windows alt键代码,我觉得有趣的是alt + 0151是“ - ”而alt + 151是“ù”。这与我的问题有关,还是简单的巧合?
答案 0 :(得分:0)
windows是unicode(UTF-16)系统。控制台unicode也是如此。如果你想要打印unicode文本 - 你需要(这是最有效的)使用WriteConsoleW
BOOL PrintString(PCWSTR psz)
{
DWORD n;
return WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), psz, (ULONG)wcslen(psz), &n, 0);
}
PrintString(L"—");
在这种情况下,在你的二进制文件中将是宽字符—
(2字节0x2014
)并且控制台按原样打印它。
如果为输出控制台调用ansi(多字节)函数 - 如WriteConsoleA
或WriteFile
- 控制台首先通过MultiByteToWideChar
将多字节字符串转换为unicode并将其放置到 {CodePage 将使用GetConsoleOutputCP
返回的值。如果你使用字符>这里(翻译)可能会有问题0x80的
首先编译器会给你警告:该文件包含一个无法在当前代码页(数字)中表示的字符。以Unicode格式保存文件以防止数据丢失。(C4819)。但即使以Unicode格式保存源文件,也可以是下一步:
wprintf(L"ù"); // no warning
printf("ù"); //warning C4566
因为L"ù"
在二进制文件中保存为宽字符串(按原样) - 这里一切正常,没有任何问题和警告。但"ù"
保存为字符串(单字节字符串)。编译器需要将源文件中的宽字符串“ù”转换为二进制文件中的多字节字符串( .obj 文件,链接器创建 > pe 比)。和#em> CP_ACP (当前系统默认的Windows ANSI代码页。)
WideCharToMultiByte
如果你说拨打printf("ù");
会怎么样?
WideCharToMultiByte(CP_ACP, )
这将是编译时。结果多字节字符串将保存在二进制文件MultiByteToWideChar(GetConsoleOutputCP(), ..)
和unicode -> CP_ACP -> multi-byte -> GetConsoleOutputCP() -> unicode
打印此字符串所以你获得了2次转换:GetConsoleOutputCP() == CP_OEMCP != CP_ACP
默认情况下CP_OEMCP
,即使您在编译它的计算机上运行程序也是如此。 (在另一台计算机上使用另一台CP_ACP
特别是)
不兼容转换中的问题 - 使用了不同的代码页。但即使您将控制台代码页更改为wprintf
- 转换,无论如何都可能会错误地转换某些字符。
和关于 CRT api wprintf
- 下面是这种情况:
WriteFile
首先使用内部当前locale将给定字符串从unicode转换为多字节(并注意 crt 区域设置独立且与控制台不同区域设置)。然后使用多字节字符串调用unicode -> current_crt_locale -> multi-byte -> GetConsoleOutputCP() -> unicode
。 console将这个多字节字符串转换回unicode
wprintf
为了使用GetConsoleOutputCP()
,我们需要先将当前的crt语言环境设置为char sz[16];
sprintf(sz, ".%u", GetConsoleOutputCP());
setlocale(LC_ALL, sz);
wprintf(L"—");
-
但无论如何,我在屏幕上—
上查看(在我的比赛中)-—
。PrintString(L"—");
。如果在此之后调用WriteConsoleW
(使用 public void tryPost() {
RequestQueue queue = Volley.newRequestQueue(this);
String serverUrl = "http://10.0.2.2:3000/tasks";
StringRequest stringRequest = new StringRequest(Request.Method.POST, serverUrl,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.d("TAG", "response = "+ response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.d("TAG", "Error = "+ error);
}
})
{
//
@Override
public Map<String, String> getHeaders() {
HashMap<String, String> headers = new HashMap<>();
headers.put("Accept", "application/json");
headers.put("Content-Type", "application/json");
return headers;
}
////
@Override
public Map<String, String> getParams() {
Map<String, String> params = new HashMap<>();
params.put("userId","sargent");
params.put("password","1234567");
return params; //return the parameters
}
};
// Add the request to the RequestQueue.
queue.add(stringRequest);
}
),那么10.1
也是如此。
所以只有可靠的方式打印任何unicode字符(由windows支持) - 使用WriteConsole W api。
答案 1 :(得分:0)
在完成评论后,我发现eryksun的解决方案是最简单的(......也是最容易理解的):
{
"manifest_version": 2,
"name": "chrome extension",
"description": "This extension will used to simplify the project",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": [
"http://example.com/*",
"activeTab"
]
}
便携性不是我的担忧,这解决了我最初的问题 - 不再ù-我心爱的em-dash正在展出。
我承认这个问题基本上是the one linked by sata300.de的副本。虽然#include <stdio.h>
#include <io.h>
#include <fcntl.h>
int main()
{
//other stuff
_setmode(_fileno(stdout), _O_U16TEXT);
wprintf(L"#help — display a list of commands...");
代替printf
,但有相关信息的地方也有不必要的谣言。