通过getline函数从终端获取用户输入并将其写入文件时出现Qt逻辑错误

Qt logical error during getting user's input from terminal via getline function and writing it into a file

使用控制台,我想通过 wFile 中的 getline 函数将所需用户的输入写入文件 函数,然后读取它。我在运行时遇到逻辑错误;无论我作为用户写什么,都不会输入输出终端,也不会成功执行更多步骤。显然,库中存在具有此功能的 fwrite 函数,但我想以这种方式编写自己的代码。我想我一定是忽略了一点。这是代码:

#include <QCoreApplication>
#include <QDebug>
#include <QFile>
#include <QString>
#include <QTextStream>
#include <String>
#include <cstdlib>
using namespace std;

void wFile(QString Filename)
{
QFile  mFile(Filename);
QTextStream str(&mFile);
qDebug() << "what do you want to write in the desired file: ";
istream& getline (istream& is, string& str);
if (!mFile.open(QFile::WriteOnly  | QFile::Text))
{
    qDebug() << "could not open the file";
    return;
}
mFile.flush();
mFile.close();
}

void read (QString Filename){
QFile nFile(Filename);

if(!nFile.open(QFile::ReadOnly | QFile::Text))
 {
     qDebug() << "could not open file for reading";
     return;
 }
QTextStream in(&nFile);
QString nText = in.readAll();
qDebug() << nText;
nFile.close();
}

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QString nFilename ="P:/DocumentArminV.txt";
wFile(nFilename);
read(nFilename);
return a.exec();
}

剧透警报:在这个答案的最后,有一个非常简单的修复建议。

OP 做了什么

关于 wFile(QString Filename) 中的 istream& getline (istream& is, string& str);

这在函数 wFile() 中声明了函数 getline()

  1. 这是关于 C++ 的有效声明。

  2. 关于示例代码,我错过了相应的headers。恕我直言,
    #include <istream>
    #include <string>
    需要进行此编译。
    但是,现有的 #include 有可能间接包含它们。因此,OP 的代码甚至可以在没有它们的情况下编译。

  3. 声明未使用的函数以及 re-declaring 已经声明的函数在某种程度上是无用的,但没有错。

为了证明这一点,我制作了一个小样本:

#include <cstdio>
#include <istream>
#include <string>

void func()
{
  puts("in func()\n");
  std::istream& getline(std::istream&, std::string&);
  // Even duplicated prototyping is accepted without complaints:
  std::istream& getline(std::istream&, std::string&);
}

int main () 
{
  func();
  return 0;
}

完美编译和运行。

输出:

in func()

Live Demo on coliru

OP(可能)想要什么

Using console, I want to write the desired user's input into a file via getline function inside the wFile function and then read it.

这听起来让我有点困惑。 std::getline(std::cin, ) 可用于从控制台读取 用户输入。可能是,只是措辞有点不好。

假设,OP 想要从控制台读取输入,显然,声明一个函数是不够的——必须调用它才能生效:

#include <iostream>

void func()
{
  std::cout << "Enter file name: ";
  std::string fileName; std::getline(std::cin, fileName);
  std::cout << "Got file name '" << fileName << "'\n");
}

int main () 
{
  func();
  return 0;
}

输出:

输入文件名:test.txt<kbd>↵</kbd>
得到文件名 'test.txt'

Live Demo on coliru

C++ std 与 Qt

Qt 无疑是建立在 C++ std 库之上的。但是,尽管可以避免混合使用这两种 API(或者没有特定原因),但不建议混合使用。

Qt 和 C++ std 都可以编写可移植软件。 Qt 涵盖了 std 库中提供的很多东西,但还有很多其他东西没有或还不是 std 的一部分。在某些情况下,Qt 不太通用但更方便,尽管这是我个人的看法。恕我直言,以下解释了我是如何得出这个结论的:

std::string 对比 QString

std::string 存储 char 的序列。 char 作为字形公开时的含义(例如在控制台上打印或在 window 中显示)取决于此公开中使用的编码。有很多编码以不同的方式解释 char 中的数字。

示例:

std::string text = "\xc3\xbc";

Decoded/displayed 和

根据 std::string 的字符类型,无法确定编码。因此,必须提供 附加提示 才能正确解码。

(据我所知,std::wstringwchar_t 类似。)

QString stores a sequence of Unicode 个字符。因此,设计选择了一种通用编码来减轻 "encoding hell".

只要程序在 QString 上运行,就不会出现编码问题。将QString与Qt的其他函数结合起来也是如此。然而,当 "leaving the Qt universe" 时,它会变得有点复杂——例如将 std::string 的内容存储到 QString.

这是程序员必须为 std::string 中的内容编码提供 附加提示 的地方。 QString 提供了很多 from...()to...() 方法可以用于 re-encode 内容,但应用程序程序员仍然有责任选择正确的方法。

假设 text 的预期内容应该是 ü(即 UTF-8 编码),这可以通过以下方式转换为 QString(并返回):

// std::string (UTF-8) -> QString
std::string text = "\xc3\xbc";
QString qText = QString::fromUtf8(text.c_str());
// QString -> std::string (UTF-8)
std::string text2 = qText.toUtf8();

将来自 std::cin 的输入传递给 QString 时必须考虑这一点:

std::cout << "Enter file name: ";
std::string input; std::getline(std::cin, input);
QString qFileName = QString::fromLocal8Bit(input);

即使是现在,代码仍然存在一点缺陷——std::cin 的语言环境可能已经随着 std::ios::imbue() 发生了变化。我必须承认,对此我不能说太多。 (在日常工作中,我试图完全避免这个话题,例如不依赖我认为对 Windows 特别重要的控制台输入 – 我们通常在其上部署给客户的 OS。)

相反,关于 OP 代码的最后一个注释:

如何修复

记住我上面的建议(如果没有必要不要混合 std 和 Qt),这可以在 Qt 中独占完成:

QTextStream qtin(stdin);
qtin.readline();

我必须承认我从来没有自己做过,但在 Qt 论坛上发现了这个:Re: stdin reading