代码在 Visual c++ 中无法按预期工作(来自 bjarne stroustrup 编程和原则书 2n 版的示例)
Posted
技术标签:
【中文标题】代码在 Visual c++ 中无法按预期工作(来自 bjarne stroustrup 编程和原则书 2n 版的示例)【英文标题】:Code doesn't work as intended in visual c++ (examples from bjarne stroustrup programming and principles book 2n version) 【发布时间】:2017-05-21 08:02:11 【问题描述】:好吧,因为我最近开始阅读有关 C++ 的内容,并尝试阅读我正在阅读的《编程原理和练习使用 C++ 第二版》这本书。
我是一个完全的新手,所以这可能就是原因,但就是这样。
好吧,所以在书中他们让你实现了一个头 .h 文件而不是 (iostream) 等。所以它只是一开始就包含所有这些,因为这本书不希望我们在一开始就专注于那些库的学习。 所以我实现了它并使用了它(不确定这是否与问题有关)。无论如何,在第 77 页,我被卡住了。
基本上这是一个错误的值,它应该只显示 -1(或 0),因为 int 得到一个错误值,等等 Carlos(字母,不是整数)所以 int 没有得到正确的值因此根据本书,应该可以工作的代码(并显示 0 或 -1,因为它是输入的错误值)是这样的:
#include "std_lib_facilities.h"
using namespace std;
int main()
cout << "Please enter your first name and age\n";
string first_name = "???"; // string variable // ("???” means “don’t know the name”)
int age = –1; // integer variable (–1 means “don’t know the age”)
cin >> first_name >> age; // read a string followed by an integer
cout << "Hello, " << first_name << " (age " << age << ")\n";
这就是我写的:
#include "std_lib_facilities.h"
using namespace std;
int main()
cout << "Please enter your first name and age" << endl;
string First_Name = "???";
int Age = -1;
cin >> First_Name >> Age;
cout << "Hello, " << First_Name << "(age" << Age << ")" << endl;
keep_window_open();
return 0;
但是,当我写 22 Carlos 时,Visual C++ 的结果是崩溃。 根据这本书它应该输出 Hello, 22 (age -1)
但对我来说,它只是在我输入 Carlos 作为年龄值后崩溃... 当我运行和编译它时,我没有收到错误或任何东西,但是当我为年龄提供错误值后它崩溃了。
我做错了什么? 补充:我知道我可以使用一个字符串来让它工作,但是我只是对它为什么不起作用感兴趣,因为我正在关注这本书我希望在没有这些问题的情况下遵循它工作。
这是我做的时候的 gif: http://imgur.com/a/ERjhz 解决方案:使用 system("pause");而不是 keep_window_open(); 然而,在知道书中的代码并不总是有效的情况下阅读这本书仍然很烦人:(
【问题讨论】:
您使用的是什么版本的 Visual Studio,它在 MSVC2015 中按预期工作。 您可以尝试包含#include <iostream>
和#include <string>
来代替您添加的包含吗?只是看看它是否可以这样工作。
这本书明显过时了。按照目前的标准,正确的输出是0,而不是-1。但是程序不应该崩溃。你确定程序可以编译吗?它包含在 C++ 程序中不合法的非标准减号。当使用 MS Word 或其他文字处理器进入程序时,它们会出现 ifteb。不要那样做。使用程序员的文本编辑器。
我正在使用 Visual Studio 社区 2017 版来编写我的代码。顺便说一下,我尝试包含 iostream 和字符串,但它也不起作用(是的,我删除了 keep_window_open();因为它引用了我之前使用的那个)
抱歉,第一个样本包含无效字符,第二个没有。
【参考方案1】:
这不是问题,但太快了,我们的眼睛无法注意到。
我正在添加keep_window_open()的函数定义
inline void keep_window_open()
cin.clear();
cout << "Please enter a character to exit\n";
char ch;
cin >> ch;
return;
如您所见,它只需要我们输入的字符 转发您将了解输入流及其缓冲区 因此,当您输入一个字符代替整数时,流(背景)中会标记错误,并且只使用输入的一个字符(在您的情况下,“C”用于标记)。
我将输入用作 Carlos 22
所以现在输入流仍然有字符 'a','r','l','o','s',22 所以现在 'a' 被用作 keep_window_open 函数的输入 程序结束,无需等待您的输入 所以没有错误或崩溃,但由于字符已经存在用于 keep_window_open 函数的输入,所以它的速度非常快
【讨论】:
对于错误标记的函数 cin.clear 清除所有引发的错误标记并将流恢复正常【参考方案2】:问题出在keep_window_open
。这是一个棘手的功能,很难完全正确。您可以将其替换为避开问题但仅适用于 Windows 的代码:
inline void keep_window_open()
system("pause");
或者用这个稍微复杂一点的代码来尝试考虑更多的情况:
inline void keep_window_open()
cout << "Please enter a character to exit\n";
if (!cin)
cin.clear();
cin.ignore(120, '\n');
char ch;
cin >> skipws >> ch;
(假设您输入的行不超过 120 个字符。如果您希望它不受任意限制,请将 120 替换为 numeric_limits<streamsize>::max()
。在这种情况下,std_lib_facilities.h 中的其他函数确实使用 120。你很多或可能不必在您的程序中添加#include <limits>
指令)。
我已经在几个案例中进行了测试,它似乎可以在正确和不正确的程序输入下工作,但使用它需要您自担风险。如果您的程序需要更复杂的输入,它仍然可能正常工作,也可能无法正常工作。
【讨论】:
【参考方案3】:一个好的规则是始终除非最终用户是白痴,因此您需要以一种可以处理各种输入而不会崩溃的方式编写程序。因此,始终将输入数字读取为std::string
,然后尝试将其转换为int
、short
、double
、unsigned int
或您使用的任何数据类型。
您的代码应如下所示:
#include <cstdlib>
#include <exception>
#include <iostream>
#include <stdexcept>
#include <string>
int main(int argc, char **argv)
int age;
std::string first_name;
std::string input_age;
std::cout << "Please enter your first name and age: " << std::endl;
std::cin >> first_name >> input_age; // Read the age as 'std::string'
try
age = std::stoi(input_age); // Try to convert age from 'std::string' to 'int'
std::cout << "Hello, " << first_name << " (" << age << ")" << std::endl;
catch(std::invalid_argument& ex) // 'std::stoi()' will throw 'std::invalid_argument' if it's not able to convert 'std::string' to 'int'
std::cerr << "Unable to convert input value ('" << input_age << "') to 'int'" << std::endl;
std::cerr << "Debug info: " << ex.what() << std::endl;
catch(std::out_of_range& ex) // 'std::stoi()' will throw 'std::out_of_range' if 'std::string' is too small or too big to store in a 'int'
std::cerr << "The input value (" << input_age << ") is out of range, please input a value inside the range" << std::endl;
std::cerr << "Debug info: " << ex.what() << std::endl;
return EXIT_SUCCESS;
【讨论】:
问题不在于编写正确的代码。问题是为什么 Stroustrup 书中的代码不像宣传的那样表现得那么好。修改该代码并不能帮助您回答问题。 感谢您的回复,但作为@n.m,作为一个编程新手,您提供的所有代码对我来说有点高:) stoi、cerr、argc 等...学习:)【参考方案4】:所以与代码无关,与输入有关。
例如,当我写 22 卡洛斯时。
问题是代码要求First_Name
然后Age
,而不是Age
然后First_Name
。因此,当您将 22 作为 First_Name 时,.exe 会变得混乱。
例如,假设我这样做了
int y = 0;
cout << "Give me INT: ";
cin >> y;
cout >> "You put: " >> y;
当我运行程序并将其输入时
Give me INT: ghaisewofasd
*crashed*
这是一个问题,因为用户在代码请求 int 时给出了一个字符串。
因此,对于您的情况,不要写 22 Carlos,而只需写 Carlos 22。 还要记住,这本书可能不太正确,因为它不应该打印出 Hello, (22)。如果发生这种情况,现在会出现类似崩溃的情况,可能是旧版本的 C++。
【讨论】:
不是这个。他的程序在应该执行Hello, 22 (age -1)
时崩溃。刚刚在 Unix 中尝试过,它确实有他所说的输出。
否,如果您尝试从包含非 int 字符的流中提取 int
,则 value 保持不变并设置了 failbit。没有崩溃
OP 想要输入错误的数据。程序不应崩溃。
哦,我刚刚在 Visual C++ 中测试了我的代码,它没有崩溃。该死的,我很喜欢“在堆栈溢出时有一些问题可以得到 15 分”,看来我错了。虽然我有时会因为这些问题而崩溃
是的,除了我没有使用你的标题,我得到了 -1以上是关于代码在 Visual c++ 中无法按预期工作(来自 bjarne stroustrup 编程和原则书 2n 版的示例)的主要内容,如果未能解决你的问题,请参考以下文章
远程进程的 Visual Studio 2012 调试未按预期工作
正则表达式无法与 C++ regex_match 一起按预期工作