求助这个功能怎么实现呀!
我正在写一个图书管理系统(准确地说是: copy代码然后在屎山旁边拉一坨)然后我考虑到每次要录入或者修改数据, 可能人家点进来之后就反悔了或者想回去查看以下数据, 这个时候就不能强制人家输入, 而是如果人家直接输入Return就回去
它的原代码如下
voidLibraryManager::Add_book(book **q)//增加图书信息
{
char m;
std::cout << "请按照如下顺序输入图书信息! " << std::endl;
book *p;//定义book类指针
p = new book;//申请存储空尾间
std::cout << "本书登录号 本书书籍名称 本书作者姓名 本书分类号 本书出版单位 本书出版时间 本书书籍价格" << std::endl;
std::cin >> *p;
if (*q == NULL)//检查链表是否为空链表
{
p->next = NULL;
*q = p;
}//如果链表为空则把链表头指向p
else
{
p->next = NULL;//p是倒数第二个节点,next指针中保存这尾节点的地址值,p指向尾节点
(zbook)->next = p;//如果链表不为空则把链表尾指向p
}
zbook = p;
std::cout << "添加成功,是否继续添加:是Y,否N:" << std::endl;
std::cin.clear();
std::cin.ignore(1024, '\n');
std::cin >> m;
while ((m != 'Y'&& m != 'y' && m != 'N' && m != 'n') || std::cin.good() == FALSE)
{
std::cout << "输入错误,请重新输入:" << std::endl;
std::cin.clear();
std::cin.ignore(1024, '\n');
std::cin >> m;
}
if (m == 'Y' || m == 'y')
{
Add_book(&abook);
exit(EXIT_SUCCESS);
}
else if (m == 'N' || m == 'n')
{
std::cout << "正在返回到菜单,请勿操作" << std::endl;
Sleep(1500);//停滞1.5s再继续
system("cls");//清屏
Menu();
exit(EXIT_SUCCESS);
}
}
然后我改之后的如下
voidLibraryManager::Add_book(book **q)//增加图书信息
{
//以下代码加入了输入Return就返回的功能, 但是有bug(输入之后会直接跳到错误)
//我的想法是, 将用户输入的内容和"Return"对比, 如果一样就返回, 如果不一样就流给*p
//但是, 没办法直接将ifReturn的内容流给*p(也可能是我不会)
//然后我就想把第一个数据给赋值过去, 但是它会往后面串一个emm
/*
char m;
std::cout << "请按照如下顺序输入图书信息, 如要返回请输入\"Return!\" " << std::endl;
book *p;//定义book类指针
p = new book;//申请存储空尾间
std::cout << "本书登录号 本书书籍名称 本书作者姓名 本书分类号 本书出版单位 本书出版时间 本书书籍价格" << std::endl;
std::string ifReturn;
std::getline(std::cin, ifReturn);
if ((ifReturn.compare("Return")) == 0)
{
std::cout << "正在返回到菜单,请勿操作" << std::endl;
Sleep(1500);//停滞1.5s再继续
system("cls");//清屏
Menu();
exit(EXIT_SUCCESS);
}
else
{
std::stringstream ss(ifReturn);
std::cin.rdbuf(ss.rdbuf());
}
std::cin >> *p;
if (*q == NULL)//检查链表是否为空链表
{
p->next = NULL;
*q = p;
}//如果链表为空则把链表头指向p
else
{
p->next = NULL;//p是倒数第二个节点,next指针中保存这尾节点的地址值,p指向尾节点
(zbook)->next = p;//如果链表不为空则把链表尾指向p
}
zbook = p;
std::cout << "添加成功,是否继续添加:是Y,否N:" << std::endl;
std::cin.clear();
std::cin.ignore(1024, '\n');
std::cin >> m;
while ((m != 'Y'&& m != 'y' && m != 'N' && m != 'n') || std::cin.good() == FALSE)
{
std::cout << "输入错误,请重新输入:" << std::endl;
std::cin.clear();
std::cin.ignore(1024, '\n');
std::cin >> m;
}
if (m == 'Y' || m == 'y')
{
Add_book(&abook);
exit(EXIT_SUCCESS);
}
else if(m == 'N' || m == 'n')
{
std::cout << "正在返回到菜单,请勿操作" << std::endl;
Sleep(1500);//停滞1.5s再继续
system("cls");//清屏
Menu();
exit(EXIT_SUCCESS);
}
*/
}
运行的时候, 就会无限出现: 输入错误请重试!
另外,明明都已经用了cin.clear();还有cin.ignore(100, '\n');了,为啥缓冲区的错误还是存在呢? 在你的代码中,你尝试使用std::stringstream对象来接受用户输入,然后再将它的缓冲区设置为std::cin的缓冲区。虽然这样做确实可能在某些情况下起作用,但它可能并不适用于你的特定情况,因为这种方法可能会导致某些异常行为,如你所描述的。
另外,当你的代码中出现 "输入错误请重试!" 这样的提示时,你可以检查std::cin.good()的返回值。这是因为你使用了while循环来检查输入的合法性,但是std::cin.good()可能在遇到错误的输入时返回false 。这可能就是为什么你看到无限循环的原因。
关于你的问题,如果你想要实现的功能是如果用户输入 "Return",则程序返回,而不是继续,那么你可以在获取用户输入并转化为std::string后直接检查它是否等于 "Return",如果是则返回,否则继续程序。
我做了一些小修改,使用std::istringstream对象而不是修改std::cin的缓冲区,并假设book对象的输入运算符已经正确重载。
void LibraryManager::Add_book(book **q) {
char m;
std::cout << "请按照如下顺序输入图书信息, 如要返回请输入\"Return\"! " << std::endl;
book *p;
p = new book;
std::cout << "本书登录号 本书书籍名称 本书作者姓名 本书分类号 本书出版单位 本书出版时间 本书书籍价格" << std::endl;
std::string userInput;
std::getline(std::cin, userInput);
if (userInput == "Return") {
std::cout << "正在返回到菜单,请勿操作" << std::endl;
Sleep(1500);
system("cls");
Menu();
exit(EXIT_SUCCESS);
}
else {
std::istringstream iss(userInput);
iss >> *p;
if (*q == NULL) {
p->next = NULL;
*q = p;
}
else {
p->next = NULL;
(zbook)->next = p;
}
zbook = p;
std::cout << "添加成功,是否继续添加:是Y,否N:" << std::endl;
std::cin.clear();
std::cin.ignore(1024, '\n');
std::cin >> m;
while ((m != 'Y' && m != 'y' && m != 'N' && m != 'n') || !std::cin) {
std::cout << "输入错误,请重新输入:" << std::endl;
std::cin.clear();
std::cin.ignore(1024, '\n');
std::cin >> m;
}
if (m == 'Y' || m == 'y') {
Add_book(&abook);
exit(EXIT_SUCCESS);
}
else if (m == 'N' || m == 'n') {
std::cout << "正在返回到菜单,请勿操作" << std::endl;
Sleep(1500);
system("cls");
Menu();
exit(EXIT_SUCCESS);
}
}
}
注意: 你需要确保book对象的输入运算符已经正确重载,以支持从std::istringstream对象中读取数据。 本帖最后由 铭凡 于 2023-6-12 23:16 编辑
isdkz 发表于 2023-6-12 22:19
在你的代码中,你尝试使用std::stringstream对象来接受用户输入,然后再将它的缓冲区设置为std::cin...
还是不行
执行结果如下:
##########欢迎使用图书信息管理系统##########
#############输入1 增加图书信息#############
#############输入2 显示图书信息#############
#############输入3 删除图书信息#############
#############输入4 修改图书信息#############
#############输入5 查找图书信息#############
#############输入6 按照价格排序#############
#############输入7 保存&&退出###############
1
请按照如下顺序输入图书信息, 如要返回请输入"Return"!
本书登录号 本书书籍名称 本书作者姓名 本书分类号 本书出版单位 本书出版时间 本书书籍价格
添加成功,是否继续添加[是Y/否N]:
y
123 123 123 123 123 123 123
输入错误,请重新输入:
1 2 3 4 5 6 7
输入错误,请重新输入:
1 2 3 4 5 6 7
输入错误,请重新输入:
然后我调试程序的时候,
std::string userInput;
std::getline(std::cin, userInput);
这两行应该停下来等用户输入的, 但是它直接走下去了, 所以我觉得这是第一次我啥也没输入就显示“添加成功,是否继续添加[是Y/否N]:”这句话的原因
然后我输入Y继续,不管我输入什么,它都说我输入错误, 请重试 铭凡 发表于 2023-6-12 23:11
还是不行
执行结果如下:
看起来问题可能在于你的book类对输入流的处理方式。这可能是因为你的operator>>实现不适用于从空白字符(例如空格)分隔的字符串流中读取。
为了解决这个问题,你需要确保你的book类可以正确地从std::istringstream对象中读取。如果你的book类的输入运算符已经适当地重载,那么你应该可以像这样处理它:
std::istringstream iss(userInput);
iss >> p->login_number >> p->book_name >> p->author_name >> p->classification_number >> p->publisher >> p->publish_date >> p->book_price;
注意,上面的代码假设你的book类有如下的数据成员: login_number ,book_name ,author_name ,classification_number ,publisher ,publish_date ,book_price 。你需要根据你的book类的实际情况进行调整。
如果你的book类的operator>>重载是正确的,那么你应该可以直接使用iss >> *p 。如果不行,你就需要检查你的operator>>实现,确保它能正确处理从空格分隔的字符串流中读取。
另外,你的while循环条件可能也需要修改。在std::cin发生错误(例如输入不是 'Y', 'y', 'N', 'n' 的字符)时,你需要清空缓冲区并忽略剩余的输入,然后再尝试读取。你可以尝试如下的循环:
do {
std::cin >> m;
if (m != 'Y' && m != 'y' && m != 'N' && m != 'n') {
std::cout << "输入错误,请重新输入:" << std::endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
} while (m != 'Y' && m != 'y' && m != 'N' && m != 'n');
在这个循环中,如果输入的不是 'Y', 'y', 'N', 'n' 中的一个,那么会清空输入流并忽略剩余的输入,然后提示用户重新输入。当输入正确时,循环才会结束。 isdkz 发表于 2023-6-12 23:15
看起来问题可能在于你的book类对输入流的处理方式。这可能是因为你的operator>>实现不适用于从空 ...
你好,按照你的思路,我改了一下,代码如下
char m;
std::cout << "请按照如下顺序输入图书信息, 如要返回请输入\"Return\"! " << std::endl;
book *p;
p = new book;
std::cout << "本书登录号 本书书籍名称 本书作者姓名 本书分类号 本书出版单位 本书出版时间 本书书籍价格" << std::endl;
std::string userInput;
std::getline(std::cin, userInput);
if (userInput == "Return")
{
std::cout << "正在返回到菜单,请勿操作" << std::endl;
Sleep(1500);
system("cls");
Menu();
exit(EXIT_SUCCESS);
}
else
{
std::istringstream iss(userInput);
iss >> p->book_Entry_number >> p->book_name >> p->author_name >> p->book_number >> p->publish_address >> p->publish_time >> p->book_price;
if (*q == NULL)
{
p->next = NULL;
*q = p;
}
else
{
p->next = NULL;
(zbook)->next = p;
}
zbook = p;
std::cout << "添加成功,是否继续添加[是Y/否N]: " << std::endl;
std::cin.clear();
std::cin.ignore(1024, '\n');
do {
std::cin >> m;
if (m != 'Y' && m != 'y' && m != 'N' && m != 'n') {
std::cout << "输入错误,请重新输入:" << std::endl;
std::cin.clear();
//std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');//"std::numeric_limits<std::streamsize>::max()"说我max未定义
std::cin.ignore(1024, '\n');//我暂时还用这个
}
} while (m != 'Y' && m != 'y' && m != 'N' && m != 'n');
if (m == 'Y' || m == 'y')
{
Add_book(&abook);
exit(EXIT_SUCCESS);
}
else if (m == 'N' || m == 'n')
{
std::cout << "正在返回到菜单,请勿操作" << std::endl;
Sleep(1500);
system("cls");
Menu();
exit(EXIT_SUCCESS);
}
}
所以。。。现在就出现了新的问题:
1. 我现在根本没办法输入书籍信息, 因为
std::string userInput;
std::getline(std::cin, userInput);
这两行执行之后,人家就自动以为我已经输入了,就当作我已经成功录入一本书了
2. 我采用了这种方式
iss >> p->book_Entry_number >> p->book_name >> p->author_name >> p->book_number >> p->publish_address >> p->publish_time >> p->book_price;
因为C++我才学不久,本来就是打算借这个机会练练手emm
所以“如果你的book类的operator>>重载是正确的,那么你应该可以直接使用iss >> *p 。如果不行,你就需要检查你的operator>>实现,确保它能正确处理从空格分隔的字符串流中读取。”并不是很理解
3. 这行代码
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n')
说我max未定义,但是这个应该是一个类里边的方法吧,咋会这样呢 isdkz 发表于 2023-6-12 23:15
看起来问题可能在于你的book类对输入流的处理方式。这可能是因为你的operator>>实现不适用于从空 ...
大佬我录了一个调试程序的视频,麻烦抽空帮忙看下,感激不尽!
链接:https://pan.baidu.com/s/1G2aM5fh7iPas5QxRG10Zaw
提取码:mfzd
--来自百度网盘超级会员V3的分享 铭凡 发表于 2023-6-12 23:29
你好,按照你的思路,我改了一下,代码如下
非常抱歉给你带来了困扰。针对你提出的问题,我给出以下建议:
1. 我怀疑你的输入可能被某处的 '\n' (换行符)捕获了,因此当你试图使用std::getline(std::cin, userInput);时,它立即返回了空字符串。你可以试着在该句之前添加std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); ,看看是否有所帮助。
2. 我建议你试试直接使用iss >> *p; ,但是确保你的operator>>重载可以从空格分隔的字符串流中正确读取。在你的book类中应该有一个类似于以下的方法:
friend std::istream& operator>>(std::istream& in, book& b) {
in >> b.book_Entry_number >> b.book_name >> b.author_name >> b.book_number >> b.publish_address >> b.publish_time >> b.book_price;
return in;
}
这样就可以直接使用iss >> *p;了。如果你的book类中并没有这样的方法,或者该方法的实现不正确,那么你就需要使用你之前的方式,即iss >> p->book_Entry_number >> p->book_name >> p->author_name >> p->book_number >> b.publish_address >> b.publish_time >> b.book_price; 。
3. 对于std::numeric_limits<std::streamsize>::max()未定义的问题,你需要在文件顶部加入#include <limits> ,这样std::numeric_limits才可以使用。如果你的编译器仍然提示错误,你可以尝试使用std::cin.ignore(1024, '\n');作为替代。
希望这些建议能帮到你!如果还有问题,请随时向我提问。
页:
[1]