【问题标题】:Convert char * to QString and remove zeros将 char * 转换为 QString 并删除零
【发布时间】:2015-05-08 23:26:07
【问题描述】:

在我的应用程序中,我从本地(非 Unicode)字符集中的文件中读取字符串字段。 该字段为 10 字节,如果字符串

char str ="STRING\0\0\0\0"; // that was read from file
QByteArray fieldArr(str,10); // fieldArr now is STRING\000\000\000\000
fieldArr = fieldArr.trimmed() // from some reason array still containts zeros
QTextCodec *textCodec = QTextCodec::codecForLocale();
QString field = textCodec->ToUnicode(fieldArr).trimmed(); // also not removes zeros

所以我的问题 - 如何从字符串中删除尾随零?

附:我在调试时在“本地和表达式”窗口中看到零

【问题讨论】:

  • 设置 10 个字节时,char 数组是否终止? abcdefghijabcdefghij\0?
  • 没有这个数组将只有 10 个字符,没有最后的 \0,所以我使用 QByteArray 说我的字符串最多可以有 10 个字符。

标签: c++ qt codec qbytearray


【解决方案1】:

我将假设 str 应该是 char const * 而不是 char

只是不要超过QByteArray -- QTextCodec 可以处理 C 字符串,它以第一个空字节结束:

QString field = textCodec->toUnicode(str).trimmed();

附录:由于字符串可能不是以零结尾的,所以在末尾添加空字节的存储似乎是不可能的,并且复制准备复制似乎很浪费,我建议自己计算长度并使用接受 char 指针和长度的 toUnicode 重载。

std::find 对此很有用,因为如果在其中找不到元素,它会返回给定范围的结束迭代器。这使得特殊情况处理变得不必要:

QString field = textCodec->toUnicode(str, std::find(str, str + 10, '\0') - str).trimmed();

【讨论】:

  • 那么如果 str 为 10 个字符,因为它不是以 null 结尾的,会发生什么?
  • 那会爆炸的。一个简单的解决方法是为 11 个字符分配内存并设置str[10] = '\0';。然后它总是以空值终止。
  • 在我的情况下,当该字段是该结构的一部分时,我将数据从文件读取到结构。所以附加额外的字节会有问题。
  • 抱歉耽搁了,被肉空间困住了。我添加了另一种方式。
  • 谢谢大家,我看到修剪空终止字符串的唯一方法是自己制作。奇怪的是 Qt 错过了这一点。
【解决方案2】:

这对你有用吗?

#include <QDebug>
#include <QByteArray>

int main()
{
    char str[] = "STRING\0\0\0\0";
    auto ba = QByteArray::fromRawData(str, 10);

    qDebug() << ba.trimmed(); // does not work
    qDebug() << ba.simplified(); // does not work

    auto index = ba.indexOf('\0');
    if (index != -1)
        ba.truncate(index);
    qDebug() << ba;

    return 0;
}

使用fromRawData() 可以节省额外的副本。确保str 一直存在,直到您删除 ba

indexOf() 是安全的,即使你已经填满了整个 str,因为 QByteArray 知道您只有 10 个字节可以安全访问。它 不会触及 11 号或更晚。没有缓冲区溢出。

删除多余的\0 后,转换为QString 就很简单了。

【讨论】:

    【解决方案3】:

    我会这样做:

    char* str = "STRING\0\0\0\0";
    QByteArray fieldArr;
    
    for(quint32 i = 0; i < 10; i++)
    {
        if(str[i] != '\0')
        {
            fieldArr.append(str[i]);
        }
    }
    

    【讨论】:

    • 即使这段代码能做它应该做的事情,阅读和维护也是一场噩梦。您阅读此代码的次数将比编写它的次数多 1000 倍,并且每次您将花费大约 3 秒的宝贵思考时间来了解它在做什么。
    • 告诉我,@Ute Riegel,Assembler 是你的第一语言吗?
    【解决方案4】:

    QString 可以使用 fromLocal8Bit 从 char 数组指针构造。编解码器的选择方式与您在代码中手动选择的方式相同。

    您需要手动将长度设置为 10,因为您说您不能保证存在终止空字节。

    然后你可以使用remove() 来去掉所有的空字节。注意:STRI\0\0\0\0NG 也会导致 STRING 但你说这不会发生。

    char *str = "STRING\0\0\0\0"; // that was read from file
    QString field = QString::fromLocal8Bit(str, 10);
    field.remove(QChar::Null);
    

    【讨论】:

    • 谢谢@Simon Warta,但这不起作用,即这个字符串仍然包含零。 Qt 文档说:“QTextCodec::codecForLocale() 用于执行转换” 所以你的解决方案和我的完全一样,只是更短。
    • 你是对的。我确实希望 char 数组在第一个空字节之前被剪切,但只有在你没有设置任何长度的情况下才会出现这种情况。我更新了我的答案。
    【解决方案5】:

    你可以截断第一个\0之后的字符串:

    char * str = "STRING\0\0\0\0";                 // Assuming that was read from file
    QString field(str);                            // field == "STRING\0\0\0\0"
    field.truncate(field.indexOf(QChar::Null));    // field == "STRING" (without '\0' at the end)
    

    【讨论】:

      猜你喜欢
      • 2020-11-13
      • 2014-01-16
      • 2011-07-27
      • 2020-04-20
      • 2012-11-04
      • 1970-01-01
      • 1970-01-01
      • 2014-08-17
      • 2015-01-03
      相关资源
      最近更新 更多