C/C++语言基础--字符串(包括字符串与字符数组、字符串与指针、字符串处理函数等),代码均可运行

本文主要是介绍C/C++语言基础--字符串(包括字符串与字符数组、字符串与指针、字符串处理函数等),代码均可运行,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本专栏目的

  • 更新C/C++的基础语法,包括C++的一些新特性

前言

  • 无论什么语言,字符串都是最重要、最基础的数据类型,他对二进制有很好的对应关系
  • 在C语言中没有提供专门的处理字符串的类型,但是我们可以通过字符数组、开辟内存地址来处理字符串
  • 本文将从字符串与字符数组的关系、字符串与内存的关系、字符串处理函数来讲解字符串。
  • 制作不易,欢迎收藏+点赞+关注,本人会持续更新

文章目录

  • 字符串与字符数组
    • 字符和字符串
    • 字符串与字符数组
      • 特点
      • 创建字符串两种形式
      • 字符串内存区域
    • 字符数组输入/输出
      • 输入
        • scanf
        • gets_s
        • getchar
      • 输出
    • 字符串处理函数(常用)
      • strlen
      • strcpy/strncpy
      • strcmp/strncmp/stricmp
      • strcat/strncat
      • strchr/strrchr
      • strstr
      • 其他(了解)
    • 内存相关的处理函数(常用)
      • memcmp
      • memcpy
      • memset

字符串与字符数组

字符和字符串

字符

  • 普通字符:‘a’,‘1’
  • 转义字符:‘\a’,‘\n’…

字符串

  • “Boy”,”Wy”

字符与字符串的区别

​ 1,形式上不同
​ 2,本质上:字符串有结束符 ‘\0’

在这里插入图片描述

字符A和字符串A所占内存空间不一样,以下代码输出分别是多少呢?

printf("%d %d", sizeof('a'),sizeof("a"));

答案:

1 2

解释:

  • char:内存是一字节,代表一个字符
  • ”a“,代表一个字符串,它含有一个字符’\0’,代表字符串结束,故等于2
  • 那请问:如果用strlen(“a”),又会输出多少呢??? 请看后面分析

字符串与字符数组

在各种编程语言中,字符串的地位都十分重要,C语言中并没有提供“字符串”这个特定类型,而是以特殊字符数组的形式来存储和处理字符串,这种字符数组必须以空字符’\0’结尾

特点

  • 字符数组可以没有'\0'
  • 字符串必须要有'\0'
  • 字符数组可以存储字符串

注意:字符串一定是字符数组,字符数组不一定是字符串

下列字符数组存储的是不是字符串:

 char str[10] = {'1','b','c'};		//并不是字符串,没有\0char str[1] ={'\0'};		 	    //是字符串 等价于””“abcdedf”; 			            //也是字符串,编译器会自动的在双引号最后加,上\0char str[10] =“abcdef"; 			//字符串可以用字符数组表示{'a','b'...'\0'}char str[10]={''a,,”b”,”c”,'\0'}	//不是字符串char *p=”maye”;			        //一个字符指针指向字符串

总结:

  • 编译器不会给字符数组自动添加’\0’

  • 编译器会自动给双引号的字符串字面值加上’\0’

  • 指针指向的字符串是常量,是没法修改的。

创建字符串两种形式

  • 字符数组形式:char str[20];
  • 字符指针形式:char* pc;

区别:

  • str是一个字符数组,字符串中的每个字符逐个存放,且可以随意修改
  • pc是一个字符指针,指向的是常量区的字符串,不能修改,只能访问
char  str[20];     str=“I love China!;    //(X) str是常量不能改变指向
char   *pc;        pc=“I love China!;     //(√) pc是变量,可以改变指向
  • 因此pc接受输入字符串时,要么指向一个字符串,要么开辟内存空间,

在这里插入图片描述

在这里插入图片描述

字符串内存区域

我们知道内存可以分为四区:

  • 栈区
  • 堆区
  • 全局区(静态区)
  • 代码区:存放二进制代码

其实在代码区和全局区之间还有一层文字常量区,用来存储字符串常量,生命周期随程序周期。

一下是某一位大佬写的,通过对比p1、p2、p3的内存区域,可以很明确的区别不同区的不同。

//main.cpp  
int a = 0; //全局初始化区  
char *p1; //全局未初始化区  
main()  
{  int b; //栈  char s[] = "abc";// 栈  char *p2;// 栈  char *p3 = "123456";// 123456\0在常量区,p3在栈上。  static int c =0//全局(静态)初始化区  p1 = (char *)malloc(10);  p2 = (char *)malloc(20);  //分配得来得10和20字节的区域就在堆区。  
strcpy(p1, "123456"); //123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。  
}  

字符数组输入/输出

输入

scanf
  • 使用scanf输入字符串时,遇到空格会自动截断,遇到回车结束,自动添加’\0’
  • 输入超出范围时,不会进行越界检查,甚至能完全输出
gets_s
  • 能读取空格,遇到回车结束,自动添加’\0’
  • 输入超出范围时,会进行越界检查,如下图

在这里插入图片描述

getchar
char str[10];
for(int i=0;i<10;i++)
{str[i] = getchar();
}
puts(str);	//如果结尾没有'\0',输出结果将不可预料,可以改为逐个字符输出
  • 在结尾自动加上’\0‘,养成良好习惯,否则在很多情况会出现很多问题
for(int i=0;i<10;i++)
{str[i] = getchar();if(str[i] == '\n'){str[i] = '\0';break;}
}

输出

由于C语言中没有真正的字符串类型,可以通过字符数组表示字符串,因为它的元素地址是连续的,这就足够了。

1. 从首地址开始逐字节寻址,把存储单元(一个字节)内的数据转换为ASCII字符格式输出。
2. 直到某一个字节内存的元素为字符'\0'时,输出此字符并且寻址结束。

如果字符数组里没有’\0’,那么使用printf (%s) 输出时,就找不到正确的结束标志,就会多输出一些乱码。

在这里插入图片描述

字符串处理函数(常用)

C语言提供了丰富的字符串处理函数,大致可分为字符串的输入、输出、合并、修改、比较、转换、复制、搜索几类。 使用这些函数可大大减轻编程的负担。用于输入输出的字符串函数,在使用前应包含头文件"stdio.h",使用其它字符串函数则应包含头文件"string.h"。

strlen

求字符串长度**(不包括\0)**,包括可以用 sizeof关键字

strlen("hello maye");	

strcpy/strncpy

把一个src拷贝到dest中去,要保证dst缓冲区有足够的内存。

  • strcpy 会在dest结尾添加\0
  • strncpy 不会在dest结尾添加\0
char dest[10];
strcpy(dest, "maye");
puts(dest);

strcmp/strncmp/stricmp

比较str1和str2,str1 > str2 返回1,str1==str2 返回0,否则返回-1

int res = strcmp("maye", "maye");
printf("res:%d\n", res);

strcat/strncat

  • 把src连接到dest的末尾(\0的位置)
char dest[20]="hello ";
strcat(dest, "maye");
puts(dest);

strchr/strrchr

  • 在字符串string中查找字符val,存在返回val的开始位置,否则返回NULL
char words[] = "hello every one,My name's maye";
puts(strchr(words, 'o'));

strstr

char* strstr(char* _String, char * _SubString)

  • 在字符串string中查找子串substr,存在返回substr的开始位置,否则返回NULL
char words[] = "hello every one,My name's maye";
puts(strstr(words, "one"));

其他(了解)

算法:刷题的时候很常用

  • strlwr 把字符串转成小写

  • strupr 把字符串转成大写

  • strset/strnset 把字符串s中的所有字符都设置成字符c

  • strrev 反转字符串

  • strdup 拷贝字符串,返回动态分配的内存,使用完毕后需要手动free

内存相关的处理函数(常用)

memcmp

  • 内存比较,不仅可以比较字符串,还可以比较其他的内存
  • 返回值为三种情况 >0, <0 , =0
int arr[5] = { 1,2,6,4,5};
int arr1[5] = { 1,2,5,4,5 };
int ok = memcmp(arr, arr1, sizeof(int) * 5);
int ok1 = strcmp(arr, arr1);
printf("%d  %d\n", ok,ok1);

memcpy

  • 内存拷贝
int temp[5];
memcpy(temp, arr,sizeof(int)*5);
//strcpy(temp, arr);		//复制整型数组会有问题for (int i = 0; i < 5; i++)
{printf("%d ", temp[i]);
}

memset

  • 字节对内存进行初始化
char num[5];
memset(num, 127, sizeof(char) * 5);
for(int i = 0; i < 5; i++)
{printf("%d ", num[i]);
}

nt temp[5];
memcpy(temp, arr,sizeof(int)*5);
//strcpy(temp, arr); //复制整型数组会有问题

for (int i = 0; i < 5; i++)
{
printf("%d ", temp[i]);
}


### memset+ 按**字节**对内存进行初始化```cpp
char num[5];
memset(num, 127, sizeof(char) * 5);
for(int i = 0; i < 5; i++)
{printf("%d ", num[i]);
}

这篇关于C/C++语言基础--字符串(包括字符串与字符数组、字符串与指针、字符串处理函数等),代码均可运行的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1099830

相关文章

Python实现MQTT通信的示例代码

《Python实现MQTT通信的示例代码》本文主要介绍了Python实现MQTT通信的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 安装paho-mqtt库‌2. 搭建MQTT代理服务器(Broker)‌‌3. pytho

MySQL字符串常用函数详解

《MySQL字符串常用函数详解》本文给大家介绍MySQL字符串常用函数,本文结合实例代码给大家介绍的非常详细,对大家学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录mysql字符串常用函数一、获取二、大小写转换三、拼接四、截取五、比较、反转、替换六、去空白、填充MySQL字符串常用函数一、

MySQL进行数据库审计的详细步骤和示例代码

《MySQL进行数据库审计的详细步骤和示例代码》数据库审计通过触发器、内置功能及第三方工具记录和监控数据库活动,确保安全、完整与合规,Java代码实现自动化日志记录,整合分析系统提升监控效率,本文给大... 目录一、数据库审计的基本概念二、使用触发器进行数据库审计1. 创建审计表2. 创建触发器三、Java

C++中全局变量和局部变量的区别

《C++中全局变量和局部变量的区别》本文主要介绍了C++中全局变量和局部变量的区别,全局变量和局部变量在作用域和生命周期上有显著的区别,下面就来介绍一下,感兴趣的可以了解一下... 目录一、全局变量定义生命周期存储位置代码示例输出二、局部变量定义生命周期存储位置代码示例输出三、全局变量和局部变量的区别作用域

C++中assign函数的使用

《C++中assign函数的使用》在C++标准模板库中,std::list等容器都提供了assign成员函数,它比操作符更灵活,支持多种初始化方式,下面就来介绍一下assign的用法,具有一定的参考价... 目录​1.assign的基本功能​​语法​2. 具体用法示例​​​(1) 填充n个相同值​​(2)

深入理解Go语言中二维切片的使用

《深入理解Go语言中二维切片的使用》本文深入讲解了Go语言中二维切片的概念与应用,用于表示矩阵、表格等二维数据结构,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧... 目录引言二维切片的基本概念定义创建二维切片二维切片的操作访问元素修改元素遍历二维切片二维切片的动态调整追加行动态

c++ 类成员变量默认初始值的实现

《c++类成员变量默认初始值的实现》本文主要介绍了c++类成员变量默认初始值,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录C++类成员变量初始化c++类的变量的初始化在C++中,如果使用类成员变量时未给定其初始值,那么它将被

Java中的数组与集合基本用法详解

《Java中的数组与集合基本用法详解》本文介绍了Java数组和集合框架的基础知识,数组部分涵盖了一维、二维及多维数组的声明、初始化、访问与遍历方法,以及Arrays类的常用操作,对Java数组与集合相... 目录一、Java数组基础1.1 数组结构概述1.2 一维数组1.2.1 声明与初始化1.2.2 访问

C++中NULL与nullptr的区别小结

《C++中NULL与nullptr的区别小结》本文介绍了C++编程中NULL与nullptr的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编... 目录C++98空值——NULLC++11空值——nullptr区别对比示例 C++98空值——NUL

C++ Log4cpp跨平台日志库的使用小结

《C++Log4cpp跨平台日志库的使用小结》Log4cpp是c++类库,本文详细介绍了C++日志库log4cpp的使用方法,及设置日志输出格式和优先级,具有一定的参考价值,感兴趣的可以了解一下... 目录一、介绍1. log4cpp的日志方式2.设置日志输出的格式3. 设置日志的输出优先级二、Window