在c中使用宽字符时出现奇怪的空格
我试图画一个给定宽度和高度的正方形。 我试图在使用Unicode中的方框字符时这样做。 我正在使用以下代码:在c中使用宽字符时出现奇怪的空格,c,C,我试图画一个给定宽度和高度的正方形。 我试图在使用Unicode中的方框字符时这样做。 我正在使用以下代码: #include <stdlib.h> #include <stdio.h> #include <wchar.h> #include <locale.h> #include "string_prints.h" #define VERTICAL_PIPE L"║" #define HORIZONTAL_PIPE L"═" #define
#include <stdlib.h>
#include <stdio.h>
#include <wchar.h>
#include <locale.h>
#include "string_prints.h"
#define VERTICAL_PIPE L"║"
#define HORIZONTAL_PIPE L"═"
#define UP_RIGHT_CORNER L"╗"
#define UP_LEFT_CORNER L"╔"
#define DOWN_RIGHT_CORNER L"╝"
#define DOWN_LEFT_CORNER L"╚"
// Function to print the top line
void DrawUpLine(int w){
setlocale(LC_ALL, "");
wprintf(UP_LEFT_CORNER);
for (int i = 0; i < w; i++)
{
wprintf(HORIZONTAL_PIPE);
}
wprintf(UP_RIGHT_CORNER);
}
// Function to print the sides
void DrawSides(int w, int h){
setlocale(LC_ALL, "");
for (int i = 0; i < h; i++)
{
wprintf(VERTICAL_PIPE);
for (int j = 0; j < w; j++)
{
putchar(' ');
}
wprintf(VERTICAL_PIPE);
putchar('\n');
}
}
// Function to print the bottom line
void DrawDownLine(int w){
setlocale(LC_ALL, "");
wprintf(DOWN_LEFT_CORNER);
for (int i = 0; i < w; i++)
{
wprintf(HORIZONTAL_PIPE);
}
wprintf(DOWN_RIGHT_CORNER);
}
void DrawFrame(int w, int h){
DrawUpLine(w);
putchar('\n');
DrawSides(w, h);
putchar('\n');
DrawDownLine(w);
}
但是当我用一些int值运行这段代码时,我会得到一个输出,其中似乎有随机的空格和换行符,尽管管道看起来顺序正确
它是从main.c从标头调用的,如下所示:
#include <stdlib.h>
#include <stdio.h>
#include <wchar.h>
#include <locale.h>
#include "string_prints.h"
int main(){
DrawFrame(10, 20); // Calling the function
return 0;
}
正如您所见,我不理解setlocale的正确用法,您是否只需要执行一次?还是更多
任何帮助,请提前感谢
正如您所见,我不理解setlocale的正确用法,您是否只需要执行一次?还是更多
通过setlocale应用的区域设置更改在调用进程中是持久的。除非要进行多次更改,否则不需要多次调用该函数。但是您确实需要为它命名一个符合您预期目的的区域设置,或者如果您使用空字符串调用它,那么您或程序用户确实需要确保定义各种区域设置类别的环境变量设置为适合该目的的值
但是当我用一些int值运行这段代码时,我会得到一个输出
用看似随机的空格和换行符
这听起来像是字符编码不匹配的结果,甚至是两个字符编码不匹配的结果,但也请参见以下内容:
可能存在运行时不匹配,因为您告诉程序用于输出的区域设置与输出设备预期的区域设置不匹配,例如,显示程序输出的终端,以及
源文件的实际字符编码与编译器解释为具有的编码之间也可能存在编译时不匹配。
此外,尽管使用了宽字符串文字语法,但源代码中可能出现的字符(C的基本集除外)取决于实现。宽语法主要指定wchar\u t类型的文本元素的存储形式,而不是指定什么字符值有效或如何解释它们
还请注意,wchar_t的宽度取决于实现,它可以小到8位。wchar______________________________________________________。您可能会以两个单位的形式获得更宽字符的内部表示,例如UTF-16代理项对,但您也可能无法获得,这在很大程度上取决于单个实现
在这些事情中,编译器期望的编码是什么,在什么情况下,以及您可以如何影响这些都依赖于实现。例如,对于GCC,默认的源输入字符集是UTF-8,您可以通过其-finput字符集选项定义一个不同的输入字符集。如果愿意,还可以通过-fexec字符集和-fwide exec字符集选项指定标准字符集和宽执行字符集。GCC依赖iconv进行转换,既可以在编译时从源字符集转换为执行字符集,也可以在运行时从执行字符集转换为区域设置字符集。其他实现具有自己的语义,有其他选项或没有
那你该怎么办?首先,我建议通过使用仅使用基本字符集表示的UTF-8字符串文字,将源字符集从等式中去掉,这需要C2011:
#define VERTICAL_PIPE u8"\xe2\x95\x91"
#define HORIZONTAL_PIPE u8"\xe2\x95\x90"
#define UP_RIGHT_CORNER u8"\xe2\x95\x97"
#define UP_LEFT_CORNER u8"\xe2\x95\x94"
#define DOWN_RIGHT_CORNER u8"\xe2\x95\x9d"
#define DOWN_LEFT_CORNER u8"\xe2\x95\x9a"
请注意,生成的字符串是普通字符串,而不是宽字符串,因此不应将面向宽的输出函数用于它们。而是使用普通的printf、putchar等
这就给我们带来了代码的另一个问题:在没有采取明确措施切换freopen或fwide的情况下,不能将面向广域和面向字节的函数混合写入同一个流;请参阅标准的第1部分。在实践中,将两者混合在一起可能会产生混乱的结果
然后还要确保为实际环境正确设置了本地环境变量。它们已经存在的可能性很高,但值得一看。我得到的是a-回旋,而不是盒子,但它看起来几乎是正确的。@NeilEdelman我认为您应该尝试用:en_US.UTF-8填充setlocale的空引号。应该指定您想要的US UTF-8设置。这可能是因为您混合了宽字符输出wprintf和窄字符输出putchar。是否将putchar调用更改为putwcharL'\n';有什么区别吗?您应该只调用setlocale一次,这在main的开头是最明智的。然而,这主要是一种优化。用相同的参数多次调用它,最坏的代价应该是重新读取区域设置所花费的时间;充其量,代码会将请求的语言环境与当前本地语言环境进行比较,确定没有更改并返回。您是哪种编译器和操作系统 使用?对wprintf的支持各不相同,源代码编码也很重要,您可能会发现║ 例如,变为窄字符0xBA。源代码使用基本字符集,并使用unicode序列(如\u2551)更便于移植