什么是字符串?
在程序中,字符串是一种特殊的字符数组。它是由一串连续的字符组成,可以包含字母、数字、标点符号,以及空白字符等。在 C 语言中,字符串以 null 字符('\0')结尾,这个特殊字符表明了一个字符串的结束标志。
例如,字符串 "Hello world" 在 C 语言中表示为:
char str[] = "Hello world";
在程序中,我们有时需要对字符串进行处理,例如反转字符串、查找字符串中某个字符的位置、以及把字符串分割成子串等。下面我们来看一段 C 语言代码,实现反转字符串的功能。该程序可以从用户输入的字符串中,逆序输出字符串中的各个字符。
1.逆序字符串的递归实现
#include <stdio.h>
#include <string.h>
int my_strlen(char* str)
{
int count = 0;
while (*str != '\0')
{
count++;
str++;
}
return count;
}
void re_string(char* str)
{
char tmp = *str;
int len = my_strlen(str);
*str = *(str + len - 1);
*(str + len - 1) = '\0';
if (my_strlen(str + 1) >= 2)
{
re_string(str + 1);
}
*(str + len - 1) = tmp;
}
int main()
{
char arr[] = "abcdef";
re_string(arr);
printf("%s\n", arr);
return 0;
}
代码解释
首先看my_strlen函数:
int my_strlen(char* str)
{
int count = 0;
while (*str != '\0')
{
count++;
str++;
}
return count;
}
该函数用于计算输入字符串的长度,并返回长度值。首先定义了一个count变量用于计数,然后在循环中使用指向string开头的指针来逐一遍历每个字符,直到遇到字符串的终止字符'\0'。在每个字符被访问后,count值都会加1。最后,该函数返回count,作为字符串的长度。
接着看re_string函数:
void re_string(char *str)
{
char tmp = *str; // 保存当前字符
int len = my_strlen(str); // 求字符串长度,如果输入为"hello"则len为5
*str = *(str + len - 1); // 将首尾字符移动,如果输入为"hello"则变为"oellh"
*(str + len - 1) = '\0'; // 将字符串末尾置为\0,如果输入为"hello"则变为"oell\0"
if (my_strlen(str + 1) >= 2) // 如果剩余字符数大于等于2,则继续递归翻转
{
re_string(str + 1);
}
// 恢复首尾字符的位置
*(str + len - 1) = tmp; // 如果输入为"hello",则变为"oellh"
}
该函数用于递归地将输入的字符串翻转。具体做法是通过交换首尾字符的位置,并对剩下的字符串进行递归翻转。
函数首先保存字符串的第一个字符到tmp中,并计算字符串的长度。接下来,将字符串的第一个字符替换为最后一个字符,把字符串的最后一个字符设置为\0,以便将字符串视为以第一个字符为开头,以\0为终止的新字符串。
然后,函数检查当前字符串剩余部分的长度是否大于等于2,如果是,则递归调用re_string函数,并让它处理从第二个字符开始的子字符串。这个过程被反复进行,直到字符串中没有字符或者只剩下1个字符时递归结束。
最后,函数执行指令*(str + len - 1) = tmp来交换首尾字符位置。
最后来看一下main函数:
int main()
{
char arr[] = "abcdef";
re_string(arr);
printf("%s\n", arr);
return 0;
}
该函数首先定义了一个字符型数组arr,并将其初始化为"abcdef"。然后调用re_string函数,对该字符串进行翻转操作。最后,通过printf函数把翻转后的字符串打印出来,输出结果为"fedcba"。
所以,整个程序的输入为"abcdef",输出为"fedcba",是这段代码的运行结果。
总结
这段C语言代码定义了两个函数。my_strlen函数用于计算字符串的长度,是通过逐一遍历字符的方式来实现的。re_string函数则是通过递归来翻转字符串,它首先保存了字符串的第一个字符,然后移动字符串的首尾字符,接着递归翻转短字符串,并把首尾字符移回原位置。最后再通过main函数来调用re_string函数,对字符数组进行翻转操作,并输出结果。
2.逆序字符串的非递归实现
int my_strlen(char* str)
{
int count = 0;
while (*str != '\0')
{
count++;
str++;
}
return count;
}
void restring(char* str)
{
int left = 0;
int right = my_strlen(str) - 1;
while (left < right)
{
int tmp = str[left];///*(str=left)
str[left] = str[right];
str[right] = tmp;
left++;
right--;
}
}
int main()
{
char arr[] = "abcdef";
restring(arr);
printf("%s\n", arr);
return 0;
}
代码解释
int my_strlen(char* str)
{
int count = 0;
while (*str != '\0')
{
count++;
str++;
}
return count;
}
这里定义了一个函数 `my_strlen()`,用于计算字符串的长度。它的参数是一个指向字符数组的指针 `str`。定义了一个 `count` 变量,初始值为 `0`。通过一个 `while` 循环,遍历字符串中的每个字符,每遍历一次,就将 `count` 变量的值加 `1`,直到 `str` 指向字符串末尾 `'\0'` 为止。最后返回 `count` 变量的值,即字符串的长度。
void restring(char* str)
{
int left = 0;
int right = my_strlen(str) - 1;
while (left < right)
{
int tmp = str[left];
str[left] = str[right];
str[right] = tmp;
left++;
right--;
}
}
这里定义了函数 `restring()`,用于将字符串反转。和 `my_strlen()` 一样,它的参数也是一个指向字符数组的指针 `str`。首先,定义两个变量 `left` 和 `right`,分别表示字符串的首尾下标。`left` 的初始值为 `0`,`right` 的初始值为字符串的长度减 `1`。通过一个 `while` 循环,将字符串中字符两两交换位置。对于每个字符,使用一个 `tmp` 变量暂存左边的字符,将左边的字符赋值为右边的字符,右边的字符赋值为 `tmp` 变量中暂存的字符。这样就完成了原字符串的反转。
int main()
{
char arr[] = "abcdef";
restring(arr);
printf("%s\n", arr);
return 0;
}
这里是 `main()` 函数,首先定义了一个长度为 `7` 的字符数组 `arr`,并将字符串 `"abcdef"` 赋值给它。接着调用 `restring()` 函数来将字符串反转。由于数组是按地址传递的,所以在 `restring()` 函数中对 `arr` 数组中内容的改变也会反映到 `main()` 函数中。因此,在 `main()` 函数中打印出反转后的字符串。最后返回 `0`,表示程序正常结束。
程序的执行流程如下:
1. `main()` 函数中定义了一个字符数组 `arr`,并初始化为 `"abcdef"`。
2. 调用 `restring()` 函数,将字符数组 `arr` 中的内容反转。
3. `restring()` 函数中定义了 `left` 和 `right` 两个变量,分别指向字符串的首尾元素。使用 while 循环,当 `left < right` 时执行下列操作:
- 取出 `left` 位置上的字符,保存到 `tmp` 变量中。
- 将 `right` 位置上的字符覆盖给 `left` 位置上的字符。
- 将 `tmp` 变量中的字符覆盖给 `right` 位置上的字符。
- 将 `left` 右移一位,即 `left++`。
- 将 `right` 左移一位,即 `right--`。
4. `restring()` 函数执行完毕,`main()` 函数中打印反转后的字符数组 `arr` 的内容,此时为 `"fedcba"`。
整个程序的执行结果就是将字符数组 `arr` 中的 `"abcdef"` 反转成 `"fedcba"` 并打印出来。