C++ 如何在wchar\t数组中添加换行符?

C++ 如何在wchar\t数组中添加换行符?,c++,winapi,console,windows-console,C++,Winapi,Console,Windows Console,我正在做一个控制台游戏。更新地图后,它使用屏幕缓冲区刷新控制台窗口 这是主while循环 while(true){ //player.doStuff(_kbhit()); //map.update(); WriteConsoleOutputCharacter( console.getScreenBuffer(), (LPWSTR)map.getScreen(), map.getWidth()*map.getHeight(), {0,0},console.getBytesWrited() ); 睡

我正在做一个控制台游戏。更新地图后,它使用屏幕缓冲区刷新控制台窗口

这是主
while
循环

while(true){
//player.doStuff(_kbhit());
//map.update();
WriteConsoleOutputCharacter(
console.getScreenBuffer(),
(LPWSTR)map.getScreen(),
map.getWidth()*map.getHeight(),
{0,0},console.getBytesWrited()
);
睡眠(1000/30);
}
在此循环之前,我将从
.txt
文件获取地图的布局:

类映射{
int宽度、高度;
wchar_t*屏幕;
公众:
wchar_t*getScreen(){
返回屏幕;
}
无效设置屏幕(std::string layoutFile,std::string levelDataFile){
std::ifstream levelData(levelDataFile);
水平数据>>宽度>>高度;
屏幕=新wchar_t[(宽度+1)*高度];
levelData.close();
std::wifstream布局(layoutFile);
std::wstring线;
对于(int j=0;j
问题是打印的地图显示为一个字符串,没有任何换行符,如下所示:

00000\u00000
当我期望它看起来像这样时:

0000
0__0 
0000
我尝试在每一行写入后添加
L'\n'
L'\r\n'
,但没有效果。

简而言之 这里有两个独立的问题:

  • 第一个是换行符被覆盖
  • 第二个问题,在纠正第一个问题后,是windows控制台API不处理换行符
更多细节 覆盖的问题 我假设宽度不包括每行末尾的尾随换行符,因为屏幕分配为:

new wchar_t[(width + 1) * height];   // real width is width + 1 for '\n'
现在看看您的逻辑,您添加到行中的最后一个
'\n'
,设置为:

screen[ width * (j + 1) ]   // same as screen[ j * width + width ]
根据索引方案,这似乎很好,因为您将布局字符复制到:

screen[ j * width + i ]`   // where `i` is between `0` and `width-1` 
因此换行符将位于
屏幕[j*width+width]

不幸的是,在索引公式中,下一行的第一个字符覆盖了相同的位置:将
j
替换为
j+1
,将
i
替换为
0
给出:

screen[ (j + 1) * width + 0 ]  
那是

screen[ (j + 1) * width ]    // same location as screen [ width * (j+1)]
在每行上有尾随换行符的解决方案 考虑到行的实际宽度为
width+1
,请更正索引方案

因此,索引公式变为:

    for(int i = 0; i < width; i++) {
        screen[j * (width+1) + i] = line.at(i);
    }
控制台API的问题 对换行符和控制字符不提供真正的支持。这些都显示为问号

文档中提到了根据控制台模式处理这些控制字符的可能性,但我在Windows 10中尝试过,甚至在变量
writeconsoleooutputCharactera()
(确保排除宽字符的问题)中也尝试过,它根本不起作用

您有两种解决方案来实现这一点,但这两种解决方案需要一些返工:

  • 逐行显示输出,并相应地控制光标位置
  • 使用可以指定目标矩形(高度和宽度)并在矩形中写入字符,而无需换行。不幸的是,数组应该是CHAR_INFO,而不是简单的字符
第二种方法的示例:

std::string w = "SATORAREPOTENETOPERAROTAS";
SMALL_RECT sr{ 2, 2, 6, 6 };
CHAR_INFO t[25];
for (int i = 0; i < 25; i++) { t[i].Char.AsciiChar = w[i]; t[i].Attributes = BACKGROUND_GREEN; }
WriteConsoleOutputA(
    hOut,
    t,
    { 5,5 },
    { 0,0 },
    &sr
);
std::string w=“SATORAREOPTENIEOPEROTAS”;
小直sr{2,2,6,6};
字符信息t[25];
对于(inti=0;i<25;i++){t[i].Char.AsciiChar=w[i];t[i].Attributes=BACKGROUND_GREEN;}
WriteConsoleOutputA(
然而,
T
{ 5,5 },
{ 0,0 },
&sr
);

一行的长度为
宽度+1
,包括换行符。由于这个原因,指数(
j*width+i
width*(j+1)
)的公式是错误的。还要注意用空字符结束字符串,而不是换行。@fabian但问题是getline只返回一个不带\n的字符串,在这种情况下,行的长度是
width
而不是
width+1
。因此,我尝试使map 1符号比一条线宽,并手动添加换行符,这似乎不起作用,但输出仍然不正确:
0000?0?00
。由于某种原因,程序无法读取\n,它写
,而不是linebreak@kastrycznik现在还不清楚你是怎么做到这一点的。如何读取输出文件以及如何显示它?因为原则上,即使使用简单的“\n”(请参阅联机演示:)也应该可以使用。当然,如果您写入windows控制台缓冲区,则不应添加新行,而应在缓冲区中的正确位置写入。im逐行读取输出文件,然后将其写入WSString而不是wchar__t(如您所说),然后使用以下命令显示此字符串:
WriteConsoleOutputCharacter(console.getScreenBuffer(),(LPWSTR)map.getScreen().c_str(),map.getWidth()*map.getHeight(),{0,0},console.getBytesWrite())
map.getScreen()返回std::wstring screen。我还必须在我的wstring上使用c_str()方法,因为
WriteConsoleOutputCharacter
只接受LPWSTRi也尝试使用
std::wcout
std::string w = "SATORAREPOTENETOPERAROTAS";
SMALL_RECT sr{ 2, 2, 6, 6 };
CHAR_INFO t[25];
for (int i = 0; i < 25; i++) { t[i].Char.AsciiChar = w[i]; t[i].Attributes = BACKGROUND_GREEN; }
WriteConsoleOutputA(
    hOut,
    t,
    { 5,5 },
    { 0,0 },
    &sr
);