还是早上的控制台问题。
我使用std::stringstream存储输入的数据并将其转换为支持的格式。
但是我发现,假如在一行以空格符输入多个数据(类比iostream),stringstream检测不到
我想知道怎样才能判断stringstream里还有非空字符,eof()貌似不能满足我的需求
我使用了多种办法,结果导致现在的处理很是复杂,甚至可能有其他的bug
下面是代码,原来的代码分为多个文件,我将其合并后码风很丑,还请见谅
请定位到代码中的input函数,谢谢。
#pragma warning(disable:4996)
#include<easyx.h>
#include<windows.h>
#include<string>
#include<memory>
#include<queue>
#include<sstream>
using namespace std;
HWND m_hWnd; //EasyX的窗口句柄
WNDPROC m_originWndProc; //原始窗口回调函数
std::queue<wchar_t> m_str; //键盘输入的缓冲区
CRITICAL_SECTION m_cs_str; //缓冲区的线程锁
CRITICAL_SECTION cs_data;
LRESULT CALLBACK m_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
bool hasInput();
wchar_t readInput();
void Flush();
//颜色
class Color
{
public:
Color() = default;
Color(int r, int g, int b)
:r(r), g(g), b(b)
{
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="color">另一个颜色类</param>
Color(const Color& color)
:r(color.r), g(color.g), b(color.b)
{}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="color">传统C颜色</param>
Color(COLORREF color)
:Color(GetRValue(color), GetGValue(color), GetBValue(color))
{
}
/// <summary>
/// 导出为传统C颜色
/// </summary>
/// <returns>导出结果</returns>
COLORREF asCOLORREF()const
{
return RGB(r, g, b);
}
int r;//r分量
int g;//g分量
int b;//b分量
};
//前景色
class ForeColor :public Color
{
public:
ForeColor() = default;
ForeColor(int r, int g, int b)
:Color(r, g, b)
{}
ForeColor(COLORREF color)
:Color(color)
{}
ForeColor(const Color& color)
:Color(color)
{}
};
//背景色
class BackColor :public Color
{
public:
BackColor() = default;
BackColor(int r, int g, int b)
:Color(r, g, b)
{}
BackColor(COLORREF color)
:Color(color)
{}
BackColor(const Color& color)
:Color(color)
{}
};
class Word
{
public:
Word(wchar_t data = 0, ForeColor fore_color = Color(255, 255, 255), BackColor back_color = Color(0, 0, 0), bool wide = false)
:data(data), fore_color(fore_color), back_color(back_color), wide(wide)
{}
wchar_t data; //文字内容
ForeColor fore_color; //前景色
BackColor back_color; //背景色
bool wide; //是否为宽字符
};
int Width;
int Height;
Word** Data;
wstringstream Wss;
struct
{
LOGFONT e; //英文字体
LOGFONT c; //中文字体
}font;
struct _pt
{
~_pt() = default;
int x;
int y;
ForeColor fcolor;
BackColor bcolor;
}pt;
void init(int _width, int _height, const LOGFONT& efont, const LOGFONT& cfont)
{
Width = _width, Height = _height, pt = { 0,0,Color(255,255,255),Color(0,0,0) };
font = { efont,cfont };
Data = new Word * [Height];
for (int i = 0; i < Height; i++)Data[i] = new Word[Width];
}
void ScrollNext()
{
if (++pt.y == Width)
{
pt.y = 0;
if (++pt.x == Height)
{
pt.x = 0;
}
}
}
void ScrollNextLine()
{
pt.y = 0;
if (++pt.x == Height)
{
pt.x = 0;
}
}
void putchar(wchar_t wc, bool wide = false)
{
Data[pt.x][pt.y] = Word(wc, pt.fcolor, pt.bcolor, wide);
ScrollNext();
}
void print() {}
void _print(const wchar_t* const str)
{
EnterCriticalSection(&cs_data);
for (int i = 0; i < lstrlenW(str); i++)
{
if (iswcntrl(str[i]))
{
switch (str[i])
{
case L'\n':
ScrollNextLine();
break;
case L'\b':
if (--pt.y < 0)
{
pt.y = Width - 1;
if (--pt.x < 0)pt.x = Height - 1;
}
default:
break;
}
}
else
{
//判断全/半角
if (HIBYTE(WORD(str[i])))
{
if (pt.y == Width - 1)
{
putchar(L' ');
}
putchar(str[i], true);
putchar(L' ');
}
else
{
putchar(str[i]);
}
}
}
LeaveCriticalSection(&cs_data);
}
void _print(const ForeColor& fcolor)
{
pt.fcolor = fcolor;
}
void _print(const BackColor& bcolor)
{
pt.bcolor = bcolor;
}
void draw()
{
EnterCriticalSection(&cs_data);
settextstyle(&font.e);
int width = textwidth(L' ');
int height = textheight(L' ');
bool last_is_wide = false;
settextstyle(&font.e);
for (int i = 0; i < Height; i++)
{
for (int j = 0; j < Width; j++)
{
if (last_is_wide)
{
last_is_wide = false;
settextstyle(&font.e);
continue;
}
if (Data[i][j].wide)
{
last_is_wide = true;
settextstyle(&font.c);
}
setfillcolor(Data[i][j].back_color.asCOLORREF());
solidrectangle(j * (width + 1), i * (height + 1), (j + 1 + last_is_wide) * (width + 1), (i + 1) * (height + 1));
settextcolor(Data[i][j].fore_color.asCOLORREF());
setbkmode(TRANSPARENT);
outtextxy(j * (width + 1), i * (height + 1), Data[i][j].data);
}
}
LeaveCriticalSection(&cs_data);
}
template<typename T, typename... Args>
void print(T&& t, Args... args)
{
_print(t);
print(args...);
}
template<typename T>
bool input(T& t)
{
Flush();
Wss.clear(ios::goodbit);
T t1;
Wss >> t1;
if (!Wss.good())
{
Wss.clear();
std::vector<wchar_t> buffer;
bool flag = true;
wchar_t tmp[2] = { 0,0 };
while (flag)
{
wchar_t ch = readInput();
if (iswcntrl(ch))
{
switch (ch)
{
case L'\n':
case L'\r':
flag = false;
print(L"\n");
break;
case L'\b':
if (!buffer.empty())
{
buffer.pop_back();
print(L"\b \b");
}
break;
}
}
else
{
buffer.push_back(ch);
tmp[0] = ch;
print(tmp);
}
Flush();
}
wstring wstr;
for (auto i : buffer)wstr += i;
Wss.write(wstr.data(), wstr.size());
Wss >> t;
bool result = Wss.good();
return result;
}
else
{
t = t1;
return true;
}
}
LRESULT CALLBACK m_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CLOSE:
DeleteCriticalSection(&m_cs_str);
exit(0);
break;
case WM_CHAR:
EnterCriticalSection(&m_cs_str);
m_str.push(wchar_t(wParam));
LeaveCriticalSection(&m_cs_str);
break;
case WM_USER + 1:
draw();
FlushBatchDraw();
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
bool hasInput()
{
return !m_str.empty();
}
wchar_t readInput()
{
while (m_str.empty())Sleep(0);
EnterCriticalSection(&m_cs_str);
wchar_t result = m_str.front();
m_str.pop();
LeaveCriticalSection(&m_cs_str);
return result;
}
void InitGraph(int width, int height)
{
InitializeCriticalSection(&m_cs_str);
InitializeCriticalSection(&cs_data);
m_hWnd = ::initgraph(width, height);
//-4:GWL_WNDPROC和GWLP_WNDPROC,懒得区分系统位数
m_originWndProc = (WNDPROC)GetWindowLong(m_hWnd, -4);
SetWindowLong(m_hWnd, -4, LONG(m_WndProc));
}
void Flush()
{
SendMessage(m_hWnd, WM_USER + 1, 0, 0);
}
INT WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, INT)
{
InitGraph(640, 480);
LOGFONT efont, cfont;
ZeroMemory((char*)&efont, sizeof efont);
efont.lfHeight = 20;
wcscpy_s(efont.lfFaceName, L"Cascadia Code");
cfont = efont;
wcscpy_s(cfont.lfFaceName, L"等线");
init(80, 25, efont, cfont);
print(L"English 中文\n");
while (1)
{
wstring wstr;
input(wstr);
print(wstr.data(), L"\n");
Flush();
}
while (1);
return 0;
}