C语言教程-详解C字符串
字符串可以被定义为以空字符('0')结尾的一维字符数组。字符数组或字符串用于操作文本,如单词或句子。数组中的每个字符占据一个字节的内存空间,而最后一个字符必须始终是0。终止字符('0')在字符串中很重要,因为它是唯一用于标识字符串结束的方式。当我们将字符串定义为char s[10]
时,字符s[10]
在内存中隐式地被初始化为空字符。
在C语言中,有两种声明字符串的方式:
- 使用字符数组
- 使用字符串字面值
让我们看一个使用字符数组声明字符串的例子:
char ch[10] = {'j', 'a', 'v', 'a', 't', 'p', 'o', 'i', 'n', 't', '\0'};
正如我们所知,数组索引从0开始,因此如下图所示:
在声明字符串时,大小是可选的。因此,我们可以将上面的代码写成:
char ch[] = {'j', 'a', 'v', 'a', 't', 'p', 'o', 'i', 'n', 't', '\0'};
我们也可以使用字符串字面值在C语言中定义字符串,例如:
char ch[] = "javatpoint";
在这种情况下,编译器会在字符串末尾自动添加'0'。
字符数组和字符串字面值的区别
字符数组和字符串字面值有两个主要区别:
- 对于字符数组,我们需要自己在数组末尾添加空字符'0',而对于字符串字面值,编译器会在末尾自动添加。
- 字符串字面值不能重新分配给另一组字符,而字符数组可以重新分配字符的值。
C中的字符串示例
让我们看一个简单的例子,其中声明并打印了一个字符串。在C语言中,'%s'被用作字符串的格式说明符。
#include <stdio.h>
#include <string.h>
int main(){
char ch[11] = {'j', 'a', 'v', 'a', 't', 'p', 'o', 'i', 'n', 't', '\0'};
char ch2[11] = "javatpoint";
printf("Char Array Value is: %s\n", ch);
printf("String Literal Value is: %s\n", ch2);
return 0;
}
输出
Char Array Value is: javatpoint
String Literal Value is: javatpoint
遍历字符串
遍历字符串是任何编程语言中最重要的部分之一。我们可能需要处理非常大的文本,这可以通过遍历文本来完成。遍历字符串与遍历整数数组有所不同。对于整数数组,我们需要知道数组的长度来进行遍历,但对于字符串,我们可以使用空字符('0')作为结束标志。
下面是一个简单的示例,演示了如何遍历字符串并打印每个字符:
#include <stdio.h>
void printString(char *str) {
int i = 0;
while (str[i] != '\0') {
printf("%c", str[i]);
i++;
}
printf("\n");
}
int main() {
char ch[] = "Hello, World!";
printString(ch);
return 0;
}
输出
Hello, World!
这是遍历字符串的基本方法。我们使用了一个while循环,它会在遇到空字符('0')之前打印每个字符。
使用字符串长度
让我们看一个计算字符串中元音字母个数的示例。
#include<stdio.h>
void main() {
char s[11] = "javatpoint";
int i = 0;
int count = 0;
while (i < 11) {
if (s[i] == 'a' || s[i] == 'e' || s[i] == 'i' || s[i] == 'u' || s[i] == 'o') {
count++;
}
i++;
}
printf("The number of vowels %d", count);
}
输出
The number of vowels 4
使用空字符
让我们通过使用空字符来看一下相同的计算元音字母个数的示例。
#include<stdio.h>
void main() {
char s[11] = "javatpoint";
int i = 0;
int count = 0;
while (s[i] != '\0') {
if (s[i] == 'a' || s[i] == 'e' || s[i] == 'i' || s[i] == 'u' || s[i] == 'o') {
count++;
}
i++;
}
printf("The number of vowels %d", count);
}
输出
The number of vowels 4
接受字符串输入
到目前为止,我们已经使用scanf
来接受用户输入。然而,在字符串的情况下,它也可以使用,但有一些不同的情况。考虑以下代码,它在遇到空格时存储字符串。
#include<stdio.h>
void main() {
char s[20];
printf("Enter the string?");
scanf("%[^\n]s", s);
printf("You entered %s", s);
}
输出
Enter the string?javatpoint is the best
You entered javatpoint is the best
很明显,上面的代码将无法处理以空格分隔的字符串。为了使这段代码适用于以空格分隔的字符串,需要在scanf
函数中进行一些小修改,即将scanf("%s", s)
改为scanf("%[^\n]s", s)
,这指示编译器在遇到换行符(\n
)时存储字符串s
。让我们考虑以下示例来存储以空格分隔的字符串。
#include<stdio.h>
void main() {
char s[20];
printf("Enter the string?");
scanf("%[^\n]s", s);
printf("You entered %s", s);
}
输出
Enter the string?javatpoint is the best
You entered javatpoint is the best
在这里,我们还必须注意,在scanf
中不需要使用地址(&
)运算符来存储字符串,因为字符串s
是一个字符数组,数组的名称即s
表示字符串(字符数组)的基地址,因此我们不需要在其前面加上&
。
一些重要注意事项
但是,在使用scanf
输入字符串时,有以下几点需要注意:
- 编译器不对字符数组进行边界检查。因此,字符串的长度可能超过字符数组的尺寸,这可能会覆盖一些重要数据。
- 我们可以使用
gets()
而不是scanf
,gets()
是在头文件string.h
中定义的内置函数。gets()
只能接收一个字符串。
字符串与指针
到目前为止,我们已经在数组、函数和基本数据类型中使用了指针。然而,指针也可以用于指向字符串。使用指针指向字符串有各种优点。让我们考虑以下示例,通过指针访问字符串。
#include<stdio.h>
void main() {
char s[11] = "javatpoint";
char *p = s; // 指针p指向字符串s
printf("%s", p); // 如果打印p,将输出字符串javatpoint
}
输出
javatpoint
我们知道字符串是字符数组,指针可以以与数组相同的方式使用。在上面的示例中,p声明为指向字符数组s的指针。p与s具有相同的影响,因为s是字符串的基地址,并在内部被视为指针。但是,我们无法直接更改s的内容或将s的内容直接复制到另一个字符串中。为此,我们需要使用指针来存储字符串。在下面的示例中,我们展示了使用指针来复制字符串内容的示例。
#include<stdio.h>
void main() {
char *p = "hello javatpoint";
printf("String p: %s\n", p);
char *q;
printf("copying the content of p into q...\n");
q = p;
printf("String q: %s\n", q);
}
输出
String p: hello javatpoint
copying the content of p into q...
String q: hello javatpoint
一旦定义了一个字符串,就不能将其重新分配给另一组字符。但是,使用指针,我们可以将一组字符分配给字符串。考虑以下示例。
#include<stdio.h>
void main() {
char *p = "hello javatpoint";
printf("Before assigning: %s\n", p);
p = "hello";
printf("After assigning: %s\n", p);
}
输出
Before assigning: hello javatpoint
After assigning: hello