Arduino - 字符串

字符串用于存储文本。它们可用于在 LCD 或 Arduino IDE 串行监视器窗口中显示文本。字符串还可用于存储用户输入。例如,用户在连接到 Arduino 的键盘上键入的字符。

Arduino 编程中有两种类型的字符串 −

  • 字符数组,与 C 编程中使用的字符串相同。
  • Arduino 字符串,它允许我们在草图中使用字符串对象。

在本章中,我们将学习字符串、对象以及 Arduino 草图中字符串的使用。在本章结束时,您将了解在草图中使用哪种类型的字符串。

字符串字符数组

我们将学习的第一种字符串类型是一系列 char 类型的字符。在上一章中,我们了解了什么是数组;存储在内存中的一系列连续的相同类型变量。字符串是 char 变量的数组。

字符串是一种特殊数组,在字符串末尾有一个额外的元素,该元素的值始终为 0(零)。这被称为"以空字符结尾的字符串"。

字符串字符数组示例

此示例将展示如何创建字符串并将其打印到串行监视器窗口。

示例

void setup() {
    char my_str[6]; // 一个足够容纳 5 个字符的字符串的数组
    Serial.begin(9600);
    my_str[0] = 'H'; // 该字符串由 5 个字符组成
    my_str[1] = 'e';
    my_str[2] = 'l';
    my_str[3] = 'l';
    my_str[4] = 'o';
    my_str[5] = 0; // 第 6 个数组元素是空终止符
    Serial.println(my_str);
}

void loop() { 

}

以下示例显示了字符串的组成;一个字符数组,其中包含可打印字符,数组的最后一个元素为 0,表示字符串在此处结束。可以使用 Serial.println() 并传递字符串的名称,将字符串打印到 Arduino IDE 串行监视器窗口。

此示例可以更方便地编写,如下所示 −

示例

void setup() {
   char my_str[] = "Hello";
   Serial.begin(9600);
   Serial.println(my_str);
}

void loop() {

}

在此草图中,编译器计算字符串数组的大小,并自动用零终止字符串。一个长度为六个元素且由五个字符后跟一个零组成的数组的创建方式与上一个草图完全相同。

操作字符串数组

我们可以在草图中更改字符串数组,如以下草图所示。

示例

void setup() {
    char like[] = "I like coffee and cake"; // 创建字符串
    Serial.begin(9600);
    // (1) 打印字符串
    Serial.println(like);
    // (2) 删除字符串的一部分
    like[13] = 0;
    Serial.println(like);
    // (3) 将单词替换为字符串
    like[13] = ' '; // 用空格替换空终止符
    like[18] = 't'; // 插入新单词
    like[19] = 'e';
    like[20] = 'a';
    like[21] = 0; // 终止字符串
    Serial.println(like);
}
void loop() {

}

结果

I like coffee and cake
I like coffee
I like coffee and tea

该草图的工作方式如下。

创建和打印字符串

在上面给出的草图中,创建了一个新字符串,然后将其打印出来以显示在串行监视器窗口中。

缩短字符串

通过将字符串中的第 14 个字符替换为以空字符结尾的零 (2) 来缩短字符串。这是从 0 开始计数的字符串数组中的元素编号 13。

打印字符串时,将打印所有字符,直到新的以空字符结尾的零。其他字符不会消失;它们仍然存在于内存中,并且字符串数组的大小仍然相同。唯一的区别是,任何使用字符串的函数都只能看到第一个空字符结束符之前的字符串。

更改字符串中的单词

最后,该草图将单词"cake"替换为"tea"(3)。它首先必须用空格替换 like[13] 处的空终止符,以便将字符串恢复为最初创建的格式。

新字符用单词"tea"覆盖单词"cake"中的"cak"。这是通过覆盖单个字符来实现的。"cake"中的"e"被替换为新的空终止符。结果是字符串实际上以两个空字符结尾,一个是字符串末尾的原始字符,另一个是替换"cake"中"e"的新字符。这在打印新字符串时没有区别,因为打印字符串的函数在遇到第一个空终止符时会停止打印字符串字符。

操作字符串数组的函数

上一个草图通过访问字符串中的单个字符以手动方式操作字符串。为了更轻松地操作字符串数组,您可以编写自己的函数来执行此操作,或者使用 C 语言库中的某些字符串函数。

下一个草图使用了一些 C 字符串函数。

示例

void setup() {
    char str[] = "This is my string"; // 创建字符串
    char out_str[40]; // 此处放置的字符串函数的输出
    int num; // 通用整数
    Serial.begin(9600);
    
    // (1) 打印字符串
    Serial.println(str);
    
    // (2) 获取字符串的长度(不包括空终止符)
    num = strlen(str);
    Serial.print("String length is: ");
    Serial.println(num);
    
    // (3) 获取数组的长度(包括空终止符)
    num = sizeof(str); // sizeof() 不是 C 字符串函数
    Serial.print("Size of the array: ");
    Serial.println(num);
    
    // (4) 复制字符串
    strcpy(out_str, str);
    Serial.println(out_str);
    
    // (5) 将字符串添加到字符串末尾(附加)
   strcat(out_str, " sketch.");
   Serial.println(out_str);
   num = strlen(out_str);
   Serial.print("String length is: ");
   Serial.println(num);
   num = sizeof(out_str);
   Serial.print("Size of the array out_str[]: ");
   Serial.println(num);
}

void loop() {

}

结果

This is my string
String length is: 17
Size of the array: 18
This is my string
This is my string sketch.
String length is: 25
Size of the array out_str[]: 40

草图的工作方式如下。

打印字符串

新创建的字符串将打印到串行监视器窗口,就像在之前的草图中所做的那样。

获取字符串的长度

strlen() 函数用于获取字符串的长度。字符串的长度仅适用于可打印字符,不包括空终止符。

字符串包含 17 个字符,因此我们在串行监视器窗口中看到打印的 17。

获取数组的长度

运算符 sizeof() 用于获取包含字符串的数组的长度。长度包括空终止符,因此长度比字符串的长度多一个。

sizeof() 看起来像一个函数,但从技术上讲是一个运算符。它不是 C 字符串库的一部分,但在草图中用于显示数组大小和字符串大小(或字符串长度)之间的差异。

复制字符串

strcpy() 函数用于将 str[] 字符串复制到 out_num[] 数组。strcpy() 函数将传递给它的第二个字符串复制到第一个字符串中。该字符串的副本现在存在于 out_num[] 数组中,但仅占用数组的 18 个元素,因此数组中仍有 22 个可用 char 元素。这些可用元素位于内存中的字符串之后。

将字符串复制到数组中,以便我们在数组中有一些额外的空间可用于草图的下一部分,即将字符串添加到字符串的末尾。

将字符串附加到字符串(连接)

草图将一个字符串连接到另一个字符串,这称为连接。这是使用 strcat() 函数完成的。strcat() 函数将传递给它的第二个字符串放在传递给它的第一个字符串的末尾。

连接后,将打印字符串的长度以显示新的字符串长度。然后打印数组的长度以显示我们在 40 个元素长的数组中有一个 25 个字符长的字符串。

请记住,由于以零结尾,25 个字符长的字符串实际上占用了数组的 26 个字符。

数组边界

使用字符串和数组时,在字符串或数组的范围内工作非常重要。在示例草图中,创建了一个长度为 40 个字符的数组,以便分配可用于操作字符串的内存。

如果数组太小,并且我们尝试将大于数组的字符串复制到其中,则该字符串将被复制到数组的末尾。数组末尾以外的内存可能包含草图中使用的其他重要数据,这些数据随后将被我们的字符串覆盖。如果字符串末尾以外的内存超限,则可能导致草图崩溃或导致意外行为。