(数据结构)C语言中字符串存储的三种形式 —— 2022/3/19

根据串中存储字符的数量及特点,对一些特殊的串进行了命名

  1. 空串:存储0个字符的串,如 str = ""(双引号紧挨着)
  2. 空格串:只包括空格的串,如 str = " "(双引号包括三个空格)
  3. 主串和子串:子串能在主串中找到,如 str_zi = "abc";str_zhu = "aabc"(子串能在主串中找到若干连续字符与之对应)

串的定长顺序存储

实际上是用普通数组(又称静态数组,如 char str[3] = "lo")存储

#include <stdio.h>
#include <string.h> 

int main(void){
	// 静态数组存储字符串 
	// 1. 提前知道存储字符串的长度(4)
	// 2. 申请长度为字符串长度 +1的静态数组 
    char str[5] = "love";  // str[4] = '\0' 
    printf("%s\n", str);  // love(字符 '\0'默认不输出,但是会占位置) 
    printf("%此字符串的长度:%d\n", strlen(str));  // 此字符串的长度:4(没有计算字符 \0) 
    return 0;
}

串的堆分配存储

堆区: 堆区的内存空间需要程序员手动使用 malloc 函数申请,并且在不用后要手动通过 free 函数将其释放

具体实现方式采用动态数组存储字符串

char *str = (char*)malloc(5*sizeof(char));
// 创建了动态数组 str,通过 malloc申请了 5个 char类型大小的堆存储空间

动态数组相比普通数组(静态数组)的优势是长度可变

str = (char*)realloc(str, 10*sizeof(char));
// 通过 realloc函数重新分配了 10个 char类型大小的堆存储空间

释放堆存储空间

free(str);

示例

#include <stdio.h>
#include <stdlib.h>
#include <string.h> 

int main(void){
	// 案例:用动态数组实现二个字符串的拼接 
	char *str1 = (char*)malloc(10 * sizeof(char)); 
	char *str2 = (char*)malloc(10 * sizeof(char)); 
	strcpy(str1, "www.baidu");
	strcpy(str2, ".com");
	int length1 = strlen(str1);  // 9
	int length2 = strlen(str2);  // 4
	
	if(length1 + length2 > 10){
		// 重新申请内存 
		str1 = (char*)realloc(str1, (length1+length2+1)*sizeof(char));
	}
	// 合并二个字符串
	for(int i = length1; i < length1+length2; i++){
		str1[i] = str2[i-length1];
	} 
	// 字符串的末尾要加上 '\0'
	str1[length1+length2] = '\0';
	printf("%s\n", str1);  // www.baidu.com
	free(str1);
    free(str2);
	return 0;
} 

串的块链存储

实际上指使用链表结构存储字符串(此处采用单链表)

#include <stdio.h>
#include<stdlib.h>
#include<string.h>
#define linkNum 3  // 全局设置链表中节点存储数据的个数

// 声明节点 
typedef struct Link {
    char str[linkNum];  // 数据域可存放 linkNum个数据
    struct Link *next;  // 代表指针域,指向直接后继元素
} link;

// 初始化链表 
link *initLink(char *str){
	int length = strlen(str);  // 计算字符串的长度
	int num = length / linkNum;  // 计算存储字符串需要的节点数
	if(length % linkNum){
		num++;
	} 
	// 创建并初始化首元节点(头节点是有数据的) 
	link *head = (link*)malloc(sizeof(link));
	head->next = NULL;
	link *temp = head;  // 创建指向头节点的临时节点
	// 初始化链表
	for(int i = 0; i < num; i++){
		int j = 0;
		for(; j < linkNum; j++){
			if(i*linkNum+j < length){
				temp->str[j] = str[i*linkNum+j];
			}else{
				temp->str[j] = '#';
			}
		}
		if(i*linkNum+j < length){
			link *newtemp = (link*)malloc(sizeof(link));  // 继续创建节点
			newtemp->next = NULL;
			temp->next = newtemp;
			temp = newtemp; 
		}
	} 
	return head;
}

// 展示字符串内容的函数 
void displayLink(link *head){
	while(head != NULL){
		for(int i = 0; i < linkNum; i++){
			printf("%c", head->str[i]);
		}
		head = head->next;
	}
}

int main(void)
{
    link *head = initLink("www.baidu.com");
    displayLink(head);
    return 0;
}
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是我来晚了!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值