C/C++ 字符数组(字符串)和指针总结(char *, string, Type *)

本文深入解析C++中的字符串处理与指针运用,包括char*与string类型的使用技巧,指针的基本概念及高级操作,以及两者间的转换方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:学过的东西好久不用就会忘掉,也许这就是所谓的“用进废退”吧!
所以这里对C(++) 对字符串、指针等知识点做一个小小的总结.
补充(2022-10-30):这篇博文是之前所作的笔记,现在看来好简陋,对框架进行了简单的修补,内容基本没变。

Part.I 字符串 char*

Chap.I 读入字符串

cin方法

char line[100];
cin>>line;

scanf方法

char line[100];
scanf("%s",line);//注意不是&line
  • scanf 会自动添加结尾的\0
  • scanf 读入到空格为止

cin.getline 方法

//cin.getline(char buf[],int bufSize);
char line[100];
cin.getline(line,sizeof(line));

读入一行(行长度不超过bufSize-1)或bufSize-1 个字符到buf,自动添加\0 回车换行符不会写入buf,但是会从输入流中去掉。如果这一行的字符数超过bufSize-1 ,实际上只取前bufSize-1 个字符,后面的存放在输入流中,不会报错。

gets方法

//gets(char buf[]);
char line[100];
gets(line);
  • 读入一行,自动添加’\0’
  • 回车换行符不会写入buf,但是会从输入流中去掉。可能导致数组越界!所以要确保buf 数组足够的大

Chap.II 输出字符串

cout 方法

cout<<str;

printf方法

printf("%s",line);

Chap.III 字符串函数

#include <cstring> //所要包含的头文件
1.字符串拷贝
strcpy(char[] dest,char[] src);//将src拷贝到dest中
2.字符串比较大小(字典序 前小后大)
int strcmp(char[] s1,char[] s2);//s1<s2,返回负数,s1=s2,返回0
3.求字符串长度
int strlen(char[] s);
4.字符串拼接
strcat(char[] s1,char[] s2);//s2拼接到s1后面
5.字符串转换大小写
strupr(char []);//转大写
strlwr(char []);//转小写

形参为char[] 类型,则实参可以是char 数组或字符串常量。

本来想好好自己写一下的,但是写到这里发现一个特牛的博客,里面对此介绍的内容是我见过的最详尽的,传送门如下:
https://blog.youkuaiyun.com/xfjjs_net/article/details/79329030

以上就是 C 语言中的字符串知识点
除此之外,C++中还提供了string 这一字符串对象
传送门:门 1

Part.II 字符串 string

上面介绍了C语言中char*类型的字符串,在C++中有更好用的string类型的字符串,需要以下include

#include <string>

switch 的表达式中不能用char *或者string

Chap.I 字符串初始化

string strs 	//生成空字符串
string s(str) 	//生成字符串str的复制品
string s(str, stridx) //将字符串str中始于stridx的部分作为构造函数的初值
string s(str, strbegin, strlen) //将字符串str中始于strbegin、长度为strlen的部分作为字符串初值
string s(cstr) 	//以C_string类型cstr作为字符串s的初值
string s(cstr,char_len)    //以C_string类型cstr的前char_len个字符串作为字符串s的初值
string(num, c) //生成一个字符串,包含num个c字符
string(strs, beg, end)    //以区间[beg, end]内的字符作为字符串s的初值

Chap.II 字符串函数

列个大表格,除了构造函数,成员函数的调用方法都是s.xx()

函数名称功能备注
构造函数产生或复制字符串
析构函数销毁字符串
=,assign赋以新值
swap交换两个字符串的内容
+=,append(),push_back()添加字符
insert()插入字符str.insert(1,s);在原串下标为1的字符前插入字符串s
erase()删除字符s.erase(beg,len);
clear()移除全部字符
resize()改变字符数量
replace()替换字符
+串联字符串
==,!=,<,<=,>,>=,compare()比较字符串内容
size(),length()返回字符数量这两个无区别
max_size()返回字符的最大可能个数
empty()判断字符串是否为空
capacity()返回重新分配之前的字符容量
reserve()保留内存以存储一定数量的字符
[],at()存取单一字符
>>,getline()从stream中读取某值
<<将值写入stream
copy()将内容复制为一个C-string
c_str()将内容以C-string形式返回
data()将内容以字符数组形式返回
substr()返回子字符串这个比较常用,s.substr(beg,len)
find()搜寻某子字符串或字符find(str,position)从位置position开始搜寻,返回str第一次出现的首字母的位置。
begin(),end()提供正向迭代器支持
rbegin(),rend()提供逆向迭代器支持
get_allocator()返回配置器

不会用看这俩:
string常用函数用法总结
string类及其成员函数汇总

Part.III 指针

Chap.I 指针存在的意义

有了指针,就有了自由访问内存空间的手段,不需要通过变量,就能对内存直接进行操作。通过指针,程序能访问的内存区域就不仅限于变量所占据的数据区域! 往往在写底层的,比较接近硬件的应用程序的时候要用到指针。有了指针,就可以做很多“出格”的事情了,比如:病毒的注入或者在别的应用程序存储空间里面杀病毒……

T * p;           //T可以是任何类型的名字,比如int,double
p   的类型:T *
*p  的类型: T    //*p 等价于存放在地址p 开始的sizeof(T)个字节
// "*" 称为间接引用运算符.
// "&"称为取地址运算符
  • 通过表达式 *p,可以读写从地址p开始的sizeof(T)个字节
  • 对于类型 T 的变量 x&x 表示变量x的地址(即指向 x 的地址)&x 的类型是 T *
  • 不同类型的指针,如果不经过强制类型转换,不能直接互相赋值。

Chap.II 指针的运算

  • 两个同类型的指针变量,可以比较大小
  • 两个同类型的指针变量,可以相减
T * p1,p2;
p1 - p2 =(地址p1 - 地址p2)/sizeof(T)

指针变量加减一个整数的结果还是指针

int n;
T * p;
p+n  //表示T * 类型的指针,指向地址p+n*sizeof(T);

指针可以用下标运算符[]进行运算

T * p;
int n;
p[n]=*(p+n);

Chap.III 空指针

  • 地址 0 不能访问。指向地址 0 的指针就是空指针
  • 可以用NULL关键字对任何类型的指针进行赋值。NULL实际上就是整数0,值为NULL的指针就是空指针。如:
int * pn=NULL;
char * pc=NULL;
int * p2=0;

指针可以作为条件表达式使用。如果指针的值为NULL,则相当于为假,值不为NULL,就相当于为真。

if(p)  <=>   if(p!=NULL)
if(!p)   <=>   if(p==NULL)

Chap.IV 数组与指针

  • 数组的名字就是一个指针,但它是一个常量,指向数组的起始地址,你不能让它指向别处,作为函数形参时,T * p和T p[]等价。

指针与二维数组
T a[M][N];

  • a[i](i是整数) 是一个一维数组
  • a[i]的类型是T *
  • sizeof(a[i])=sizeof(T) * N
  • a[i]指向的地址:数组a 的起始地址 +i*N*sizeof(T)

指向指针的指针
T **p;
p是指向指针的指针,p指向的地方应该存放着一个类型为 T *的指针 *p 的类型是T *

指针与字符串
字符串常量的类型是char *
字符数组名的类型是char *, 就是一个地址

Chap.V void 指针

void * p;
  • 可以用任何类型的指针对 void 指针进行赋值或初始化;
  • sizeof(void) 没有定义,所以对于void * 类型的指针p* p无定义

头文件 cstring 中声明:

void * memset(void *dest,int ch,int n);
//将从dest 开始的n 个字节,都设置成 ch .返回值是dest ch只有最低的字节起作用。
void * memcpy(void *dest, void *src,int n);
//将地址src开始的n个字节,拷贝到地址dest,返回值是dest
使用例子

下面是几个例子

// eg1:将szName的前10个字符,都设置成'a':
char szName[200]="";
memset(szName,'a',10);

// eg2:将数组内容全部设置为0:
int a[100];
memset(a,0,sizeof(a));

// eg3:将数组a1 的内容拷贝到a2 中去
int a1[10],a2[10];
memcpy(a2,a1,10*sizeof(int));

Chap.VI 函数指针

程序运行期间,每个函数都会占用一段连续的内存空间。而函数名就是该函数所占内存区域的起始地址(也称“入口地址”)。我们可以将函数的入口地址赋给一个指针变量,使该指针变量指向该函数。然后通过指针变量就可以调用这个函数。这种指向函数的指针变量称为“函数指针”
定义形式:

类型名(* 指针变量名)(参数类型1,参数类型2,……)

使用方法:

#include <cstdio>

void PrintMin(int a, int b)
{
	if (a < b) printf("%d", a);
	else printf("%d", b);
}
int main()
{
	void(*pf)(int, int);
	int x = 4, y = 4;
	pf = PrintMin;
	pf(x, y);
	return 0;
}

详细内容,传送门参上……
门 1
门 2

Part.IV 区别与转换

C++ 中涉及字符串的类型,如果大体分类的化可以只分为两类char *string。但细分的话,其实有很多种,下面列了一个表:

类型说明
char用单引号''引起来的一个字符,可以重新赋值
char []指针常量,可以理解为char * (const xx);其值(指向)不能更改;但是其指向目标(在内存中的区域)的内容可变。最后有一个 '\0'结束符作为字符串的结束标志。
char *指针变量,其值(指向)可以改变,可以通过它来更改指向区域的内容
const char *指针变量,其值(指向)可以改变,但是只能指向常量,不能通过它来更改指向区域的内容,通过别的或许可以。
char const *等价于const char *
char * const指针常量,其值(指向)不能更改;但是可以通过它来更改指向区域的内容
stringC++ 新增的一个类,用双引号""引起来的字符串,对其操作十分灵活。要引用头文件#include <string>
CString常用于MFC编程中,是属于MFC的类

Chap.I 区别

C++中用单引号''括起来的一个数字、字母或符号表示一个char,用双引号括起来的一串数字、字母或符号表示一个字符串。主要是关于char*, CString, string 之间的区别


  • char*是一个指向字符的指针,是一个内置类型。可以指向一个字符,也可以表示字符数组的首地址(首字符的地址)。我们更多的时候是用的它的第二的功能,来表示一个字符串,功能与字符串数组char ch[n]一样,表示字符串时,最后有一个 '\0'结束符作为字符串的结束标志。
  • stringC++标准库(STL)中的类型,它是定义的一个类,定义在<string>头文件中。里面包含了对字符串的各种常用操作,它较char*的优势是内容可以动态拓展,以及对字符串操作的方便快捷,用+号进行字符串的连接是最常用的操作。
  • CString常用于MFC编程中,是属于MFC的类,如从对话框中利用GetWindowText得到的字符串就是CString类型,CString定义在<afx.h>头文件中。CString(typedef CStringT> CString)为Visual C++中最常用的字符串类,继承自CSimpleStringT类,主要应用在MFC和ATL编程中,所以使用CString时要包含afx.h文件#include <afx.h>

从灵活度来说,string最灵活易用,其次是CStringchar*的拓展性和灵活性比较差。 一般来说在基于标准库开发时用string,在 MFC 和 ATL 编程时用CString

ps:关于string是否是STL中的一员众说纷纭,可以将它视为STL中的一员,但是也许在其他地方也可能说它不是STL中的一员。


另外,关于头文件的区别:

头文件描述
string.h旧的 C 头文件,对应的是基于char*的字符串处理函数;
string包装了stdC++头文件,对应的是新的string 类;
cstring对应于旧C 头文件的std 版本。

是这么个意思:一般C里带.h扩展名的库文件,比如iostream.h,在新标准后的C++标准库中都有一个不带.h扩展名(iostream)的与之相对应(有时加上c的前缀表示来自于C),区别除了后者的好多改进之外,还有一点就是后者的东东都塞进了std命名空间(namespace)中。

Chap.II 转换

关于三者之间的相互转换:

  • char *转换为stringstring s3 = string(ch);
  • string转换为char *const char *ch1 = str.c_str();
  • char *转换为CStringCString cStr2 = CString(ch);
  • CString转换为char * char* chs=cstr.getbuffer(0);
  • string转换为CStringCString cstr(s1.c_str());
  • CString转换为stringstr = LPCSTR(cstr4);

可以看到,他们之间的转换,是以char *作为桥梁的,更为详细的 C++ 数据类型转换可参看博文

在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

流浪猪头拯救地球

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

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

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

打赏作者

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

抵扣说明:

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

余额充值