我有一个基本上进行二进制搜索的while循环。它是在一个巨大的文件中搜索日期并表现出一些奇怪的行为。它每次都打印出错误的索引,经过10分钟的调试后我输入了一个cout声明"发生了什么"在循环的最开始
while(left < right){
cout<<"what is going on"<<endl;
bunch of other stuff
}
当我跑步时,它突然起作用了。我取消评论它再次破裂。所以它好像没有cout就没有循环执行。我从来没有遇到过这样的事情,有没有人知道可能造成这种情况的原因?我在xcode上。
此文件有大约200万行,但似乎没有速度问题,当我取消注释该行时,它找到相当快的正确日期
答案 0 :(得分:0)
这是对您目前提出的问题的唯一合理回答。只有在添加cout
表达式并呈现代码时,可以缩小代码的哪些部分的行为范围,才能获得更有针对性的答案。在添加cout
表达式时缩小程序的哪些部分会改变其行为的过程是 调试 程序的良好开端。
调试是一种取证活动,因为您试图推断程序不按预期行为的方式运行的原因。它结合了逻辑推理和创造性思维。擅长它是软件工程师的雇主非常需要的技能。解释如何调试的所有方面超出了本答案的范围,但由于您对cout
表达式如何影响程序行为感到特别困惑,因此您应该进行调查以消除您的困惑。
您必须了解:添加cout
表达式不应该能够更改二进制搜索的工作方式。事实上它几乎按照定义表明你的程序正在调用未定义的行为。您应该将它作为您的任务,以发现您的程序的哪个部分正在通过添加cout
表达式来改变其行为。由于您在询问可能导致此行为的原因,因此必须假设您没有完全了解如何为自己发现此信息。以下是提示。
设计评审是对该计划如何实现其目的的重要分析。有时,设计审查会揭示一个逻辑缺陷,导致纠正实施中的缺陷。有时,设计评审将指出实施可能遗漏的可能的弱点或极端情况,并且可以帮助阐明在调试代码本身时聚焦焦点的位置。理解设计将有助于形成一个心理图像(或模型),说明如果一切正确实现,软件应该如何工作。
编译软件时,启用所有可用警告,并将任何报告的警告视为错误。了解每个警告,以及在源代码中解决它的最佳方法。这可以帮助消除许多模糊不清的问题,否则这些问题将被忽视,并且它的好处超过了有时可能导致的错误报告(实际上没有错误的代码警告)。较少经验的程序员尤其会发现很难从真正的错误中辨别真实的错误报告,因此最好只是努力正确处理所有警告。
代码审查是对软件的批评,以确保每行代码都能达到预期目的。目的不明确的代码行自动被怀疑为问题的可能来源。代码审查还可以揭示清晰但明显不符合预期目的的代码行。
您可以在计算中的关键点使用assert()
语句扩充软件,您希望条件成立。例如,您可能期望索引变量在特定范围内。您可以设计一个验证该期望的断言语句。如果遇到断言失败,则表示至少有一个假设无效。大概(并且你应该验证)你的所有断言都会成功地使用cout
表达式。您希望记下在删除cout
表达式时失败的任何断言。
通过使用较小的输入文件(例如,10-20行),其中预期的输出已知,您可以验证您的程序是否正在执行其预期的功能。如果您可以使用cout
作品重现&#34; ,则无法使用&#34;使用较小的输入集的行为,更容易观察程序可能出现的问题,因为要分析的数据更侧重于问题本身。
如果您有可重现的错误测试用例,则可以使用调试器逐步执行程序。您应该准确理解将执行哪些代码行,应该采用哪些代码路径,以及变量的预期值应该是什么。调试器可以帮助您在执行一行代码时观察所有这些信息。
在软件的某个地方,程序的某些逻辑表达不同的行为,具体取决于cout
表达式是否到位。使用上面的工具尝试隔离具有此属性的代码行,并尝试在第一次发生行为差异时进行识别。然后,查看代码所依赖的变量,以决定如何表现。根据程序模型,以及您对代码应如何工作的理解,您必须推断出导致变量以cout
表达式的存在方式表达自己的不同之处。
如果您使用小型测试用例将问题缩减为几行代码,并且您仍然不理解行为不符合您对这些代码行的预期,那么您可以尝试编写将问题减少的问题解释为问题,并且可能会在这里得到很好的接受。