举报

stringstream求助

-1

还是早上的控制台问题。

我使用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;
}
ava
无名氏

2021-6-27

举报
0

如果你的问题是 stringstream 相关,那么就用 stringstream 写一个小的 demo 来体现你的问题?整个项目抛出来实在难以理解你的问题。

ava
慢羊羊

2021-6-27

技术讨论社区
相关提问