在 C 语言里,字符串是由一系列字符构成,并且以空字符 '\0'
作为结束标志。
1. 字符串的定义和初始化
字符数组形式
#include <stdio.h>
int main() {
// 使用字符串字面量初始化字符数组
char str1[]="hello";
// 初始化字符数组
// 另一种初始化方式
char str2[10] = {'W', 'o', 'r', 'l', 'd', '\0'};
// 更简洁的初始化方式
char str3[10] = "Hello";
printf("str1: %s\n", str1);
printf("str2: %s\n", str2);
printf("str3: %s\n", str3);
return 0;
}
str1
:使用字符串字面量直接初始化字符数组。编译器会自动在字符串末尾添加空字符'\0'
。是字符串变量,允许被修改。str2
:逐个字符初始化字符数组,并且手动添加了空字符'\0'
。str3
:同样使用字符串字面量初始化字符数组,与str1
类似,编译器会自动处理空字符。
字符指针形式
#include <stdio.h>
int main() {
// 定义一个字符指针指向字符串常量
char *str = "Hello, World!";
printf("%s\n", str);
return 0;
}
这里的 str
是一个字符指针,它指向了一个字符串常量。需要注意的是,字符串常量存储在只读内存区域,不能通过指针去修改它。
字符数组的存储方式和整型数组在存储上的区别
- 第一处
len = 5
:data
数组初始化有5
个元素,sizeof(data)
是数组总字节数,sizeof(data[0])
是单个元素字节数,相除得到元素个数5
。 - 第二处
len = 6
:cdata2
存储字符串"hello"
,编译器自动添加结束符'\0'
,实际元素为'h'
、'e'
、'l'
、'l'
、'o'
、'\0'
,共6
个,计算得6
。 - 第三处
len = 6
:cdata
数组定义大小为6
,sizeof(cdata)/sizeof(cdata[0])
直接返回定义的数组大小6
。
输出:
len = 5
len = 6
len = 6
字符数组的存储方式多了结束标志‘\0’
2. 字符串的输入输出
输出字符串
使用 printf
函数输出字符串:
使用 puts 函数输出字符串:
输入(获取)字符串
使用 scanf
函数输入字符串:
使用 gets 函数输入字符串:
#include <stdio.h>
#include <string.h>
int main()
{
char *p="diqiqzhangzifuchuan";
char str[128]={'\0'};
puts(p);//输出字符串
printf("%s\n",p);//输出字符串
puts("请输入字符串");
//scanf("%s",str);获取字符串
//gets(str);//获取字符串
//strcpy(str,p);
strncpy(str,p,6);
puts(str);
return 0;
}
不过要注意,scanf
遇到空格就会停止读取,若想读取包含空格的字符串,可以使用 fgets
函数:
#include <stdio.h>
int main() {
char str[100];
printf("请输入一个字符串: ");
fgets(str, sizeof(str), stdin);
printf("你输入的字符串是: %s", str);
return 0;
}
stdin
用于标识输入数据的来源,程序通过它读取外部输入内容。当使用 scanf
、fgets
、getchar
等输入函数时,若未指定其他输入流,默认从 stdin
读取数据,即接收用户通过键盘输入的内容。
1. 使用 malloc
函数动态开辟字符串
函数原型 void *malloc(size_t size)
size
:表示每个元素的大小(以字节为单位)。
步骤分析
- 明确字符串长度:要知道需要存储的字符串大概有多长,并且要额外预留 1 个字节用于存放字符串结束符
'\0'
。 - 调用
malloc
函数:根据确定的长度调用malloc
函数分配内存。 - 检查分配结果:查看
malloc
函数的返回值是否为NULL
,若为NULL
则表示内存分配失败。 - 使用字符串:把字符串内容复制到分配的内存中。
- 释放内存:使用完字符串后,调用
free
函数释放之前分配的内存,防止出现内存泄漏。
malloc
函数用于在堆内存中分配指定大小的连续内存空间。以下是使用 malloc
动态开辟字符串的示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int length = 20;
// 使用 malloc 动态分配内存
char *str = (char *)malloc((length + 1) * sizeof(char));
if (str == NULL) {
printf("内存分配失败\n");
return 1;
}
// 复制字符串到分配的内存中
strcpy(str, "Hello, World!");
printf("字符串: %s\n", str);
// 释放内存
free(str);
return 0;
}
代码解释:
malloc((length + 1) * sizeof(char))
:分配length + 1
个字符大小的内存空间,多出来的 1 个字符用于存储字符串结束符'\0'
。strcpy(str, "Hello, World!")
:将字符串"Hello, World!"
复制到分配的内存中。free(str)
:释放之前分配的内存,避免内存泄漏。
2. 使用 calloc
函数动态开辟字符串
函数原型 void* calloc(size_t num, size_t size);
num
:表示要分配的元素数量。size
:表示每个元素的大小(以字节为单位)。- 函数返回一个指向分配内存起始位置的指针,若分配失败则返回
NULL
。
使用calloc
动态开辟字符串的步骤
- 确定字符串长度:先明确要存储的字符串大概需要多大的空间,然后加上 1 个字节用于存储字符串结束符
'\0'
。 - 调用
calloc
函数:依据确定的长度调用calloc
函数分配内存。 - 检查分配结果:查看
calloc
函数的返回值是否为NULL
,若为NULL
则表示内存分配失败。 - 使用字符串:将字符串内容复制到分配的内存中。
- 释放内存:使用完字符串后,调用
free
函数释放之前分配的内存,防止内存泄漏。
calloc
函数也用于动态分配内存,与 malloc
不同的是,calloc
会将分配的内存初始化为 0。示例如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int length = 20;
// 使用 calloc 动态分配内存并初始化为 0
char *str = (char *)calloc(length + 1, sizeof(char));
if (str == NULL) {
printf("内存分配失败\n");
return 1;
}
// 复制字符串到分配的内存中
strcpy(str, "Hello, C!");
printf("字符串: %s\n", str);
// 释放内存
free(str);
return 0;
}
代码解释:
calloc(length + 1, sizeof(char))
:分配length + 1
个字符大小的内存空间,并将其初始化为 0。strcpy(str, "Hello, C!")
:将字符串"Hello, C!"
复制到分配的内存中。free(str)
:释放之前分配的内存。
3. 使用 realloc
函数调整字符串内存大小
函数原型 void *realloc(void *ptr, size_t size)
使用步骤
- 分配初始内存:首先使用
malloc
或calloc
分配初始的字符串内存。 - 使用
realloc
调整内存大小:当需要增加或减少字符串长度时,调用realloc
函数。 - 检查
realloc
的返回值:如果返回NULL
,说明内存分配失败,需要进行相应的错误处理。 - 释放内存:使用完字符串后,使用
free
函数释放内存。
realloc
函数用于调整已经分配的内存块的大小。示例如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int initialLength = 10;
// 初始分配内存
char *str = (char *)malloc((initialLength + 1) * sizeof(char));
if (str == NULL) {
printf("内存分配失败\n");
return 1;
}
strcpy(str, "Hello");
// 需要更大的内存空间
int newLength = 20;
char *newStr = (char *)realloc(str, (newLength + 1) * sizeof(char));
if (newStr == NULL) {
printf("内存重新分配失败\n");
free(str);
return 1;
}
str = newStr;
// 继续添加字符串
strcat(str, ", World!");
printf("字符串: %s\n", str);
// 释放内存
free(str);
return 0;
}
代码解释:
malloc((initialLength + 1) * sizeof(char))
:初始分配initialLength + 1
个字符大小的内存空间。realloc(str, (newLength + 1) * sizeof(char))
:将之前分配的内存空间调整为newLength + 1
个字符大小。free(str)
:释放最终分配的内存。
3.free
C 库函数 void free(void *ptr) 释放之前调用 calloc、malloc 或 realloc 所分配的内存空间。
函数原型
void free(void *ptr);
- 参数:
ptr
是一个指向之前通过calloc
、malloc
或realloc
分配的内存块的指针。 - 返回值:该函数没有返回值,其返回类型为
void
。
free
函数的主要功能是将之前动态分配的内存归还给操作系统,这样这块内存就可以被其他程序或者本程序后续的内存分配操作再次使用。这有助于避免内存泄漏问题,所谓内存泄漏,就是程序不断分配内存却不释放,最终导致可用内存越来越少。
释放 malloc
分配的内存
#include <stdio.h>
#include <stdlib.h>
int main() {
// 使用 malloc 分配内存
int *arr = (int *)malloc(5 * sizeof(int));
if (arr == NULL) {
printf("内存分配失败\n");
return 1;
}
// 使用分配的内存
for (int i = 0; i < 5; i++) {
arr[i] = i;
}
// 释放内存
free(arr);
return 0;
}
释放后指针置为 NULL
:为了避免误操作,在释放内存后,建议将指针置为 NULL
。
int *ptr = (int *)malloc(sizeof(int));
free(ptr);
ptr = NULL; // 释放内存后将指针置为 NULL
4.memset
void *memset(void *str, int c, size_t n)
是 C 语言标准库 <string.h>
中的一个函数,用于将一段内存区域的每个字节都设置为指定的值。
函数原型
void *memset(void *str, int c, size_t n)
- 返回值:返回指向
str
的指针,即指向被设置的内存块起始位置的指针。这样设计是为了方便进行链式操作,比如可以在调用memset
之后紧接着进行其他操作。 - 参数:
str
:指向要设置的内存块的指针。它是一个void *
类型的通用指针,这意味着可以传入任意类型的指针,因为void *
可以接收任何类型的指针。c
:要设置的值。虽然参数类型是int
,但实际上只会使用该整数的低 8 位(即一个字节)的值来进行设置。n
:要设置的字节数,类型为size_t
,size_t
是一个无符号整数类型,通常用于表示对象的大小。
功能描述
memset
函数的主要功能是将从 str
所指向的内存地址开始的连续 n
个字节,每个字节都设置为 c
的低 8 位所表示的值。
初始化字符数组
#include <stdio.h>
#include <string.h>
int main() {
char str[10];
// 将 str 数组的前 10 个字节都设置为 'A'
memset(str, 'A', 10);
for (int i = 0; i < 10; i++) {
printf("%c ", str[i]);
}
printf("\n");
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *p;
p=(char*)malloc(1);
*p='c';
free(p);
p=NULL;
p=(char*)malloc(12);
if(p==NULL){
printf("malloc error\n");
exit(-1);
}
memset(p,'\0',12);
printf("扩容前地址:%x\n",p);
int len =strlen("chenlicheng123456788888");
int newLen=len-12+1;
realloc(p,newLen);
printf("扩容后地址:%x\n",p);
strcpy(p,"chenlicheng123456788888");
puts(p);
puts("end");
return 0;
}