【问题标题】:Saving randomly generated passwords to a text file in order to display them later将随机生成的密码保存到文本文件中,以便以后显示
【发布时间】:2017-06-15 09:38:24
【问题描述】:

我目前正在实习,我目前必须使用我正在开发的软件。昨天提出了最重要的请求,但我一直坚持其主要功能的失败:保存密码

该应用程序是使用 Visual Studio 2013 在 C++\CLR 中开发的(无法以某种方式安装 MFC 库,即使在多次重新启动后安装仍然失败并崩溃。)并旨在从用户提供的种子生成密码。生成的密码将保存到 .txt 文件中。如果种子已经被使用过,则会显示之前生成的密码。

很遗憾,我无法将密码和种子保存到文件中,尽管我可以编写种子如果我没有读到文档的末尾。我选择了“如果行为空,则将其写入文档”,但它不起作用,我不知道为什么。但是我可以毫无问题地读取密码。

这是源代码中有趣的部分:

int seed;
char genRandom() {
    static const char letters[] =
        "0123456789"
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "abcdefghijklmnopqrstuvwxyz";
    int stringLength = sizeof(letters) - 1;
    return letters[rand() % stringLength];
}
System::Void OK_Click(System::Object^  sender, System::EventArgs^  e) {
    fstream passwords;
    if (!(passwords.is_open())) {
        passwords.open("passwords.txt", ios::in | ios::out);
    }
    string gen = msclr::interop::marshal_as<std::string>(GENERATOR->Text), line, genf = gen;
    bool empty_line_found = false;
    while (empty_line_found == false) {
        getline(passwords, line);
        if (gen == line) {
            getline(passwords, line);
            PASSWORD->Text = msclr::interop::marshal_as<System::String^>(line);
            break;
        }
        if (line.empty()) {
            for (unsigned int i = 0; i < gen.length(); i++) {
                seed += gen[i];
            }
            srand(seed);
            string pass;
            for (int i = 0; i < 10; ++i) {
                pass += genRandom();
            }
            passwords << pass << endl << gen << "";
            PASSWORD->Text = msclr::interop::marshal_as<System::String^>(pass);
            empty_line_found = true;
        }
    }
}

我也尝试将ios::in 替换为ios::app,但它不起作用。是的,我已经包含了 fstream、iostream 等。

提前致谢!

[编辑] 刚刚解决了这个问题。感谢 Rook 让我走上了正确的道路。这感觉像是一种愚蠢的做法,但我已经关闭了文件并使用 ios::app 重新打开它以在其末尾写入。我还解决了一个愚蠢的错误,导致在种子之前写入密码并且没有插入最后一行,因此主循环仍然可以工作。如果有人遇到同样的问题,下面是代码:

int seed;
char genRandom() {
    static const char letters[] =
        "0123456789"
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "abcdefghijklmnopqrstuvwxyz";
    int stringLength = sizeof(letters) - 1;
    return letters[rand() % stringLength];
}
System::Void OK_Click(System::Object^  sender, System::EventArgs^  e) {
    fstream passwords;
    if (!(passwords.is_open())) {
        passwords.open("passwords.txt", ios::in | ios::out);
    }
    string gen = msclr::interop::marshal_as<std::string>(GENERATOR->Text), line, genf = gen;
    bool empty_line_found = false;
    while (empty_line_found == false) {
        getline(passwords, line);
        if (gen == line) {
            getline(passwords, line);
            PASSWORD->Text = msclr::interop::marshal_as<System::String^>(line);
            break;
        }
        if (line.empty()) {
            passwords.close();
            passwords.open("passwords.txt", ios::app);
            for (unsigned int i = 0; i < gen.length(); i++) {
                seed += gen[i];
            }
            srand(seed);
            string pass;
            for (int i = 0; i < 10; ++i) {
                pass += genRandom();
            }
            passwords << gen << endl << pass << endl << "";
            PASSWORD->Text = msclr::interop::marshal_as<System::String^>(pass);
            empty_line_found = true;
        }
    }
    passwords.close();
}

【问题讨论】:

  • 用 C++-CLI 编写应用程序是一个非常糟糕的想法。它仅用于粘合代码,因此您可以在托管应用程序中使用 C++ 内容。用 C#(或其他 CLR 语言)编写其余的托管代码,您的开发将更快、更简单,您的生活也会更轻松。
  • (或者如果你喜欢 C++,写一个漂亮的简单命令行应用程序,避免弄乱庞大的 UI 库和语言扩展)
  • “_如果我没有到达文档的末尾,我可以写种子_”意味着您正在遇到 EOF,并且没有清除文件流的状态标志,所以它将拒绝接受任何更多的输入。我也会避免对您仍在读取的文件进行格式化写入,但这只是我。
  • 嗯,问题是我对 C# 一无所知,我必须创建一个不是控制台应用程序的应用程序。我正在处理的另一个项目(也在 CLI 中)运行良好。
  • @PointR:如果你成功地制作了一个带有 GUI 的 C++/CLI 应用程序,那么你对 C# 的了解比你想象的要多。

标签: c++-cli clr


【解决方案1】:

所以,这里有一件有趣的事情:

passwords << pass << endl << gen << "";

您不会以换行符结束它。这意味着您的文件的最后 可能 也缺少换行符。当您在最后一行执行此操作时,这会产生有趣的效果:

getline(passwords, line);

getline 将一直读取,直到看到一行结尾或 EOF。如果没有换行符,它将命中那个 EOF,然后在流上设置 EOF 位。这意味着下次您尝试这样做时:

passwords << pass << endl << gen << "";

流将拒绝写入任何内容,因为它处于 eof 状态。您可以在此处执行各种操作,但最简单的方法是执行 passwords.clear() 以删除任何错误标志,例如 eof。不过,对于意外清除真正的错误标志,我会非常谨慎;仔细阅读fstream 的文档。

我还重申我对 C++/CLR 是一种胶水语言的评论,而不是通用开发的好语言,最好使用 C++ 或 .net 语言(如 C#)来完成。如果您出于某种原因绝对喜欢 C++/CLR,那么您不妨使用广泛的 .net 库,这样您就不必来回无意义地使用托管类型。例如,请参阅System::IO::FileStream

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-24
    • 1970-01-01
    • 2020-11-18
    • 2019-05-07
    • 2012-09-01
    • 1970-01-01
    • 2012-10-17
    • 1970-01-01
    相关资源
    最近更新 更多