第11课 Qt中的字符串类

1. 历史遗留问题和解决方案

(1)历史遗留问题

  ①C语言不支持真正意义上的字符串

  ②C语言用字符数组和一组函数实现字符串操作

  ③C语言不支持自定义类型,因此无法获得字符串类型

(2)解决方案

  ①从C到C++的进化过程中引入了自定义类型

  ②在C++中可以通过类完成字符串类型的定义

2. 标准库STL

(1)STL库

  ①STL是意义上需要与C++一同发布的标准库

  ②STL是一套以模板技术完成的C++类库

  ③STL中包含了常用的算法和数据结构

  ④STL中包含了字符串类

(2)Qt VS STL

  ①STL的具体实现依赖于编译器生产厂商

  ②STL的“标准”只是其接口是标准(即相同的全局函数、相同的算法类和数据结构、相同的类成员函数)

  ②不同厂商的编译器所带的STL,其实现存在差异(依赖于STL开发的C++程序在不同平台上的行为可能出现差异!!!)

(3)开发前的选择

  ①项目是否需要使用现有库的支持?(STL、Qt、MFC、私有库?)

  ②项目是否需要在不同平台间移植?(Linux、Windows、Andriod?)

  ③项目是否需要图形用户界面?(GUI、命令行、后台服务程序?)

3. Qt中的字符串类

(1)特点

  ①采用Unicode编码

  ②使用隐式共享技术(Copy On Write)来节省内存和不必要的数据拷贝

  ③跨平台使用,不必考虑字符串的平台兼容性

(2)QString VS string

  ①QString直接支持字符串和数字的相互转换

  ②QString直接支持字符串的大小比较

  ③QString直接支持字符编码间的相互转换

  ④QString直接支持std::string和std::wstring的相互转换

  ⑤QString直接支持正则表达式的应用

  ⑥……

【实例分析】QString基本操作示例

#include <QApplication>
#include <QDebug>
#include <QString>

void Sample_1()
{
    QString s = "and";
    
    s.append(" ");   //"and "
    s.append("Qt");  //"and Qt"
    s.prepend(" ");  //" and Qt"
    s.prepend("C++");//"C++ and Qt"
    
    qDebug() << s;
    
    s.replace("and", "&"); //"C++ & Qt"
    
    qDebug() << s;
}

void Sample_2()
{
    QString s = "";
    int index = 0;
    
    s.sprintf("%d. I'm %s, thank you!", 1, "SantaClaus"); //"1. I'm SantaClaus, thank you!"
    qDebug() << s;

    index = s.indexOf(",");
    //从索引0到index之间的字符子串
    s = s.mid(0, index);  //"1. I'm SantaClaus"
    qDebug() << s;
    
    index = s.indexOf(".");
    s = s.mid(index + 1,s.length()); //" I'm SantaClaus";
    s = s.trimmed();                 //"I'm SantaClaus";
    qDebug() << s;
    
    index = s.indexOf(" ");
    s = s.mid(index + 1, s.length()); //"SantaClaus"
    
    qDebug() << s;
}

void Sample_3(QString* a, int len)
{
    for(int i=0;i<len;i++)
    {
        for(int j=i+1; j<len; j++)
        {
            if( a[j] < a[i])
            {
                QString tmp = a[i];
                a[i] = a[j];
                a[j] = tmp;
            }
        }
    }
}

int main(int,char**)
{
    qDebug() << "Sample_1:";   
    Sample_1();  
    qDebug() << endl;
    
    qDebug() << "Sample_2:";  
    Sample_2(); 
    qDebug() << endl;
    
    qDebug() << "Sample_3:";  
    QString company[5] =
    {
        QString("Oracle"),
        QString("Borland"),
        QString("Microsoft"),
        QString("IBM"),
        QString("Horizon Studio")      
    };
    
    Sample_3(company, 5);
    
    for(int i=0; i<5; i++)
    {
        qDebug() << company[i];
    }  

    return 0;
}

(3)Qt中的QString

  ①QString在Qt库中几乎是无所不在

  ②所有的Qt图形用户组件都依赖于QString

【编程实验】为计算器实例添加消息响应

//QCalculatorUI.h

#ifndef _QCALCULATORUI_H_
#define _QCALCULATORUI_H_

#include <QWidget>
#include <QLineEdit>
#include <QPushButton>

class QCalculatorUI : public QWidget
{
    //要自定义信号和槽,必须在最开始的这里添加Q_OBJECT
    Q_OBJECT
private:
    QLineEdit* m_edit;
    QPushButton* m_buttons[20];

    //二阶构造法:当new一个QLineEdit和一些按钮时可能会失败,所以采用二阶构造
    QCalculatorUI(); //第1阶——先隐藏构造函数
    bool construct();//第2阶

private slots: //声明槽时得加slots
    void onButtonClicked();

public:
    static QCalculatorUI* NewInstance();
    void show();
    ~QCalculatorUI();
};

#endif  //_QCALCULATORUI_H_
View Code

//QCalculatorUI.cpp

#include "QCalculatorUI.h"
#include <QDebug>

QCalculatorUI::QCalculatorUI(): QWidget(NULL, Qt::WindowCloseButtonHint)
{

}

bool QCalculatorUI::construct()
{
    bool ret = true;

    const char* btnText[20] =
    {
        "7", "8", "9", "+", "(",
        "4", "5", "6", "-", ")",
        "1", "2", "3", "*", "",
        "0", ".", "=", "/", "C",
    };

    m_edit = new QLineEdit(this);//le的生命期由父组件来管理
    if( m_edit != NULL)
    {
        m_edit->move(10, 10);
        m_edit->resize(240, 30);
        m_edit->setReadOnly(true); //设置编辑框的只读属性
    }
    else
    {
        ret = false;
        return ret;
    }

    for(int i = 0; (i < 4) && ret; i++)
    {
        for(int j = 0; (j< 5) && ret; j++)
        {

            m_buttons[i * 5 + j] = new QPushButton(this);//按钮的生命期由父组件来管理
            if (m_buttons[i * 5 + j] != NULL)
            {
                m_buttons[i * 5 + j]->resize(40, 40);
                m_buttons[i * 5 + j]->move(10 + j * 50, 50 + i * 50);
                m_buttons[i * 5 + j]->setText(btnText[i * 5 + j]);

                //消息映射
                //1.消息名(信号)要加SIGNAL关键字,消息处理函数(槽):用SLOT关键字
                //2.信号和槽的函数签名必须一致,即都是无参的函数,返回值void
                connect(m_buttons[i*5+j], SIGNAL(clicked()), this, SLOT(onButtonClicked()));
            }
            else
            {
                ret = false;
            }
        }
    }

    return ret;
}

QCalculatorUI* QCalculatorUI::NewInstance()
{
    QCalculatorUI* ret = new QCalculatorUI();

    if((ret == NULL) || !ret->construct())
    {
        delete ret;//删除半成品
        ret = NULL;
    }

    return ret;
}

void  QCalculatorUI::show()
{
    QWidget::show();
    setFixedSize(width(), height());
}

void QCalculatorUI::onButtonClicked()
{
    //sender是QObject类的,用于表示消息的发送者
    QPushButton* btn = (QPushButton*)sender();
    QString clickText = btn->text();

    if(clickText == "")
    {
        QString text = m_edit->text();
        if(text.length() > 0)
        {
            text.remove(text.length()-1, 1);
            m_edit->setText(text);
        }
    }else if( clickText == "C")
    {
        m_edit->setText("");

    }else if( clickText == "=")
    {

    }
    else
    {
        m_edit->setText(m_edit->text() + clickText);
    }
}

 QCalculatorUI::~QCalculatorUI()
 {

 }

//main.cpp

#include <QApplication>
#include "QCalculatorUI.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QCalculatorUI* cal = QCalculatorUI::NewInstance();
    int ret = -1;

    if(cal != NULL)
    {
        cal->show();
        ret = a.exec();

        delete cal;
    }

    return ret;
}
View Code

4. 小结

(1)应用开发中大多数的情况都在进行字符串处理

(2)Qt比STL更适合于跨平台开发的场景

(3)Qt中的QString比STL中的string更强大易用

(4)Qt图形用户组件都依赖于QString

(5)项目开发时需要综合各种因素,选择需要使用的库

原文地址:https://www.cnblogs.com/5iedu/p/5433799.html