# Qt4 中的字符串

> 原文： [http://zetcode.com/gui/qt4/strings/](http://zetcode.com/gui/qt4/strings/)

在本章中，我们将使用字符串。 Qt4 具有用于处理字符串的`QString`类。 它非常强大，并且具有多种方法。

`QString`类提供 Unicode 字符串。 它将字符串存储为 16 位`QChars`。 每个`QChar`对应一个 Unicode 4.0 字符。 与许多其他编程语言中的字符串不同，可以修改`QString`。

## 第一个例子

在第一个示例中，我们将使用`QString`类的一些基本方法。

`basic.cpp`

```cpp
#include <QTextStream>

int main(void) {

   QTextStream out(stdout);

   QString a = "love";

   a.append(" chess");
   a.prepend("I ");

   out << a << endl;
   out << "The a string has " << a.count() 
       << " characters" << endl;

   out << a.toUpper() << endl;    
   out << a.toLower() << endl;

   return 0;
}

```

在代码示例中，我们启动`QString`。 我们附加并添加一些其他文字。 我们打印字符串的长度。 最后，我们以大写和小写形式显示修改后的字符串。

```cpp
QString a = "love";

```

启动`QString`。

```cpp
a.append(" chess");
a.prepend("I ");

```

我们将文本附加和添加到初始字符串之前。 该字符串就地修改。

```cpp
out << a << endl;

```

终端上印有“我爱象棋”。

```cpp
out << "The a string has " << a.count() 
    << " characters" << endl;

```

`count()`方法返回字符串中的字符数。 `length()`和`size()`方法是等效的。

```cpp
out << a.toUpper() << endl;    
out << a.toLower() << endl;

```

这两个方法返回字符串的大写和小写副本。 他们不修改字符串，而是返回新的修改后的字符串副本。

`Output`

```cpp
$ ./basic 
I love chess
The a string has 12 characters
I LOVE CHESS
i love chess

```

## 初始化字符串

`QString`可以通过多种方式初始化。

`init.cpp`

```cpp
#include <QTextStream>

int main(void) {

   QTextStream out(stdout);

   QString str1 = "The night train";
   out << str1 << endl;

   QString str2("A yellow rose");
   out << str2 << endl;

   std::string s1 = "A blue sky";
   QString str3 = s1.c_str(); 
   out << str3 << endl;

   std::string s2 = "A thick fog";
   QString str4 = QString::fromAscii(s2.data(), s2.size());
   out << str4 << endl;

   char s3[] = "A deep forest";
   QString str5(s3);
   out << str5 << endl;

   return 0;
}

```

我们介绍了五种初始化`QString`的方法。

```cpp
QString str1 = "The night train";

```

这是在计算机语言中初始化字符串的传统方式。

```cpp
QString str2("A yellow rose");

```

这是启动`QString`的对象方式。

```cpp
std::string s1 = "A blue sky";
QString str3 = s1.c_str(); 

```

我们有一个来自 C++ 标准库的字符串对象。 我们使用其`c_str()`方法来生成以空字符结尾的字符序列。 该字符数组（字符串的经典 C 表示形式）可以分配给`QString`变量。

```cpp
std::string s2 = "A thick fog";
QString str4 = QString::fromAscii(s2.data(), s2.size());

```

在这些代码行中，我们将标准 C++ 字符串转换为`QString`。 我们利用`fromAscii()`方法。 它需要一个指向字符数组的指针。 指针通过`std::string`的`data()`方法返回。 第二个参数是`std::string`的大小。

```cpp
char s3[] = "A deep forest";
QString str5(s3);

```

这是一个 C 字符串。 它是一个字符数组。 `QString`构造器之一可以将`char`数组作为参数。

`Output`

```cpp
$ ./init 
The night train
A yellow rose
A blue sky
A thick fog
A deep forest

```

## 访问字符串元素

`QString`是`QChars`的序列。 可以使用`[]`运算符或`at()`方法访问字符串的元素。

`access.cpp`

```cpp
#include <QTextStream>

int main(void) {

   QTextStream out(stdout);

   QString a = "Eagle";

   out << a[0] << endl;
   out << a[4] << endl;

   out << a.at(0) << endl;

   if (a.at(5).isNull()) {
     out << "Outside the range of the string" << endl;  
   }      

   return 0;
}

```

我们从特定的`QString`打印一些单独的字符。

```cpp
out << a[0] << endl;
out << a[4] << endl;

```

我们打印字符串的第一个和第五个元素。

```cpp
out << a.at(0) << endl;

```

使用`at()`方法，我们检索字符串的第一个字符。

```cpp
if (a.at(5).isNull()) {
    out << "Outside the range of the string" << endl;  
}      

```

如果我们尝试访问字符串字符范围之外的字符，则`at()`方法返回`null`。

`Output`

```cpp
$ ./access 
E
e
E
Outside the range of the string

```

## 字符串长度

有三种获取字符串长度的方法。 `size()`，`count()`和`length()`方法。 所有人都做同样的事情。 它们返回指定字符串中的字符数。

`length.cpp`

```cpp
#include <QTextStream>

int main(void) {

  QTextStream out(stdout);

  QString s1 = "Eagle";
  QString s2 = "Eagle\n";
  QString s3 = "Eagle ";
  QString s4 = QString::fromUtf8("орел");

  out << s1.length() << endl;
  out << s2.length() << endl;
  out << s3.length() << endl;
  out << s4.length() << endl;

  return 0;
}

```

我们得到四个字符串的大小。

```cpp
QString s2 = "Eagle\n";
QString s3 = "Eagle ";

```

这两个字符串中的每个字符串都有一个白色字符。

```cpp
QString s4 = QString::fromUtf8("орел");

```

此字符串由俄语字母组成。

`Output`

```cpp
$ ./length
5
6
6
4

```

从输出中我们可以看到`length()`方法也计算了白色字符。 最后一个字符串包含 Unicode 字母，其中每个字母都存储为两个字符。

## 字符串插值

字符串插值是字符串的动态构建。 它允许我们用实际值替换特定的控制字符。 我们使用`arg()`方法进行插值。

`interpolation.cpp`

```cpp
#include <QTextStream>

int main() {

   QTextStream out(stdout);

   QString s1 = "There are %1 white roses";
   int n = 12;

   out << s1.arg(n) << endl;

   QString s2 = "The tree is %1 m high";
   double h = 5.65;

   out << s2.arg(h) << endl;

   QString s3 = "We have %1 lemons and %2 oranges";
   int ln = 12;
   int on = 4;

   out << s3.arg(ln).arg(on) << endl;

   return 0;
}

```

将要替换的标记以`%`字符开头。 下一个字符是指定自变量的数字。 一个字符串可以有多个参数。 `arg()`方法已重载，它可以接受整数，长数字，字符和`QChar`等。

```cpp
QString s1 = "There are %1 white roses";
int n = 12;

```

`%1`是我们计划替换的标记。 我们定义了一个整数。

```cpp
out << s1.arg(n) << endl;

```

`arg()`方法采用整数。 `%1`标记被`n`变量的值替换。

```cpp
QString s2 = "The tree is %1 m high";
double h = 5.65;

out << s2.arg(h) << endl;

```

这三行对于一个双数执行相同的操作。 正确的`arg()`方法将被自动调用。

```cpp
QString s3 = "We have %1 lemons and %2 oranges";
int ln = 12;
int on = 4;

out << s3.arg(ln).arg(on) << endl;

```

我们可以有多个控制字符。 `%1`引用第一个参数，`%2`引用第二个参数。 `arg()`方法在连续的链中调用。

`Output`

```cpp
$ ./interpolation 
There are 12 white roses
The tree is 5.65 m high
We have 12 lemons and 4 oranges

```

## 子串

在进行文本处理时，我们需要找到普通字符串的子字符串。 我们有`left()`，`mid()`和`right()`方法可供我们使用。

`substrings.cpp`

```cpp
#include <QTextStream>

int main(void) {

   QTextStream out(stdout);

   QString str = "The night train";

   out << str.right(5) << endl;
   out << str.left(9) << endl;
   out << str.mid(4, 5) << endl;

   QString str2("The big apple");
   QStringRef sub(&str2, 0, 7);

   out << sub.toString() << endl;

   return 0;
}

```

我们将使用这三种方法查找给定字符串的一些子字符串。

```cpp
out << str.right(5) << endl;

```

通过`right()`方法，我们获得`str`字符串的最右边五个字符。 将打印“火车”。

```cpp
out << str.left(9) << endl;

```

使用`left()`方法，我们获得`str`字符串的最左边九个字符。 将打印“夜晚”。

```cpp
out << str.mid(4, 5) << endl;

```

使用`mid()`方法，我们从第 4 个位置开始得到 5 个字符。 打印“夜晚”。

```cpp
QString str2("The big apple");
QStringRef sub(&str2, 0, 7);

```

`QStringRef`类是`QString`的只读版本。 在这里，我们创建`str2`字符串一部分的`QStringRef`。 第二个参数是位置，第三个参数是子字符串的长度。

`Output`

```cpp
$ ./substrings 
train
The night
night
The big

```

## 遍历字符串

`QString`由`QChars`组成。 我们可以遍历`QString`以访问字符串的每个元素。

`looping.cpp`

```cpp
#include <QTextStream>

int main(void) {

  QTextStream out(stdout);

  QString str = "There are many stars.";

  foreach (QChar qc, str) {
    out << qc << " ";  
  }

  out << endl;

  for (QChar *it=str.begin(); it!=str.end(); ++it) {
    out << *it << " " ;
  }

  out << endl;

  for (int i = 0; i < str.size(); ++i) {
    out << str.at(i) << " ";    
  }

  out << endl;

  return 0;
}

```

我们展示了通过`QString`的三种方法。 在将字母打印到终端时，我们在字母之间添加空格字符。

```cpp
foreach (QChar qc, str) {
  out << qc << " ";  
}

```

`foreach`关键字是 C++ 语言的 Qt 扩展。 关键字的第一个参数是字符串元素，第二个参数是字符串。

```cpp
for (QChar *it=str.begin(); it!=str.end(); ++it) {
  out << *it << " " ;
}

```

在此代码中，我们使用迭代器遍历字符串。

```cpp
for (int i = 0; i < str.size(); ++i) {
  out << str.at(i) << " ";    
}

```

我们计算字符串的大小，并使用`at()`方法访问字符串元素。

`Output`

```cpp
$ ./looping
T h e r e   a r e   m a n y   s t a r s . 
T h e r e   a r e   m a n y   s t a r s . 
T h e r e   a r e   m a n y   s t a r s . 

```

## 字符串比较

`QString::compare()`静态方法用于比较两个字符串。 该方法返回一个整数。 如果返回的值小于零，则第一个字符串小于第二个字符串。 如果返回零，则两个字符串相等。 最后，如果返回的值大于零，则第一个字符串大于第二个字符串。 “较少”是指字符串的特定字符在字符表中位于另一个字符之前。 比较字符串的方法如下：比较两个字符串的第一个字符； 如果它们相等，则比较以下两个字符，直到找到一些不同的字符或发现所有字符都匹配为止。

`comparing.cpp`

```cpp
#include <QTextStream>

#define STR_EQUAL 0

int main(void) {

   QTextStream out(stdout);

   QString a = "Rain";
   QString b = "rain";
   QString c = "rain\n";

   if (QString::compare(a, b) == STR_EQUAL) {
     out << "a, b are equal" << endl;
   } else {
     out << "a, b are not equal" << endl;
   }

   out << "In case insensitive comparison:" << endl;

   if (QString::compare(a, b, Qt::CaseInsensitive) == STR_EQUAL) {
     out << "a, b are equal" << endl;
   } else {
     out << "a, b are not equal" << endl;
   }     

   if (QString::compare(b, c) == STR_EQUAL) {
     out << "b, c are equal" << endl;
   } else {
     out << "b, c are not equal" << endl;
   }   

   c.chop(1);

   out << "After removing the new line character" << endl;

   if (QString::compare(b, c) == STR_EQUAL) {
     out << "b, c are equal" << endl;
   } else {
     out << "b, c are not equal" << endl;
   }            

   return 0;
}

```

我们将使用`compare()`方法进行区分大小写和不区分大小写的比较。

```cpp
#define STR_EQUAL 0

```

为了更好的代码清晰度，我们定义`STR_EQUAL`常量。

```cpp
QString a = "Rain";
QString b = "rain";
QString c = "rain\n";

```

我们将比较这三个字符串。

```cpp
if (QString::compare(a, b) == STR_EQUAL) {
    out << "a, b are equal" << endl;
} else {
    out << "a, b are not equal" << endl;
}

```

我们比较`a`和`b`字符串，它们不相等。 它们的第一个字符不同。

```cpp
if (QString::compare(a, b, Qt::CaseInsensitive) == STR_EQUAL) {
    out << "a, b are equal" << endl;
} else {
    out << "a, b are not equal" << endl;
}     

```

如果不区分大小写，则字符串相等。 `Qt::CaseInsensitive`使比较大小写不敏感。

```cpp
c.chop(1);

```

`chop()`方法从`c`字符串中删除最后一个字符。 现在`b`和`c`字符串相等。

`Output`

```cpp
$ ./comparing 
a, b are not equal
In case insensitive comparison:
a, b are equal
b, c are not equal
After removing the new line character
b, c are equal

```

## 转换字符串

字符串通常需要转换为其他数据类型，反之亦然。 `toInt()`，`toFloat()`和`toLong()`是将字符串转换为整数，浮点数和长整数的三种`QString`方法。 （还有更多这样的方法。）`setNum()`方法将各种数字数据类型转换为字符串。 该方法已重载，并且自动调用了正确的方法。

`Output`

```cpp
#include <QTextStream>

int main(void) {

  QTextStream out(stdout);

  QString s1 = "12";
  QString s2 = "15";
  QString s3, s4;

  out << s1.toInt() + s2.toInt() << endl;

  int n1 = 30;
  int n2 = 40;

  out << s3.setNum(n1) + s4.setNum(n2) << endl;

  return 0;
}

```

在示例中，我们将两个字符串转换为整数并将其相加。 然后，我们将两个整数转换为字符串并将其连接起来。

```cpp
out << s1.toInt() + s2.toInt() << endl;

```

`toInt()`方法将字符串转换为整数。 我们添加两个转换为字符串的数字。

```cpp
out << s3.setNum(n1) + s4.setNum(n2) << endl; 

```

在这种情况下，`setNum()`方法将整数转换为字符串。 我们连接两个字符串。

`Output`

```cpp
$ ./converts 
27
3040

```

## 字符

字符分为各种类别：数字，字母，空格和标点符号。 每个`QString`都由`QChar`组成。 `QChar`具有`isDigit()`，`isLetter()`，`isSpace()`和`isPunct()`方法来执行作业。

`letters.cpp`

```cpp
#include <QTextStream>

int main(void) {

  QTextStream out(stdout);

  int digits  = 0;
  int letters = 0;
  int spaces  = 0;
  int puncts  = 0;

  QString str = "7 white, 3 red roses.";

  foreach(QChar s, str) {

    if (s.isDigit()) {
      digits++;
    } else if (s.isLetter()) {
      letters++;
    } else if (s.isSpace()) {
      spaces++;
    } else if (s.isPunct()) {
      puncts++;
    }    
  }  

  out << QString("There are %1 characters").arg(str.count()) << endl;
  out << QString("There are %1 letters").arg(letters) << endl;
  out << QString("There are %1 digits").arg(digits) << endl;
  out << QString("There are %1 spaces").arg(spaces) << endl;
  out << QString("There are %1 punctuation characters").arg(puncts) << endl;

  return 0;
}

```

在示例中，我们定义了一个简单的句子。 我们将计算句子中的数字，字母，空格和标点符号的数量。

```cpp
int digits  = 0;
int letters = 0;
int spaces  = 0;
int puncts  = 0;

```

我们为每个字符类别定义一个整数变量。

```cpp
QString str = "7 white, 3 red roses.";

```

这是要检查的句子。

```cpp
foreach(QChar s, str) {

  if (s.isDigit()) {
    digits++;
  } else if (s.isLetter()) {
    letters++;
  } else if (s.isSpace()) {
    spaces++;
  } else if (s.isPunct()) {
    puncts++;
  }    
}  

```

我们使用`foreach`关键字来浏览`QString`。 每个元素都是`QChar`。 我们使用`QChar`类的方法来确定字符的类别。

```cpp
out << QString("There are %1 characters").arg(str.count()) << endl;
out << QString("There are %1 letters").arg(letters) << endl;
out << QString("There are %1 digits").arg(digits) << endl;
out << QString("There are %1 spaces").arg(spaces) << endl;
out << QString("There are %1 punctuation characters").arg(puncts) << endl;

```

使用字符串插值，我们将数字打印到终端。

`Output`

```cpp
$ ./letters 
There are 21 characters
There are 13 letters
There are 2 digits
There are 4 spaces
There are 2 punctuation characters

```

## 修改字符串

某些方法（例如`toLower()`方法）返回原始字符串的新修改副本。 其他方法可就地修改字符串。 我们将介绍其中的一些。

`modify.cpp`

```cpp
#include <QTextStream>

int main(void) {

   QTextStream out(stdout);

   QString str = "Lovely";   
   str.append(" season");

   out << str << endl;

   str.remove(10, 3);
   out << str << endl;

   str.replace(7, 3, "girl");
   out << str << endl;

   str.clear();

   if (str.isEmpty()) {
     out << "The string is empty" << endl;
   }

   return 0;
}

```

我们描述了四种就地修改字符串的方法。

```cpp
str.append(" season");

```

`append()`方法在字符串的末尾添加一个新字符串。

```cpp
str.remove(10, 3);

```

`remove()`方法从位置 10 开始从字符串中删除 3 个字符。

```cpp
str.replace(7, 3, "girl");

```

`replace()`方法用指定的字符串替换从`7`位置开始的`3`字符。

```cpp
str.clear();

```

`clear()`方法清除字符串。

`Output`

```cpp
$ ./modify 
Lovely season
Lovely sea
Lovely girl
The string is empty

```

## 对齐字符串

拥有整洁的输出是常见的要求。 我们可以使用`leftJustified()`和`rightJustified()`方法来对齐字符串。

`right_align.cpp`

```cpp
#include <QTextStream>

int main(void) {

   QTextStream out(stdout);

   QString field1 = "Name: ";
   QString field2 = "Occupation: ";
   QString field3 = "Residence: ";
   QString field4 = "Marital status: ";

   int width = field4.size();

   out << field1.rightJustified(width, ' ') << "Robert\n";
   out << field2.rightJustified(width, ' ') << "programmer\n";
   out << field3.rightJustified(width, ' ') << "New York\n";
   out << field4.rightJustified(width, ' ') << "single\n";

   return 0;
}

```

该示例将字段字符串向右对齐。

```cpp
int width = field4.size();

```

我们计算最宽字符串的大小。

```cpp
out << field1.rightJustified(width, ' ') << "Robert\n";

```

`rightJustified()`方法返回具有`width`字符的字符串。 如果字符串较短，则其余部分将使用提供的字符填充。 在我们的情况下，它是一个空格字符。

`Output`

```cpp
$ ./rightalign 
          Name: Robert
    Occupation: programmer
     Residence: New York
Marital status: single

```

在本章中，我们使用了 Qt4 中的字符串。