QString :: split(“”)仅适用于第一个元素

时间:2014-01-28 20:24:01

标签: c++ qt

我正在制作一个程序,用空格分隔一系列项目。当我使用listt的第一个元素(listt [0])时,程序运行完全正常,但是当我尝试其他任何其他时,listt [0]如listt [1]或listt [2]我得到一个错误。任何意见或建议将不胜感激。

//text from text file
Brandan Janurary 1 2000 Math 7A 4 9 10 9 10 9 0 0 0 0 0 0 
Brandan Janurary 1 2000 Math 7A 4 9 10 7 10 10 0 0 0 0 0 0 
Brandan Janurary 1 2000 Math 7A 4 10 10 10 10 10 0 0 0 0 0 0 
Bob Janurary 1 2000 Math 7A 4 9 8 10 10 10 0 0 0 0 0 0 
Bob Janurary 1 2000 Math 7A 4 9 8 10 10 10 0 0 0 0 0 0 


//relevant part of code using listt[0] (works)
void MainWindow::on_pushButton_clicked()
{
    QString line, name;
    int avglist;
    QString *reallist;
    reallist =new QString[10000];
    QString *listof;
    QStringList listt;
    listof =new QString[10000];
    int x=0;

    name=ui->lineEdit->text();

    QFile file("C:/Users/brandan/Desktop/GUIPrograms/Kumonreal.txt");

    if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        QTextStream stream(&file);

        do
        {
        line = stream.readLine();
        listof[x] = line;
        qDebug() << line;
        x++;
        } while(!line.isNull());
    }

    for (int q=x; q>=0; q--)
    {
        QString Parsing;
        Parsing = listof[q];

        listt = Parsing.split(" ");

        qDebug() << listt[0]; //"name" in string
        reallist[q] = listt[0];


    }

    int Counter = sort(reallist,x,name);
    qDebug() << Counter;

}

2 个答案:

答案 0 :(得分:1)

QString :: split()的返回类型是QStringList而不是QString *

所以你的代码应该是这样的:

QStringList listt = Parsing.split(" ");

和访问类似

listt[0]
listt[1]
listt[2]...

答案 1 :(得分:1)

由于两个特定的错误,您的代码失败了。我先列出它们。其他错误不会立即失败,但仍然是错误。

  1. 您正在阅读空行,split()的结果会有一个元素。您正在尝试访问不存在的元素,但它失败了。

  2. 您的第二个循环从listof的无效索引开始,因为您已将x增加太多。因此,您尝试访问默认构造的空字符串,因为x太大了。如果你碰巧读了10,000行,你的x将指向数组末尾:索引10,000无效,最后一行是9,999!

  3. 您不会释放为列表元素分配的内存。使用智能指针来帮助您解决这个问题。对于使用QScopedArrayPointer分配的数组,您应该使用new Type[]。在这样的数组上使用QScopedPointer是一个错误(即使它没有崩溃!)。

  4. 该行末尾或行内的任何多余空格将转换为虚假元素。将QString::SkipEmptyParts作为第二个参数传递给split

  5. 如果显示空文件,代码将失败。检查文件结尾是错误的,您应该使用stream.atEnd()代替。

  6. 如果无法打开文件,代码也会失败:当文件无法打开时你应该立即退出 - 那时代码的其余部分没有任何意义,它可以节省一些缩进并使其更容易读取。

  7. 如果提供的文件超过10,000个元素,代码将失败:您有固定大小的数组。

  8. 如果任何行包含少于2个元素,代码将失败。

  9. 修复所有这些错误会产生这个可怕的C ++代码。它不会崩溃和刻录,对于包含10,000个条目或更少条目的文件,它“正常”工作,但它仍然是错误代码

    void processDataOrg(QIODevice * dev)
    {
        if (!dev->open(QIODevice::ReadOnly | QIODevice::Text)) return;
    
        const int N = 10000;
        QScopedArrayPointer<QString> listof(new QString[N]);
        QTextStream stream(dev);
        int x = -1; /* FIX for problem #2 */
        while (!stream.atEnd()) {
            QString line = stream.readLine();
            listof[++x] = line;  /* FIX for problem #2 */
            if (x == N-1) break;
        }
    
        QScopedArrayPointer<QString> reallist(new QString[N]);
        for (int q=x; q>=0; q--) {
            QString Parsing = listof[q];
            QStringList listt = Parsing.split(" ", QString::SkipEmptyParts);
            if (listt.size() < 2) continue; /* FIX for problem #1 */
    
            qDebug() << listt[0] << listt[1];
            reallist[q] = listt[0];
        }
    }
    

    当然,如果你使用这些列表就不会有这些问题,因为它们本来就是用来的!附加到列表不需要您跟踪任何索引。在迭代列表时,您不需要担心索引。你的编码就好像它是C,而不是C ++。您的代码可以简化如下。

    void processDataBetter(QIODevice * dev)
    {
        if (!dev->open(QIODevice::ReadOnly | QIODevice::Text)) return;
    
        QStringList lines;
        QTextStream stream(dev);
        while (! stream.atEnd()) {
            lines << stream.readLine();
        }
    
        QStringList names;
        foreach (QString line, lines) {
            QStringList elements = line.split(' ', QString::SkipEmptyParts);
            if (elements.size() < 2) continue;
            qDebug() << elements[0] << elements[1];
            names << elements[0];
        }
    }
    

    保留lines列表仍然没有任何意义,所以:

    void processDataOK(QIODevice * dev)
    {
        if (!dev->open(QIODevice::ReadOnly | QIODevice::Text)) return;
    
        QStringList names;
        QTextStream stream(dev);
        while (! stream.atEnd()) {
            QString line = stream.readLine();
            QStringList elements = line.split(' ', QString::SkipEmptyParts);
            if (elements.size() < 2) continue;
            qDebug() << elements[0] << elements[1];
            names << elements[0];
        }
    }
    

    由于您似乎希望按名称对数据进行排序,因此可以使用QMap作为按键隐式对其条目进行排序的数据结构。

    对于我们的测试,我们可以使用QBuffer而不是QFile来拥有一个自包含的单文件示例。输出按名称排序:

    "Bob" "Janurary" 
    "Bob" "Janurary" 
    "Brandan" "Janurary" 
    "Brandan" "Janurary" 
    "Brandan" "Janurary" 
    

    最后,一个相当正确,自足的例子:

    #include <QBuffer>
    #include <QTextStream>
    #include <QStringList>
    #include <QMultiMap>
    #include <QDebug>
    
    QByteArray fileData(
        "Brandan Janurary 1 2000 Math 7A 4 9 10 9 10 9 0 0 0 0 0 0\n"
        "Brandan Janurary 1 2000 Math 7A 4 9 10 7 10 10 0 0 0 0 0 0\n"
        "Brandan Janurary 1 2000 Math 7A 4 10 10 10 10 10 0 0 0 0 0 0\n"
        "Bob Janurary 1 2000 Math 7A 4 9 8 10 10 10 0 0 0 0 0 0\n"
        "Bob Janurary 1 2000 Math 7A 4 9 8 10 10 10 0 0 0 0 0 0");
    
    void processData(QIODevice * dev)
    {
        if (! dev->open(QIODevice::ReadOnly | QIODevice::Text)) return;
    
        typedef QMultiMap<QString, QStringList> Map;
        Map map;
    
        QTextStream stream(dev);
        while(! stream.atEnd()) {
            QString line = stream.readLine().trimmed();
            QStringList elements = line.split(' ', QString::SkipEmptyParts);
            if (elements.count() < 2) continue;
            QString name = elements[0];
            map.insert(name, elements);
        }
    
        for (Map::const_iterator it = map.begin(); it != map.end(); ++it) {
            qDebug() << it.key() << it.value()[1];
        }
    }
    
    int main()
    {
        QBuffer buf(&fileData);
        processData(&buf);
    }