【问题标题】:qstring to qchar specialcharacterqstring 到 qchar 特殊字符
【发布时间】:2025-12-21 19:25:12
【问题描述】:

我正在开发一个解析器。我想逐个字符地解析一个文本文件。

bool parse(QString fileName,
           QString fieldTerminator,
           QString lineTerminator,
           QString encloseChar)
{
    QChar ft = *(fieldTerminator.unicode());
    QChar lt = *(lineTerminator.unicode());
    QChar ec = *(encloseChar.unicode());

    QFile file(fileName);

    if(!file.open(QIODevice::ReadOnly))
    {
        qDebug() << file.errorString();
        return false;
    }

    QTextStream inStream(&file);

    while(!inStream.atEnd())
    {
        QChar c;
        inStream >> c;

        if(c == ft)
            qDebug() << "fieldterm";
        else if(c == lt)
            qDebug() << "lineterm";
        else if(c == ec)
            qDebug() << "encloseChar";
    }

    return true;
}

我在将 fieldTerminator 等转换为特殊字符 (QChar::SpecialCharacter) 时遇到问题。

例如:如果我将fieldTerminator = "\n" 传递给函数,ft = '\' (92)

有没有简单的存档方法?谢谢。

【问题讨论】:

  • 我不确定你在问什么,当我传入QString( "\n" ) 时,我得到lt = 10 '\n'
  • -__- 有趣:screen 为什么它对我不起作用?
  • 因为我误解了问题,请看我的回答。
  • 您能否提供使用该功能的示例?与fieldTerminator = "\n"。或者说fieldTerminator 字符串的大小(当你像屏幕截图一样传递数据时)

标签: c++ qt qstring


【解决方案1】:

快速解析文本成为一个有状态的事情。如果要将两个字符序列\n识别为换行符\n,那么比较单个字符(c == ft)是不够的。您可以记住前一个字符并检查当前和以前的字符。

QString parse(QString const& text)
{
    static QChar BACKSLASH('\\');
    static QByteArray const SPECIAL_CHARS ("\"'?abfnrtv");
    static QString    const SPECIAL_QCHARS ("\\\"\'\?\a\b\f\n\r\t\v") ;

    QString result;
    QChar prev;

     for( int i = 0; i < text.size(); ++i)
     {
        QChar c = text[i];

        if( prev == BACKSLASH )
        {
            int idx = SPECIAL_CHARS.indexOf( c );
            if( idx != -1)
            {
                result.append( SPECIAL_QCHARS[idx] );
            }
            else
            {
               result.append( prev );
               result.append( c );
            }
            prev = 0;
        }
        else
        {
           result.append( c );
           prev = c;
        }
    }

    return result;
}

【讨论】:

  • 我认为它不起作用,因为inStream &gt;&gt; c; 只给你一个字符,例如\n
  • 它确实有效,因为它记住了rev 中的前一个字符。我修正了作业prev = c 中的一个错字。所以在第二次迭代中 prev 将是 '\' 而 c 将是 'n'
  • 我重写了示例以支持多个特殊字符。
  • 重写示例以构建并返回结果。
【解决方案2】:

您是否期望 QString fieldTerminator = "\n" 长度为 1 个字符并包含“行尾”?它不能那样工作: fieldTerminator 将是两个字符长:'\' 和 'n';如果你想遵循 printf() 逻辑,你应该自己实现它(或使用其他一些字符串解析函数)

另外,如果我正确理解您的解析器的逻辑,我建议将 QChar 用于参数 fieldTerminator、lineTerminator、encloseChar ——这些应该是一个字符,而不是字符串,amirite?

【讨论】:

    【解决方案3】:
    QChar strToChar(QString str)
    {
        QChar ret;
    
        if(!str.isEmpty())
        {
            if(str.size() == 1)
                ret = str.at(0);
            else if(str.size() == 2 && str.startsWith('\\'))
            {
                // special char
                QChar tmp = str.at(1);
                if(tmp == '\'')
                    ret = '\'';
                else if(tmp == '\"')
                    ret = '\"';
                else if(tmp == '?')
                    ret = '\?';
                else if(tmp == '\\')
                    ret = '\\';
                else if(tmp == 'a')
                    ret = '\a';
                else if(tmp == 'b')
                    ret = '\b';
                else if(tmp == 'e')
                    ret = '\e';
                else if(tmp == 'f')
                    ret = '\f';
                else if(tmp == 'n')
                    ret = '\n';
                else if(tmp == 'r')
                    ret = '\r';
                else if(tmp == 't')
                    ret = '\t';
                else if(tmp == 'v')
                    ret = '\v';
            }
            // hex, oct, unicode missing
        }
    
        return ret;
    }
    

    这就是我现在正在使用的......但我希望看到更好的实现

    【讨论】: