【问题标题】:C++ Loop Error "Exited With Non-Zero Status" for Random Password Generator随机密码生成器的 C++ 循环错误“以非零状态退出”
【发布时间】:2017-04-25 07:13:04
【问题描述】:

所以我正在尝试学习 C++ 中的循环和条件,所以我决定编写一个程序,为用户生成一个随机密码。出于某种原因,代码可能工作了 1/5 次,但其余时间它只是给了我“以非零状态退出”。 谢谢, 埃文

#include <iostream>
#include <cstdlib>
#include <chrono>
#include <thread>
#include <time.h>
using namespace std;
int main() 
{
    using namespace std::this_thread;
    using namespace std::chrono;
//  Vars
    string lett;
    int input;
    string password("");
    string lettArray [] = {"a", "b", "c", "d", "e","f", "g", "h", "i", "j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"};

//  Prompt
    cout << "How long would you like your password to be?";
    cin >> input;
//  Loop
    for(int i = 0; i < input; i++)
    {
        struct timespec ts;
        clock_gettime(CLOCK_MONOTONIC, &ts);
        srand((time_t)ts.tv_nsec);
        int random = (rand() % 26 + 1);
        lett = lettArray[random];
        password = password + lett;
        sleep_for(milliseconds(10));
        cout << "." << endl;
        if (random == 0 )
            break;
    }
//  Output
    cout << password << endl;
    return 0;
}

【问题讨论】:

  • 不确定是问题所在,但将分配中的 +1 删除为随机。您需要 0 到 25 范围内的数字,而不是 1 到 26。
  • @MathieuVanNevel 我猜这是增加熵的尝​​试(在这里不太可能获得很多...)
  • 其实有几种情况你会重新调用srand。这不是其中之一
  • 链接页面上的示例代码调用了srand两次,所以不可以多次调用。
  • 一些弊端:没有测试函数调用是否失败。例如,clock_gettime 可能已经失败,导致无效的ts @WayneTanner 已经锁定了一个很容易引发崩溃的大但未定义的行为:没有lettArray[26]。建议在 GDB 下运行程序以查看崩溃的确切位置,然后检查崩溃现场周围的变量。

标签: c++ arrays loops compiler-errors conditional


【解决方案1】:

这个程序随机失败的原因(双关语)是你使用了 C 数组,而你的索引范围错误。

C 数组,例如 lettArray,不检查是否违反了数组边界。在您的示例中,如果您运行此程序,lettArray[26] 会给您一个分段错误,因为该内存地址中没有string 元素。 C 数组不检查边界,因此很难知道出了什么问题。这在复杂的程序中可能会变得特别棘手,因为如果该内存地址中发生了某些事情,您可能会得到一个荒谬的结果。

更好的实现是使用std::vector:

#include <iostream>
#include <cstdlib>
#include <chrono>
#include <thread>
#include <time.h>
#include <vector>
using namespace std;
int main() 
{
    // You don't need these two lines
    //using namespace std::this_thread;
    //using namespace std::chrono;

    //  Vars
    string lett;
    int input;
    string password("");

    // Vector index range: 0-25
    vector<string> lettArray = {"a", "b", "c", "d", "e","f", "g", "h", "i", "j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"};

    // You only need to initialise the seed once.
    struct timespec ts;
    clock_gettime(CLOCK_MONOTONIC, &ts);
    srand((time_t)ts.tv_nsec);

//  Prompt
    cout << "How long would you like your password to be?";
    cin >> input;

//  Loop
    for(int i = 0; i < input; i++)
    {
        int random = (rand() % 26 ); // You get results between 0-25
        // Using lettArray.at(26) will result in a crash with a clear 
        // message that bounds are violated  
        lett = lettArray.at(random); 
        password = password + lett;
        cout << "." << endl;

       // Don't see a reason for this if statement
       // if (random == 0 ){
       //     continue;
       //}
    }
//  Output
    cout << password << endl;
    return 0;
}

我还将随机种子移到循环之外(您只需要一次),也没有理由暂停 10 毫秒。无论如何,您都会看到您的结果是正确随机的。

【讨论】:

  • 非常感谢! :),我是 C++ 新手,并且是从 Java 过来的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-20
  • 1970-01-01
  • 2022-06-21
相关资源
最近更新 更多