找回密码
 立即注册
收起左侧

【独家连载】Qt入门与提高: KS04_03 常用Qt类-QString

0
回复
3523
查看
[复制链接]
累计签到:41 天
连续签到:1 天
来源: 原创 2018-10-16 15:03:57 显示全部楼层 |阅读模式

马上注册,查看详细内容!注册请先查看:注册须知

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
本帖最后由 baizy77 于 2019-7-2 20:27 编辑

版权声明
---------------------------------------------------------------------------------------------------------------------
该文章原创于Qter开源社区(www.qter.org
作者: 女儿叫老白
转载请注明出处!
---------------------------------------------------------------------------------------------------------------------

网页版课程源码 提取码:1uy7
----------------------------------------------------------------------------------------------------------------------

引言
----------------------------------------------------------------------------------------------------------------------
我们都知道,Qt提供了非常多的类来处理各种事务,如果在服务端编程时,建议大家不要使用Qt的类库。因为引入Qt类库将使程序体积变得较大,所以在服务端编程时我们倾向于自己编写类库或者使用一些比较轻便小巧的第三方类库,这时Qt仅仅被用来制作项目的pro文件并生成Makefile。但在界面编程时本来就要用到Qt,所以就没必要选择其他类库了。今天开始,我们将选择几个Qt的常用类进行讲解。字符串处理是跨平台界面编程经常碰到的场景,对于字符串处理Qt提供了QString类来处理字符串。
正文
----------------------------------------------------------------------------------------------------------------------
在使用Qt提供的类时,首先需要引入Qt的类定义文件。Qt的类定义文件采用跟类同样的拼写方式,比如包含QString的头文件的语法:
  1. #include  <QString>
复制代码
    QString提供的接口也非常多,我们不可能一一介绍,如果有需要大家可以根据需求到assistant(注1)的Qt文档中寻求帮助。
我们给出几个案例,在这几个案例中,我们会碰到不同的字符串处理场景。
案例1-example01从输入目录中获取目录名、文件名
    在这个案例中,我们给出一个目录的全路径名,要求从这个目录中获取目录名和文件名。
    比如,输入:
QString strInput = "d:\\project\\gui\\src\\chapter01\\ks01_01\\ks01_01.pro";

    那么输出应该是:        
  1. 目录:"d:/project/gui/src/chapter01/ks01_01"
  2. 文件名:  " ks01_01.pro"  
复制代码

main()函数:
  1. if (false) {  
  2.        QString  strInput =  "d:\\project\\gui\\src\\chapter01\\ks01_01\\ks01_01.pro";  
  3.        QString strOutput;  
  4.        QString  strDir;  
  5.        QString  strFileName;  
  6.        strOutput  = example01(strInput, strDir, strFileName);  
  7.     }
  8.   
复制代码
    在上述代码中,在main()函数中调用example01()。我们注意到有这行代码:
  1. if (false) {  
  2. ……  
  3. }
复制代码

    这是本套课程的一种编程习惯。这样编码的目的是方便大家在调试时可以把注意力放在我们希望关注的代码上,比如我们只希望调试example01(),那么就可以把此处的代码改为
  1. if (true) {
  2.   ……  
  3. }
复制代码

    我们看一下example01()的实现代码:
example01():
  1. /**  
  2. * @brief  从输入目录中获取目录名、文件名  
  3. * @param[in] strInput  文件全路径  
  4. * @param[out] strDir 文件所在目录  
  5. * @param[out] strFileName  文件名(不含目录)  
  6. * @return true:成功, false:失败  
  7. */
  8.   bool example01(const QString& strInput, QString& strDir, QString& strFileName){  
  9.     if (0 == strInput.length()) {  
  10.         return false;  
  11.     }
  12.   
  13.     // str =  "d:\\project\\gui\\src\\chapter01\\ks01_01\\ks01_01.pro";  
  14.     QString str = strInput;      
  15.     // 首先将分隔符统一,便于统一处理windows及linux的目录  
  16.     str.replace("\", "/");       // str=d:/project/gui/src/chapter01/ks01_01/ks01_01.pro  
  17.     int idx = str.lastIndexOf("/");  
  18.     strDir = str.left(idx);       // strDir=d:/project/gui/src/chapter01/ks01_01  
  19.     strFileName = str.right(idx-1);// 用idx-1的目的是忽略文件名前面的"/"  
  20.                                                  // strFileName = ks01_01.pro
  21.       return true;  
  22. }
复制代码
    首先我们在函数开头提供了注释,希望大家也养成编写注释的习惯,这将对我们日后的软件开发工作产生深远的影响。
    函数提供一个输入参数strInput用来传入目录的全路径字符串,函数注释中的in表示输入参数,即在本接口中只会使用该值,对原始对象没有任何影响。
    函数还定义了两个输出参数strDir、strFileName分别用来存放解析后的目录名和文件名,这两个都是out参数,表示它们俩用作函数的返回值,会被该接口重写。
    函数入口对参数进行有效性判断。为了统一处理,我们利用replace()接口将字符串中的斜杠替换为linux风格"/",这种写法在windows和linux都支持。替换后的文本变为
  1. d:/project/gui/src/chapter01/ks01_01/ks01_01.pro
复制代码

然后,我们找到最后的斜杠,这是目录与文件名的分割点。
  1. int idx = str.lastIndexOf("/");
复制代码
然后,获取目录字符串:   
  1. strDir =  str.left(idx);
复制代码
此时的strDir = "d:/project/gui/src/chapter01/ks01_01"。
然后,获取文件名,请注意,使用idx-1目的是要剔除文件名前面的斜杠:
  1. strFileName = str.right(idx-1);
复制代码
此时,strFile = ks01_01.pro。
到此为止,我们成功将传入的文件全路径拆分成了目录与文件名。
案例2-example02字符串拼接
这个比较简单,直接上代码:
example02():
  1. /**  
  2. * @brief  组织日志信息  
  3. * @param[in] level  日志等级  
  4. * @param[out] strPerson   人员信息  
  5. * @param[out] strComputer  机器信息  
  6. * @param[out] strInfo  日志详情  
  7. * @return 拼接后的日志  
  8. */
  9.   
  10. QString  example02(int level, const QString& strPerson, const QString& strComputer, const QString& strInfo){  
  11.     QString str;  
  12.     str.sprintf("---- level=%02d, Person:", level); // str = "---- level=01, Person:"  
  13.     str  += strPerson;                            // str = "---- level=01, Person:Lisa"  
  14.     str  += ", Computer:";     // str =  "---- level=01, Person:Lisa, Computer:"  
  15.     str  += strComputer;      // str  = "---- level=01, Person:Lisa, Computer:adm01"  
  16.     str  += ", info="; // str =  "---- level=01, Person:Lisa, Computer:adm01, info="  
  17.     str  += strInfo;  // str =  "---- level=01, Person:Lisa, Computer:adm01, info=xxxxxx";  
  18.     return str;  
  19. }
复制代码
    QString的sprintf接口同编译器自带的公共sprintf的用法类似,先传入格式化字符串,最后传入变量值。字符串拼接采用QString重载的+=操作符。
每行代码后面都有拼接后的字符串内容。
    在VisualStudio的IDE环境中无法直接查看QString的值,可以使用VisualStudio的扩展工具查看。方法是选择VisualStudio的IDE中的"工具"->"扩展和更新(U)",然后选择“联机”,在右侧的搜索框中输入"Qt Visual Studio Tools",然后安装该组件,安装完后需要重新启动VisualStudio的IDE环境,然后就可以在调试窗口中查看QStrig变量的值了。
案例2-example03格式化字符串
    如果我们希望在QString的字符串按照一定的格式保存,比如将矩形的坐标、宽高按照一定格式(x,y,w,h)存储在QString中,除了sprintf()还可以使用arg()接口:
example03():   
  1. /**  
  2. *  @brief  使用arg()接口对信息格式化,输出矩形的坐标、宽高  
  3. *  @param[in] rect  矩形  
  4. *  @return 矩形的坐标、宽高  
  5. */  
  6. QString example03(const QRectF& rect){  
  7.     QString strRect = QString("%1,%2,%3,%4").arg(rect.x()).arg(rect.y()).arg(rect.width()).arg(rect.height());  
  8.     return strRect;  
  9. }
复制代码
在上述代码中,我们用arg()接口接龙完成了矩形坐标尺寸信息的格式化。
    其中,%1、%2、%3、%4对应arg()的个数,我们可以把需要传入的参数放到arg()中。
案例4-example04格式化字符串+翻译
如果我们的字符串带有可变参数,并且需要进行国际化翻译,那么使用arg()接口是个不错的选择:
example04():
  1. /**  
  2. *  @brief  使用arg()接口对信息格式化,带翻译  
  3. *  @param[in] strTemplateName  模板名称  
  4. *  @param[in] nTerminalCount  端子个数  
  5. *  @return 格式化后的信息  
  6. */
  7.   
  8. QString example04(const QString& strTemplateName, int nTerminalCount){  
  9.     QString strInfo = QObject::tr("template  name:%1 already has terminal count=%2.").arg(strTemplateName).arg(nTerminalCount);  
  10.     cout << strInfo.toLocal8Bit().data() << endl;  
  11.     return strInfo;  
  12. }
复制代码
    在上述代码中,待翻译文本中含有可变参数%1、%2,我们可以使用arg()接口配合实现该翻译。在ts文件中,待翻译文本内容:"templatename:%1 already has terminal count=%2.",翻译后的文本可以写成:"模板名:%1 已经包含%2个端子。"这样就可以翻译带参数的文本字符串了。

结语
----------------------------------------------------------------------------------------------------------------------
     在本文中,我们介绍了QString类的常用用法并给出了具体示例,其实QString还有很多接口可供调用,而且它在Qt的类库体系中扮演着非常重要的作用,值得我们去花点时间研究一下。
您想学习QString如何解析带分隔符的字符串吗?您想学习QString与数据如何相互转换吗?您想知道如何用QStrig保存小数点后15位的双精度数据吗?
欢迎关注《QT入门与提高-GUI产品开发》。选课后加课程的QQ群可以与更多学员交流,日常工作问题说不定可以在群中得到快速解答。


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册