#遇到问题的现象描述
给字符串变量name输入“中国科学技术大学”,name的值只会变成“中科技大”,隔一个吞一个,在程序中有三处会出现该情况,都是在中文输入时。
该问题和字符串编码以及宽字符没有关系,这些都试过了,不要用这些方法来回我。
请在我的代码基础上更改完后,确认能正确运行,达到程序目的,并且没有删掉我代码的任何功能后再回复我。
代码注释基本给全,如果有不确定代码用途的地方请私信。
如果出现报错请联系我,该代码在我的电脑上运行没有报错,出现报错可能是因为头文件有问题或缺少头文件。
这段代码这么长是因为任何一段单独拿出来都没有问题,我无法确定问题到底在哪,只能全发。
#问题相关代码片
#include "pch.h"
#include <Windows.h>
#include <mmsystem.h>
#include <resource.h>
#include <filesystem>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <sstream>
#include <locale>
#include <codecvt>
#include <map>
#include <thread>
#include <limits>
#include <chrono>
#include <conio.h>
#include <condition_variable>
using namespace std;
bool fileExists(const string& filePath) {
ifstream file(filePath);
return file.good(); // 检查文件是否成功打开
}
int main()
{
map<string, int> myMap;
myMap["测试用户"] = 1;
string back, word, input,name;
auto it=myMap.find(name);
auto startTime = chrono::steady_clock::now();
auto currentTime = chrono::steady_clock::now();
auto elapsedTime = chrono::duration_cast<chrono::seconds>(currentTime - startTime);
char buf[1000] = { "0" };
stringstream stream;
int had = 0 ,year = 0, cishu = 0, wenjian=0, successIndex, num = 100;
string hd,str,password,passwords,EmailContents, folderPath = "C:\\memories";
string filePath1 = "C:\\memories\\state1.ich", filePath2 = "C:\\memories\\state2.ich",filePath3 = "C:\\memories\\state3.ich",
filePath4 = "C:\\memories\\state4.ich";//这里的文件1是全局状态文件,文件2是密码输入次数记录文件,文件3记录登陆成功的人的序号并直接跳转到对应区域,文件4是控制台风格设置
DWORD folderAttributes = GetFileAttributesA(folderPath.c_str());
if (folderAttributes != INVALID_FILE_ATTRIBUTES && (folderAttributes & FILE_ATTRIBUTE_DIRECTORY))//检测文件目录是否存在
{
if (fileExists(filePath4)) {//检查控制台风格设置文件是否存在
ifstream file14(filePath4, ios::in);
if (file14.is_open()) {
while (file14 >> buf)
{
stream << buf;
str = stream.str();
stream.str("");//清理stream防止后续文件读写出现问题
file14.close(); // 关闭文件
system(("color "+str).c_str());//设置控制台风格
cout << "如果你希望更改背景颜色和文字颜色,请在4秒内输入任意字符,否则请等待4秒:";
startTime = chrono::steady_clock::now();
while (year == 0) {
// 检查是否超时
currentTime = chrono::steady_clock::now();
elapsedTime = chrono::duration_cast<chrono::seconds>(currentTime - startTime);
if (elapsedTime >= chrono::seconds(4)) {
system("cls");
cout << endl;
break;
}
// 检查是否有用户输入
if (_kbhit()) {
cin >> input;
system("cls");
cout << endl;
system("color 07");
goto font;//前往控制台风格设置
}
// 等待一小段时间
this_thread::sleep_for(chrono::milliseconds(100));
}
}
}
else {
cout << "文件打开失败,请使用管理员权限重新打开本程序试试。" << endl;
return 0;
}
}
else {
font://控制台风格设置
cout << "首先来设置你喜欢的颜色。" << endl;
cout << "1.黑色 2.深蓝色 3.天蓝色 4.红色 5.紫色 6.灰色 7.蓝紫色" << endl;
cout << "请输入对应编号以选择你喜欢的背景颜色:";
while (had == 0) {
year = 0;
cin.clear();
setbuf(stdin, NULL);//清理cin缓冲区防止cin错误导致死循环
cin >> num;
if (!cin) {
cout << "你的输入有问题,请重新选择:";
}
else {
switch (num) {
case 1:
back = "0";
break;
case 2:
back = "1";
break;
case 3:
back = "3";
break;
case 4:
back = "4";
break;
case 5:
back = "5";
break;
case 6:
back = "8";
break;
case 7:
back = "9";
break;
default:
cout << "你的输入有问题,请重新选择:";
back = "-1";
break;
}
if (back == "-1") {
continue;
}
system(("color " + back + "7").c_str());//设置控制台风格
cout << "你是否对改变结果满意?满意请输入“Y”或“y”:";
while (year == 0) {
cin >> input;
if (input == "Y" or input == "y") {
had = -1;
year = -1;
}
else {
cout << "请重新选择你喜欢的背景颜色:";
system("color 07");//改回默认设置
year = -1;
}
}
}
}
had = 0;
year = 0;
system("cls");//清屏函数
cout << "接着来设置你喜欢的文字颜色。注意,如果你不喜欢设置后的颜色,请等待四秒,程序将自动恢复原设置" << endl;
cout << "1.黑色 2.深蓝色 3.绿色 4.天蓝色 5.红色 6.紫色" << endl;
cout << "7.黄色 8.白色 9.灰色 10.淡蓝色 11.淡绿色 12.淡青色" << endl;
cout << "13.淡红色 14.淡紫色 15.淡黄色 16.亮白色" << endl;
cout << "请输入对应编号以选择你喜欢的文字颜色:";
while (had == 0) {
year = 0;
cin.clear();
setbuf(stdin, NULL);
cin >> num;
if (!cin) {
cout << "你的输入有问题,请重新选择:";
}
else {
switch (num) {
case 1:
word = "0";
break;
case 2:
word = "1";
break;
case 3:
word = "2";
break;
case 4:
word = "3";
break;
case 5:
word = "4";
break;
case 6:
word = "5";
break;
case 7:
word = "6";
break;
case 8:
word = "7";
break;
case 9:
word = "8";
break;
case 10:
word = "9";
break;
case 11:
word = "A";
break;
case 12:
word = "B";
break;
case 13:
word = "C";
break;
case 14:
word = "D";
break;
case 15:
word = "E";
break;
case 16:
word = "F";
break;
default:
cout << "你的输入有问题,请重新选择:";
back = "-1";
break;
}
if (back == "-1") {
continue;
}
system(("color " + back + word).c_str());
cout << "你是否对改变结果满意?满意请输入“Y”:";
startTime = chrono::steady_clock::now();//记录时间倒计时,倒计时结束后自动改回原设置
while (year == 0) {
// 检查是否超时
currentTime = chrono::steady_clock::now();
elapsedTime = chrono::duration_cast<chrono::seconds>(currentTime - startTime);
if (elapsedTime >= chrono::seconds(4)) {
cout << "\033[2K\r";
system(("color " + back + "7").c_str());
cin.clear();
setbuf(stdin, NULL);
cout << "请重新选择你喜欢的文字颜色:";
year = -1;
}
// 检查是否有用户输入
if (_kbhit()) {
cin >> input;
if (input == "Y" or input == "y") {
had = -1;
year = -1;
}
else {
cout << "请重新选择你喜欢的文字颜色:";
system(("color " + back + "7").c_str());
year = -1;
}
}
// 等待一小段时间
this_thread::sleep_for(chrono::milliseconds(100));
}
}
}
ofstream file17(filePath4); // 创建风格文件并记录风格设置
if (file17.is_open()) {
system("cls");
cout << endl;
file17 << back+word; // 写入数据到文件中
file17.close(); // 关闭文件
//删除此处注释可验证后文第一处吞字现象的解决,但是我不知道为什么能解决
//cout << "请重新启动程序以应用这些样式设置。注意,如果需要改变样式请在程序打开时输入任意字符。" << endl;
//return 0;
}
else {
cout << "创建文件失败,请使用管理员权限重新打开本程序试试。" << endl;
return 0;
}
}
system("cls");
if (fileExists(filePath1)) {//检测是否存在全局状态文件
ifstream file1(filePath1, ios::in);
if (file1.is_open()) {
while (file1 >> buf)
{
stream << buf;
str = stream.str();
stream.str("");
file1.close(); // 关闭文件
if (str == "a") {
ofstream file32(filePath1, ios::out);
if (file32.is_open()) {
file32 << "d"; // d为程序运行未正常退出代号,程序正常退出自动改为a
file32.close(); // 关闭文件
break;
}
else {
cout << "创建或打开文件失败,请使用管理员权限重新打开本程序试试。" << endl;
return 0;
}
break;
}
else if (str == "b") {
ifstream file2(filePath3, ios::in);
if (file2.is_open()) {
while (file2 >> buf) {
file2.close(); // 关闭文件
try {
successIndex = stoi(buf); // 将字符串转换为整型
if (successIndex > 0) {
if (successIndex < 2) {
goto begin;//如果识别成功就直接跳转到开始处,这里的0-2范围根据map函数内的人数变化而变化
}
}
cout << "请不要随意篡改程序文件信息。" << endl;//如果无法匹配则重新录入信息
ofstream file31(filePath1, ios::out);
if (file31.is_open()) {
file31 << "d"; // d为程序运行未正常退出代号,程序正常退出自动改为a
file31.close(); // 关闭文件
Sleep(2000);
break;
}
else {
cout << "创建或打开文件失败,请使用管理员权限重新打开本程序试试。" << endl;
return 0;
}
}
catch (const invalid_argument& e) {
cout << "程序数据损坏,请重新输入你的身份信息。" << endl;
ofstream file3(filePath1, ios::out);
if (file3.is_open()) {
file3 << "d"; // d为程序运行未正常退出代号,程序正常退出自动改为a
file3.close(); // 关闭文件
Sleep(2000);
break;
}
else {
cout << "创建或打开文件失败,请使用管理员权限重新打开本程序试试。" << endl;
return 0;
}
}
}
}
else {
cout << "文件打开失败,请使用管理员权限重新打开本程序试试。" << endl;
return 0;
}
}
else if (str == "c") {
ifstream file4(filePath3, ios::in);
if (file4.is_open()) {
while (file4 >> buf) {
file4.close(); // 关闭文件
try {
successIndex = stoi(buf); // 将字符串转换为整型
had = 1;
cout << "怎么,还念念不忘了不成?" << endl;
Sleep(2000);
wenjian = 1;
goto begin;
}
catch (const invalid_argument& e) {
cout << "程序数据损坏,请重新输入你的身份信息。" << endl;
ofstream file5(filePath1, ios::out);
if (file5.is_open()) {
file5 << "d"; // 写入数据到文件中
file5.close(); // 关闭文件
Sleep(2000);
break;
}
else {
cout << "创建或打开文件失败,请使用管理员权限重新打开本程序试试。" << endl;
return 0;
}
}
}
}
break;
}
else if (str == "d") {
cout << "检测到您上次使用本程序时直接关闭了本程序,请按照程序运行正常关闭,否则将导致数据丢失!" << endl;
Sleep(3000);
break;
}
else {
cout << "请不要篡改程序文件数据,否则程序将无法正常运行!!!" << endl;
ofstream file6(filePath1, ios::out);
if (file6.is_open()) {
file6 << "d"; // 写入数据到文件中
file6.close(); // 关闭文件
break;
}
else {
cout << "打开文件失败,请使用管理员权限重新打开本程序试试。" << endl;
return 0;
}
}
}
}
else {
cout << "文件打开失败,请使用管理员权限重新打开本程序试试。" << endl;
return 0;
}
}
else {
ofstream file7(filePath1); // 使用绝对路径创建输出文件流对象
if (file7.is_open()) {
file7 << "d"; // 写入数据到文件中
file7.close(); // 关闭文件
}
else {
cout << "创建文件失败,请使用管理员权限重新打开本程序试试。" << endl;
return 0;
}
}
}
else
{
// 创建文件夹
if (CreateDirectoryA(folderPath.c_str(), NULL))
{
ofstream file8(filePath1); // 使用绝对路径创建输出文件流对象
if (file8.is_open()) {
file8 << "a"; // 写入数据到文件中
file8.close(); // 关闭文件
}
else {
cout << "创建文件失败,请使用管理员权限重新打开本程序试试。" << endl;
return 0;
}
goto font;
}
else
{
cout << "创建文件夹失败,请使用管理员权限重新打开本程序试试。"<< endl;
return 0;
}
}
cout << "让我们先从设置身份开始吧,请问你是:";//程序正文开始
while (true) {//循环输入直到输入正确用户名
cin >> name;
it = myMap.find(name);
if (it != myMap.end()) {
successIndex = it->second;
break;
}
cout << name << "好像并不在班上,请重新输入你的真实身份吧(请不要输入首字母缩写):";
/*
这里出现了吞字现象,但是仅限于文件“C:\memories\state4.ich”不存在时
当用户设置完控制台风格并创建该文件后,该处吞字现象消失,但是后面还有两处吞字现象
不信可以把标签
*/
}
switch (successIndex) {//判断并设置各自用户的密码
case 1:
passwords = "测试用户密码";
break;
}
cout << "请输入我们之间约定的暗号(如果不记得了或者没有设置,请联系我获取授权码):";
while (true) {
cin >> password;
if (password == passwords) {//判断密码是否正确
ofstream file9(filePath3, ios::out);
if (file9.is_open()) {
file9 << to_string(successIndex); // 写入用户数据到文件中
file9.close(); // 关闭文件
}
else {
cout << "创建或打开文件失败,请使用管理员权限重新打开本程序试试。" << endl;
return 0;
}
ofstream file0(filePath1, ios::out);
if (file0.is_open()) {
file0 << "b"; // 写入状态数据到文件中
file0.close(); // 关闭文件
wenjian = 1;
}
else {
cout << "创建或打开文件失败,请使用管理员权限重新打开本程序试试。" << endl;
return 0;
}
break;
}
else {//如果输入密码错误则开始记录次数,超过6次则禁止输入
if (fileExists(filePath2)) {
ifstream file(filePath2, ios::in);
if (file.is_open()) {
while (file >> buf) {
stream << buf;
str = stream.str();
stream.str("");
file.close(); // 关闭文件
if (str == "0") {
cout << "你尝试输入太多次错误暗号了,请联系我获取你的授权码再使用本程序吧!" << endl;
return 0;
}
else if (str == "5") {
ofstream file11(filePath2); // 使用绝对路径创建输出文件流对象
if (file11.is_open()) {
file11 << "4"; // 写入数据到文件中
file11.close(); // 关闭文件
cishu = 5;
break;
}
else {
cout << "写入文件失败,请使用管理员权限重新打开本程序试试。" << endl;
return 0;
}
}
else if (str == "4") {
ofstream file22(filePath2); // 使用绝对路径创建输出文件流对象
if (file22.is_open()) {
file22 << "3"; // 写入数据到文件中
file22.close(); // 关闭文件
cishu = 4;
break;
}
else {
cout << "写入文件失败,请使用管理员权限重新打开本程序试试。" << endl;
return 0;
}
}
else if (str == "3") {
ofstream file33(filePath2); // 使用绝对路径创建输出文件流对象
if (file33.is_open()) {
file33 << "2"; // 写入数据到文件中
file33.close(); // 关闭文件
cishu = 3;
break;
}
else {
cout << "写入文件失败,请使用管理员权限重新打开本程序试试。" << endl;
return 0;
}
}
else if (str == "2") {
ofstream file44(filePath2); // 使用绝对路径创建输出文件流对象
if (file44.is_open()) {
file44 << "1"; // 写入数据到文件中
file44.close(); // 关闭文件
cishu = 2;
break;
}
else {
cout << "写入文件失败,请使用管理员权限重新打开本程序试试。" << endl;
return 0;
}
}
else if (str == "1") {
ofstream file55(filePath2); // 使用绝对路径创建输出文件流对象
if (file55.is_open()) {
file55 << "0"; // 写入数据到文件中
file55.close(); // 关闭文件
cishu = 1;
break;
}
else {
cout << "写入文件失败,请使用管理员权限重新打开本程序试试。" << endl;
return 0;
}
}
else {
cout << "请不要篡改文件数据,谢谢!" << endl;
ofstream file66(filePath2); // 使用绝对路径创建输出文件流对象
if (file66.is_open()) {
file66 << "0"; // 写入数据到文件中
file66.close(); // 关闭文件
}
else {
cout << "写入文件失败,请使用管理员权限重新打开本程序试试。" << endl;
}
return 0;
}
}
}
else {
cout << "文件打开失败,请使用管理员权限重新打开本程序试试。" << endl;
return 0;
}
}
else {
ofstream file77(filePath2); // 使用绝对路径创建输出文件流对象
if (file77.is_open()) {
file77 << "5"; // 写入数据到文件中
file77.close(); // 关闭文件
cishu = 6;
}
else {
cout << "创建文件失败,请使用管理员权限重新打开本程序试试。" << endl;
return 0;
}
}
cin.ignore();
cout << "密码错误,还剩" << cishu << "次机会,请检查并输入正确的暗号:";
}
}
begin:
system("cls");
switch (successIndex) {//填写每个人对应的送别话语
case 1:
break;
}
if (had == 1) {//如果已经经历过一次活动则直接结束
return 0;
}
else {
cout << "接下来是各种活动" << endl;
Sleep(1000);
system("cls");
laoshi:
cout << "活动一:我想对老师说(匿名)" << endl;
cout << "1.黄老师 2.凌老师 3.谭老师 4.赵老师 5.余老师" << endl;
cout << "6.谢老师 7.陶老师 8.邓老师 9.全体老师们" << endl;
cout << "请从以上老师中选择一位你最喜欢的老师,送TA你心里最想说的话:" << endl;
while (true) {
cin.clear();
setbuf(stdin, NULL);
cin >> num;
if (!cin) {
cout << "你的输入有问题,请重新选择:";
}
else {
switch (num) {
case 1:
hd = "黄老师";
break;
case 2:
hd = "凌老师";
break;
case 3:
hd = "谭老师";
break;
case 4:
hd = "赵老师";
break;
case 5:
hd = "余老师";
break;
case 6:
hd = "谢老师";
break;
case 7:
hd = "陶老师";
break;
case 8:
hd = "邓老师";
break;
case 9:
hd = "全体老师们";
break;
default:
cout << "你的输入有问题,请重新输入:";
continue;
}
break;
}
}
system("cls");
cout << endl;
cout << "请输入你对" << hd << "想说的话(注意,不支持换行,请说完后再按回车键):";
cin >> input;
cout << input << endl;
cout << "如果你还想再选择一位老师赠言请输入“是”,否则请输入其他字符:";
cin >> input;
if (input == "是") {
goto laoshi;
}
system("cls");
hd = "活动二:心动的瞬间(匿名)";
for (char i : hd) {
cout << i;
Sleep(50);
}
cout << endl;
hd = "活动规则:你觉得班上谁最让你心动呢?请输入TA的名字(这个活动是为了统计出班花和班草,没有别的意思,你要跳过就输入我的名字叭,嘿嘿):";
for (char i : hd) {
cout << i;
Sleep(50);
}
while (true) {
cin >> input;
cout << input << endl;
/*
这里是为了检查输入,结果又发现吞字现象
并且原因不明。
*/
cout << "请确认你的输入:";
cin >> hd;
if (input == "没有") {
break;
}
else {
it = myMap.find(input);
if (it != myMap.end()) {
}
else {
cout << input << "好像并不在班上,请重新选择你最心动的人吧(没有就说“没有”):";
}
}
}
system("cls");
cout << "活动三:最后的告别" << endl;
cout << "同学六年,你有没有什么想要对我说的呢?请在这里写下来吧(也可以让我帮忙匿名转达你想对别人说的话哦)(注意,这里还是不能换行):" << endl;
cin >> input;
cout << input << endl;
/*
这里是为了检查输入,结果又发现吞字现象
并且原因不明。
*/
cout << "请确认你的输入:";
cin >> input;
//ofstream file88(filePath1); // 所有活动进行完后再执行
//if (file88.is_open()) {
// file88 << "c"; // 写入数据到文件中
// file88.close(); // 关闭文件
// wenjian = 1;
//}
//else {
// cout << "创建或打开文件失败,请使用管理员权限重新打开本程序试试。" << endl;
// return 0;
//}
}
if (wenjian != 1) {//如果存在特殊状态则不用修改全局状态
ofstream file881(filePath1);
if (file881.is_open()) {
file881 << "a"; // 写入正常退出数据到文件中
file881.close(); // 关闭文件
}
else {
cout << "创建或打开文件失败,请使用管理员权限重新打开本程序试试。" << endl;
}
}
system("pause");
return 0;
}
#运行结果
给字符串变量name输入“中国科学技术大学”,name的值只会变成“中科技大”,在程序中有三处会出现该情况,都是在中文输入时。
#我的初步解答思路是
这里有一个奇怪的现象,在用户设置完控制台颜色(也就是state4.ich文件不存在时)如果继续执行后续操作会导致第一处问题处出现吞字符现象,但是当该文件存在时在第一处问题处不会出现吞字符现象(但是后面两处还是会吞字符)
#操作环境、软件版本等相关信息
Windows11,Visual Studio 2022 Preview,C++控制台项目
setbuf(stdin, NULL)这个函数的问题。具体参考下面图片。
等会哦! , 你要是采纳了, 记得告诉我一下 , 我读一会代码 ......
你的思路方向是对的,这里再给你补充几个小点
1、编码问题,如果编码方式不同,可能会导致字符被错误地解释或处理。可以尝试将编码方式设置为UTF-8,这是处理中文字符的一种常用编码方式。
2、控制台输入缓冲区问题,控制台输入缓冲区可能存在一些残留字符,这些字符可能会导致后续输入被干扰。可以尝试在每次输入之前清空控制台输入缓冲区,以确保不会有残留字符影响后续输入。在每次输入之前,使用Windows API函数清空控制台输入缓冲区。例如,可以使用FlushConsoleInputBuffer函数来清空输入缓冲区。
3、输入处理逻辑问题,在处理输入时,可能存在一些逻辑错误导致字符被吞。可以检查输入处理逻辑,确保没有出现错误。检查文件内容是否正确,并确保文件路径和文件名正确。在程序中添加一些调试输出语句,输出变量的值或程序的执行流程,以便更好地了解程序的状态和行为。
4、也就是你思路中提到的控制台颜色文件问题:如果state4.ich文件不存在,可能会导致控制台在中文输入时出现问题。可以尝试修复state4.ich文件,确保其能够正确处理中文输入。