📌  相关文章
📜  如果代码不起作用怎么办?

📅  最后修改于: 2022-05-13 01:56:07.587000             🧑  作者: Mango

如果代码不起作用怎么办?

本文将讨论如果他们的代码在各种情况下都无法工作,可以采取的不同路线。

如果一个人似乎至少已经完美地编写了所有代码,在语句中包含的测试用例中测试了解决方案,但是在代码提交到系统后,它在测试中失败,并且没有明确的错误代码来帮助识别和解决问题.此问题可能由多种原因引起,但通常是以下原因之一:

  • 错误的答案
  • 超过时间/内存限制
  • 失败(运行时错误)

尽管方法可能因原因而异,但通常可以遵循以下步骤:

  • 检查边缘情况:例如,如果 N = 1 或 n 是满足约束的最大可能数。检查程序是否在给定所有可能意义上都达到约束的输入的情况下正确运行。
  • 生成一些通用测试用例:您知道正确答案。在用笔和纸弄清楚答案应该是什么之前,不要查看这些测试的代码答案。否则,很容易说服自己它是正确的,而看不到一些愚蠢的错误。
  • 时间限制超过了错误,测量程序对较大输入的工作时间。以下函数有助于测量自程序启动以来的 CPU 时间:
    • C++ (double)clock() / CLOCKS PER SEC,包括时间。
    • Python time.clock() 以秒为单位返回一个浮点值。
    • Java System.nanoTime() 以纳秒为单位返回长值。

测量小型测试、中型测试和大型测试的时间。可能会遇到以下可能结果之一:

  • 该程序及时适用于中小型测试,但比所需速度慢 10 倍以上(或在大型测试中挂起)。在这种情况下,程序可能存在复杂性问题,我们可以尝试使用以下选项找出问题:
    • 测量程序的各个部分分别花费的时间。例如,读取输入/打印输出需要多少时间)。
    • 计算您的算法及其部分执行的实际操作数,看看是否符合预期。
    • 检查是否已将引用传递给仅适用于 C++、 Java和Python的函数。它总是被引用)。
  • 该程序挂在小型或中型测试上。检查无限循环/递归。在循环和函数的前置条件和后置条件上添加断言(c++、 Python和Java中的断言),看看它们是否失败。使用调试输出/调试器查看导致挂起的代码路径。
  • 如果是运行时错误,则消息可能是未知信号,那么它可能是一个好兆头。这是信息最丰富的原因之一,这意味着程序可能由于以下因素之一而崩溃:
    • 在不属于程序的内存中访问了一个位置。在 C++ 中,它可以采用两种形式:尝试访问数组中不存在的元素,尝试评估空指针或指向不属于程序的位置的指针。
    • 犯算术错误:除以零、浮点数溢出等。
    • (特定于 C++)堆栈大小超出,这可能是由无限递归或在函数内部创建大对象(如数组)引起的。

生成不同的测试并针对它们运行您的程序,直到它崩溃:

  • “错误答案”的原因可能是最具挑战性的;很多事情都会导致它。要查找失败的测试,可以执行以下操作之一:
    • 找到一个在效率方面可能不正确的替代解决方案(某些情况下甚至不适用于某些类型的测试),但可用于检查主要解决方案的答案是否正确。
    • 如果有不一致的地方,使程序崩溃。这意味着为函数和循环的后置条件和前置条件添加断言。

如何生成测试:生成测试的最简单方法是编写一个将测试打印到文本文件的程序。下面是一个例子来说明相同的:

程序 1:生成最大成对不同的测试:

Python3
import sys
n = int(sys.argv[1])
print(n)
print(' '.join([str(i∗2)for i in range(n)])


Python3
import random
import sys
  
# Input the number N
n = int(sys.argv[1])
myseed = int(sys.argv[2])
random.seed(myseed)
  
print(n)
  
# 1000 could also be moved to
# parameters instead of making it
# a hard constant in the code
print(' '.join([str(random.randint(1, 1000)) for i in range(n)])


Python3
import random
import sys
import os
  
# Accept the number of tests as a
# command line parameter
  
tests = int(sys.argv[1])
  
# Accept the parameter for the
# tests as a command line parameter
  
n = int(sys.argv[2])
for i in range(tests):
    print("Test #" + str(i))
  
    # Run the generator gen.py with
    # parameter n and the seed i
os.system("python3 gen.py " + str(n) + " " + str(i) + " > input.txt")
  
# Run the model solution model.py
# Notice that it is not necessary
# that solution is implemented in
# python, you can as well run
# ./model < input.txt > model.txt
# for a C++ solution.
  
os.system("python3 model.py < input.txt > model.txt")
  
# Run the main solution
  
os.system("python3 main.py < input.txt > main.txt")
  
# Read the output of the
# model solution
  
with open('model.txt') as f:
    model = f.read()
print("Model: ", model)
  
# Read the output of the
# main solution :
  
with open('main.txt') as f:
    main = f.read()
print("Main: ", main)
if model != main:
    break


这里最神秘的可能是 sys.argv[1]。这是第一个命令行参数的 getter。现在,如何使用它来运行程序?将可执行文件或Python脚本复制到与生成脚本相同的目录并运行以下命令:

建议使用 Python3 而不是Python。在某些情况下,它可以帮助解决问题。因此,可以自动生成一些测试并针对它们运行程序,但以下问题仍未得到解答:

  • 如何随机化测试?
  • 如何生成很多?
  • 如何检查答案?

生成随机测试并在其上运行程序:可以使用以下由 3 个部分组成的技术:

  • 接受种子作为命令行参数的测试生成器,如程序 2 中所述。
  • 另一种解决方案。
  • 使用 (1) 中的生成器重复生成测试的脚本在生成的测试上运行主解决方案和模型解决方案,并检查程序 2 中的答案是否一致。

程序 2:从命令行接受种子的生成器:

Python3

import random
import sys
  
# Input the number N
n = int(sys.argv[1])
myseed = int(sys.argv[2])
random.seed(myseed)
  
print(n)
  
# 1000 could also be moved to
# parameters instead of making it
# a hard constant in the code
print(' '.join([str(random.randint(1, 1000)) for i in range(n)])

程序 3:实际脚本:

Python3

import random
import sys
import os
  
# Accept the number of tests as a
# command line parameter
  
tests = int(sys.argv[1])
  
# Accept the parameter for the
# tests as a command line parameter
  
n = int(sys.argv[2])
for i in range(tests):
    print("Test #" + str(i))
  
    # Run the generator gen.py with
    # parameter n and the seed i
os.system("python3 gen.py " + str(n) + " " + str(i) + " > input.txt")
  
# Run the model solution model.py
# Notice that it is not necessary
# that solution is implemented in
# python, you can as well run
# ./model < input.txt > model.txt
# for a C++ solution.
  
os.system("python3 model.py < input.txt > model.txt")
  
# Run the main solution
  
os.system("python3 main.py < input.txt > main.txt")
  
# Read the output of the
# model solution
  
with open('model.txt') as f:
    model = f.read()
print("Model: ", model)
  
# Read the output of the
# main solution :
  
with open('main.txt') as f:
    main = f.read()
print("Main: ", main)
if model != main:
    break

如何添加断言:在Java、 Python和 C++ 中断言表达式、断言表达式和断言(表达式);如果布尔表达式为假,则分别会产生运行时错误。断言的一种可能用法是验证程序的答案是否一致。另一个常见的用例是验证程序的中间步骤是否一致。