【问题标题】:Embedded double quotes work in QT 4.7.4 not in 4.8.6嵌入式双引号适用于 QT 4.7.4 而不是 4.8.6
【发布时间】:2015-05-01 14:26:31
【问题描述】:

我有一个 Qt 4.7.4 应用程序正在运行。我正在尝试更新到 Qt 4.8.6,但是 4.8.6 版本不能像 4.7.4 那样处理嵌入式双引号。

例如,以下字符串是我们用作 QApplication 参数的十二个字符串之一:

QString myData = 
    QString("{\"type\":\"IndexFlt\",\"media\":\"1\",\"entityid\":\"0:0:0\"}");

在版本 4.7.4 中,十二个字符串作为 argv 的一部分传递给 QApplication。

当我在 4.7.4 版本中通过 theApp.arguments() 取回参数时,我会取回所有参数而格式没有变化。

但是,当我将相同的参数传递给版本 4.8.6 然后调用 theApp.arguments() 时,QStringList 只有六个条目而不是十二个。

当我查看第 6 个字符串时,我看到 QT 接受了参数 7-12 并将它们添加到前六个字符串中。

我在调试器中看到的 QStringList 参数在 4.7.4 和 4.8.6 之间是不同的。在 4.7.4

我认为论点 6 为:

"{"type":"IndexFlt","media":"1","entityid":"0:0:0"}"

但是对于 4.8.6 版本,我将参数 6 视为:

"{\type":"IndexFlt","media":"1","entityid":"0:0:0"} --ScriptArg:...

如您所见,字符串 type 前面不是双引号,而是/,而在将参数 7-12 添加到参数 6 后,结束 } 没有得到 "

关于如何解决这个问题的任何想法?应用程序中唯一改变的是 Qt 的版本。

您可以使用以下代码查看嵌入双引号的问题。 只需确保在第一个参数中使用至少两个参数 包含嵌入的双引号。例如,如果下面的代码是 编译成一个名为 test.exe 的 exe,然后你可以这样调用 test.exe: test.exe --DoubleQuotes="true" -NoDoubleQuotes=false

#include <QtGui/QApplication>
#include <QtCore/QStringList>
#include <iostream>

int main(int argc, char** argv)
{

    for (int i=0; i < argc ; i++)
    {
        std::string tmp = argv[i];
        std::cout << tmp << std::endl;
    }

    QApplication theApp(argc, argv);

    QStringList vArgs = theApp.arguments();
    foreach (QString t, vArgs)
    {
        std::cout << t.toStdString() << std::endl;
    }
}

【问题讨论】:

  • 请发布一个小型的单一源文件程序来重现该问题。
  • 我正在尝试显示更多代码,但这可能是不允许的。但是,我找到了一种更简单的方法来实现这一点。您只需要一个嵌入双引号的 argv,例如“--Somthing=\"TRUE\""。当您从 QT 应用程序中获取该参数时,您将看到“--Somthing=\TRUE”。看来 4.8.6 无法处理嵌入的双引号。
  • 再次:请发布一个小型的单一源文件程序来重现该问题。否则,在尝试重现您所询问的内容时会涉及太多猜测(至少对我而言)。
  • 感谢您的示例应用程序 - 我可以重现您的问题。我会试着仔细看看,但我不能保证我能做到多及时。

标签: c++ qt


【解决方案1】:

您遇到的问题源于 argv 解析 Qt 4.8.6 在模板函数 qWinCmdLine&lt;&gt;() 中实现的错误(来自 qcorecmdlineargs_p.h)。

在 Qt 4.7.4 中,该函数中处理命令行上转义引号的代码部分如下所示(左栏中的 cmets 是我的注释):

                    if (*p == '\\') {                // escape char?
/* skip escape */       p++;
                        if (*p == Char('\"') || *p == Char('\''))
/* keep quote */            ;                        // yes
                        else
/* else undo */             p--;                        // treat \ literally
                    } else {
                        if (!quote && (*p == Char('\"') || *p == Char('\''))) {        // " or ' quote
/* note and */              quote = *p++;               
/* skip quote */            continue;
                        } else if (QChar((short)(*p)).isSpace() && !quote)
                            break;
                    }

在 Qt 4.8.6 中,该函数部分如下所示:

                    if (*p == '\\') {                // escape char?
/* BUG */               if (*(p+1) == quote)
                            p++;
                    } else {
                        if (!quote && (*p == Char('\"') || *p == Char('\''))) {        // " or ' quote
                            quote = *p++;
                            continue;
                        } else if (QChar((short)(*p)).isSpace() && !quote)
                            break;

sn-ps 非常相似,除了 4.8.6 代码尝试更聪明一点,如果它看到下一个字符是 quote 时跳过转义字符,而不是 4.7.4 的跳过如果它注意到下一个字符不是'\"''\',则转义字符然后撤消该操作。问题是,在我注释为/* BUG */ 的行中,变量quote 仅在您已经在引用部分中时才设置。它不能正确处理不在命令行引号部分中的转义引号字符。

请注意,在 Qt 4.8.6 和 Qt 5.3.1 之间的某个时候,qWinCmdLine&lt;&gt;() 函数不再用于桌面 Windows 目标(它仅用于 WinCE 目标)。取而代之的是 Win32 API CommandLineToArgvW() 用于将命令行解析为 argv 数组 - 看起来这会带回您正在寻找的行为(看起来该错误已在仅 WinCE 版本的 @ 987654334@也一样)。

因此,要解决您的问题,您需要使用 4.8.6 以外的 Qt 版本(我不确定该错误是在哪个版本中出现的,或者修复的确切时间),或者您可以修补 @ 987654335@ 文件并重建 Qt 如果您出于某种原因需要 4.8.6。

另请注意,在 Windows 上,QCoreApplication(因此QApplication)会忽略您传入的argcargv 参数。解析的命令行始终从Win32 API GetCommandLine() 获得。虽然记录了这种行为,但当我尝试通过将不同的 argc/argv 值传递给 QCoreApplication 无效来测试事物时,这不是我所期望的并且有点令人恼火。

【讨论】:

  • 我知道在您提出您可能已经转向某些解决方案的问题之后,这个答案已经发布了足够长的时间。不过,我希望它对你有用。
猜你喜欢
  • 2020-05-10
  • 2011-05-18
  • 1970-01-01
  • 2014-10-05
  • 1970-01-01
  • 1970-01-01
  • 2021-09-17
  • 1970-01-01
  • 2011-12-29
相关资源
最近更新 更多