C/C++字符和字符串

1、字符和字符串的定义(字符用char,字符串用string

字符定义:在计算机里,所有数据必须以数字的形式表示,字符也不例外。根据 ASCII 码表的规定,每个字符一个数字表示,而这个数字在 0-127 之间。在 C/C++里char/short/int 都可以表示整数,由于字符的数值范围较小,我们选用 char 型变量来代表字符

如:

char c = 'aa';
char c= ' 1   ';

这些都是错误的字符表示方法,应为字符对应的单引号中只能出现一个字母,并且不能是汉字,不能有多余的空格出现 

\ddd 代表的是一个1到3位的八进制数表示的字符。 八进制数101,等于十进制数的65,而65是A的ASCII码,所以如果按字符打印,会打印对应的字符,也就是打印字符A

选项解释:

字符常量只有一个字符 a错

b是特殊字符叫转义字符 b对

c是字符串常量

d 无意义

 

字符串定义: (1) 以0结束 ;(2) 所有字符是可打印字符

如:

有一个数组a,
char a[6] = {'a', 'b',  'c', 'd' , 0 };a也可以称为一个字符串,以0结束,并且所有字符可打印,这里注意0是没有加单引号的

 

char a[4] = {'a', 'b', 'c', 'd'};
printf("%s", a)由于字符串不是以0结束,所以打印时,后面会有一些乱码字符。

 

int a[5] = {'a', 'b', 'c', 'd', 0};字符串是指一串字符,元素类型必须是char类型。这里的数组a的元素类型是int。

 

①字符的输出%c

②字符串的输出%s

char str[6] = "hello";
printf("string: %s \n", str);

③字符串的结束符

字符串的末尾必须为一个数字 0 作为结束符,它是一个字符串结束的标识。如果一串字母不以 0 结束,那它就不算是一个有效的字符串。

下面定义了一个字符数组,前 3 个字符是 b,a,d,但末尾并不是 0,那它不是一个有
效的字符串,在用 printf 输出的时候会有问题:
char buf [4] = { 'b' , 'a' , 'd' , -1 };
printf("Got: %s \n", buf);
控制台输出时,会打印出一些乱码字符

而如下的定义就是可行的,末尾为0

由于str[3] 是0,第一个输出abc 
第二个输出def
str[7]是0,所以直接结束 ,第三个输出为空

 

2、strlen()计算出字符串的长度(使用length函数)

字符名称.length()

 

3、字符串对应的路径输出(\和"之前都必须加上转义符\)

用printf 打印输出以下文本:文件路径: "e:\cprojects\example\test.c"
printf("文件路径: \"e:\\cprojects\\example\\test.c\"");

注意,\ 和 " 均需要转义,\和"之前都必须加上转义符\

这也解释了为什么定义文件名字符串的时候会出现两个斜杠的原因:

 如下:\0的应用

 

4、字符串数组(依次将字符串中的每个字符存入数组中)

char name[10] = "shaofa";

printf("%d, %d, %d \n", name[5], name[6], name[7]);
数组name,初始化为 's' 'h' 'a' 'o' 'f' 'a' 0 0 0 0
name[5] 为 'a' ,即97
name[6] 和 name[7] 为0

字符串赋值给数组,定义为char,将每个字符依次存入数组中

输出是%d,输出字符对应的ASCII码

 ①字符串数组的赋值(用数组存储字符串和用指针存储字符串)

用数组存储字符串

char name[10] = "shaofa";
name = "shaodong";

上面用法错误,数组的初试化可以直接用等号赋值,但是修改数组不能直接直接将字符串赋值给数组名,如果想修改name里的内容,可以用strcpy_s() 函数。但是可以定义两个字符串数组,用于赋值。

#include <stdio.h>
int mian()
{
    char src[]="hello";
    char dst[128];
    int i=0;
    while(1)
    {
        dst[i]=src[i];
        if(src[i]==0)
            break;
        i++;
    }
    printf("%s",dst);
    return 0;
}

因为字符串中的每一个字符挨个复制到目标缓冲区,所以每一个缓冲区中的类型为char 

可以通过打印字符串数组名输出字符串

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

int main()
{
	char name[10] = "shaofa";
	strcpy_s(name, 10, "shaodong"); // 修改数组name的内容

	getchar();
	return 0;
}

 strcpy函数中只有两个参数,一个是原数组一个是目标数组,而strcpy_s第二个参数为源目标数组的长度

char* buf = (char*) malloc (128);
buf = "abc";
buf[0] = 'h';

 上面用法错误,需要通过函数赋值

char* buf = (char*) malloc (128);
strcpy(buf, "abc");  // 这才是字符串的拷贝,用strcpy把"abc"4个字节拷贝到目标缓冲区
buf[0] = 'h';

由于malloc申请的是缓冲区,返回值为申请地内存的首地址,所以用的指针

指针存储字符串

浅拷贝:指针赋值,连个指针指向同一个字符串对象

char* p1="hello,world";
char* p2=p1;

地址给地址,前面加了*号 

字符串指针和字符串数组都是用的char

深拷贝:申请一块相同大小的内存,把字符串内容复制到内存中

char* p2=(char*)malloc(strlen(p1)+1);
strcpy(p2,p1);

通过指针变量也能统计指针字符串的长度 

②数组长度必须大于字符串长度(只能多,不能少)

char str[4] = "shao";
	printf("值为: %s \n", str);

 数组太小,数组长度至少字符串长度+1。此处,字符串 "shao" 长度为4,所以数组长度至少为5。否则,末尾为0作为结束标识,它就不是一个合格的字符串,上述打印中会有乱码。

③字符数组名+整数

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

int main()
{
	char buf[] = "helloworld";
	int n1 = strlen(buf);
	int n2 = strlen(buf + 4);
	buf[0] = 0;
	int n3 = strlen(buf);
	printf("%d, %d, %d \n", n1, n2, n3);
	return 0;
}

n1,n2,n3值分别为10, 6, 0 字符串长度是指:从第一个字符开始,到结束符0,中间字符的个数。buf+4指向第一个字母o。 如果buf[0]为0,即意味着第一个字符就是结束符,所以此时字符串长度为0

 

5、字符串操作

①截取(取出文件名的前缀和后缀)

当文件名不确定时长度只能此种方法,第二个参数对应的是截取 结束的地方

#include <string>
#include <iostream>
 
using namespace std;
 
int main()
{
		string name1 = "/a/b/c/v/zhiodfh.jpg";
		int pos1 = name1.find_last_of('/');
		string name2 = name1.substr(pos1 + 1);
		cout << "pos1:" << pos1 << endl;
		cout << "文件名:" << name2 << endl;
		int pos2 = name2.find('.');
		string name3 = name2.substr(0, pos2);
		cout << "前缀:" << name3 << endl;
		int len = name1.length();
		cout << "后缀:" << name2.substr(pos2+1,len) << endl;//<<前后必须加空格
}

头文件必须是<string>和<iostream>,用.h会报错

统计字符串的长度,直接用name.length()

 

②分割

分割第一次取出192,分割第二次取出168.0.1 

将字符串按照逗号分隔开

一个逗号,直接将逗号赋值为空格,记录每一段的起始地址

int main()
{
    char str[]="hello,world";
    str[5]=0;
    char* part1=str;
    char* part2=str+6;
    printg("%s",part0);
    printg("%s",part1);
    return 0;
}

字符数组直接赋值给指针

 

 

③字符串拼接 

方法1:+ 号拼接字符串

方法:2: 使用函数strcat()

#include <stdio.h>
#include<string.h>
int mian()
{    
    char a[128]="hello";
    char b[]="world";
    strcat(a,b);
    printf("%s",a);
}

将字符串拼接到a上,所以输出内容为a

与方法1中不同的是这里定义的数组

 

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

int main()
{
	int maxsize = 32;
	char* buf = (char*)malloc(maxsize);
	buf[0] = 0;
	
	while(1)
	{
		// 获取一行
		char line[64] = {0};
		gets(line);

		// 检查如是exit时,退出
		if(strcmp(line, "exit") == 0)
		{
			break;
		}

		// 检测缓冲区是否够大
		int linesize = strlen(line);
		int size = strlen(buf);
		if(size + linesize > maxsize - 1) // 最多乘放maxsize-1个字节
		{
			// 申请一个更大的buffer
			maxsize += 32;
			char* bufnew = (char*)malloc(maxsize);
			bufnew[0] = 0;

			// 将旧buffer中的字符串拷贝过来
			strcpy(bufnew, buf);
			size = strlen(bufnew);

			// 扔掉旧的buffer
			free(buf);
			buf = bufnew;

			printf("*** 申请更大的缓冲区: %d ***\n", maxsize);
		}

		// 拼接buffer
		strcat(buf, line);

	}

	printf("-------- result -----------\n");
	printf(buf);

	// 释放buffer
	if(buf) free(buf);
	return 0;
}

字符串的多行输入,while(1)中使用gets函数

一定要判断字符串数组的长度和分配的内存的大小关系,字符串长度比内存还大时就需要重新分配内存,释放掉原有内存

字符串拼接使用strcat函数,第一个参数可以是空的指针数组(返回数组的首地址)

 

 

④从字符串中取出指定字符(strchr函数),字符串中查找字符

char* s="LiMing";
char* p=strchr(s,'M');
if(p!=NULL)
{
    printf("%s\n",p)
}

返回值p指向了字符'M'的地址(返回第一处M出现的位置),获取目标字符的索引可以通过地址操作实现:

int pos=(int)(p-s)

⑤字符串中查找子字符串(strstr函数)

char* s="LiMing is doing homework";
char* p=strchr(s,'M');
if(p!=NULL)
{
    printf("%s\n",p)
}

同样可以返回下标索引,通过for循环取出需要的子串(或者通过substr(index,index+子串长度)取出子串)

⑥字符串比较(strcmp函数)

strcmp(a,b)

当a,b字符串的对应位置都相同时,返回0

a<b返回-1,a>b返回1

如果字符串在第二个字符分出高低,剩余字符串不再比较

如:“Jack”和“John”比较时,‘a’<'o',所以“Jack”<“John”

 

⑦字符串删除

普通方法:通过for循环移动字符串中的字符

当要删除字符串中有多个相同字符且要删除时,需要多次移动,操作复杂。通过新建一个字符串对象

char* erase(const char* text,char del)//传入参数为const char* text不是* test,形参一定要加上类型
{
	int len = strlen(text);
	char* copy=(char*)malloc(len+1);//新对象的定义直接分配内存,不需要char res[] = {0}
	int count = 0;
	for (int i = 0;i < len;i++)
	{
		char ch = text[i];//赋值时记住定义类型
		if (ch != del)
		{
			copy[count] = ch;//变量是count,不是i
			count++;
		}
	}
	copy[count] = 0;//这里不需要count+1,因为上一句是后置加
	return copy;
}

int main()
{
	char input[128] = "China is a great country with a long history";//直接定义字符数组,定义字符串const char* 
	printf("%s\n", input);
	char* copy = erase(input, 'a');
	printf("%s", copy);
	free(copy);
}

 

字符串中加空格

 利用数组的思想实现(字符串的定义为什么用const char* a?)

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

void print_string(const char* str)
{
    int len = strlen(str);
    for (int i = 0; i < len; i++)
    {
        if (str[i] == 0)
            break;
        printf("%c ", str[i]);
    }
}

int main()
{
    const char* a = "abcd";
    print_string(a);
    return 0;
}

从指针后移的角度考虑(自己)

void print_string(const char* str)
{
	int count = 0;
	int len = strlen(str);
	while (*str)//第一次*str为a
	{
		printf("%c", *str);//这里打印一定要加上*

		count++;
		//这里一定不能取等号
		if (count < len)//这里不能小于strlen(str),由于str是指针,每次str+1后,str往后移,从而使strlen长度发生变化
			printf(" ");
		else
			break;

		str = str + 1;//让指针一直往后指
	}
}
int main()
{
	print_string("abcd");
    return 0;
}

注意:注释的地方是自己之前理解有问题的地方

 

字符串中删除空格

注意:

①空格表示方法: \t,\t前一定空了一个空格

②在控制台打印string类型的字符串时必须调用c_str()函数,如果不调用程序会报错,因此使用

printf("%s",str.substr(pos1,pos2))的语法是错误的

必须先给一个新的string字符串,然后再通过新的字符串调用c_str()函数来打印

 

特殊字符转换成表情符

数组思想实现

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

void translate(const char* str)
{
    int len = strlen(str);
    for (int i = 0; i < len; i++)
    {
        if (str[i] == '/'&& str[i+1] == 's')
        {
            printf("^_^");
            i++;
        }
        else if (str[i]=='/'&&str[i+1] =='c')
        {
            printf("T_T");
            i++;
        }
        else if (str[i]=='/'&& str[i+1] == 'f')
        {
            printf("@_@");
            i++;
        }
        else
        {
            printf("%c", str[i]);
        }
    }

}

int main()
{
    const char* a = "Thank you/s I will try my best/c";
    translate(a);
    return 0;
}

同样可以用指针实现(自己在IDE中试一下,和上题解法二的思路相同)

 

去掉字符串前后空格

直接使用字符串的类find_first_not_of(“ ”),从左/右开始找到第一个不是括号中的字符串

使用字符串的类erase删除对应范围的字符

//去掉首尾空格
string ClearHeadTailSpace(string &str)
{
	if (str.empty())
	{
		return str;
	}
	int a = str.find_first_not_of(" ");

	str.erase(0, str.find_first_not_of(" "));
	str.erase(str.find_last_not_of(" ") + 1);
	return str;
}

int main()
{
	string str = "  123   456  789   ";


	cout << ClearHeadTailSpace(str) << endl;
    return 0;
}

数字转汉字

方法:不要用if判断是否是1-9,直接定义一个汉字数组,用数字作为汉字数组的下标

 

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值