1.字符串
1.1 声明
- 语法
char 字符串变量名[字符数量];
char s[10];
1.2 初始化
- 语法
char 字符串变量名[字符数量] = {'字符1','字符 2',...,'\0'};
char s[5] = {'s','a','l','t','\0'};
字符串最后一位必须是\0
- 简化写法
char 字符串变量名[字符数量] = "字符串字面量";
char 字符串变量名[] = "字符串字面量";
char s[5] = "salt";
char s[] = "salt";
- 指针方式初始化
char* s = "salt";
1.3 输入输出
输入:scanf
.. 字符串变量名为该数组的首地址
输出:printf
..\0
scanf("%s",str);
printf("%s\n",str);
- 指定读取长度
scanf()
:读入一个单词直到空白字符(空格、回车、Tab)
%
与s
之间的数字表示最多允许输入的字符数,数字比字符串长度少1
char str[8];
scanf("%7s",str);
printf("%s\n",str);
1.4 访问字符
- 语法 字符串变量名[下标]
str[] = "salt";
str[2] = '0';
- 通过指针对字符串进行修改
#include <stdio.h>
int main () {
char s[] = "salt";
char* t;
t = s;
t[1] = '0';
printf("%s\n",s);
printf("%s\n",t);
s[2] = '9';
printf("%s\n",s);
printf("%s\n",t);
}
1.4 结果
1.5 遍历
- 通过长度进行遍历
//1. 通过长度进行遍历
for(int i=0;i<n;i++){
printf("%c ",str[i]);
}
- 未知长度进行遍历
//2. 未知长度进行遍历
for(int i=0;'\0' != str[i];i++){
printf("%c ",str[i]);
}
- 指针方式遍历
++
运算符的优先级高于*
解引用。str++
返回str
再对返回的str
进行*
解引用。
- 指针方式遍历
//3. 指针方式遍历
for(int i=0;'\0' != *(str+i);i++){
printf("%c\n",str[i]);
}
// 简化1
for(;'\0' != *str;str++){
printf("%c\n",str[i]);
}
// 简化2
while('\0' != *str){
printf("%c\n",*str++);
}
1.6 赋值
- 字符串不能直接进行赋值
- 1.遍历的方式赋值
char s[] = "salt";
char t[255];
for (int i=0;'\0' != s[i];i++){
t[i] = s[i];
}
- 2.函数
strcpy()
头文件:#include <string.h>
char s[] = "salt";
char t[255];
strcpy(t,s); // 将s中的内容复制到t中
- 注意事项
1.目标字符串的长度要大于等于源字符串的长度;
2.目标字符串结尾:'\0'
#include <stdio.h>
int main()
{
//char s[5] = {'s','a','l','t','\0'};
char s[] = "salt";
for(int i=0;i < 5;i++){
printf("%c ",s[i]);
}
printf("\n");
char temp[255];
scanf("%s",temp);
temp[2] = '0';
printf("%s\n",temp);
}
- 3.指针方式赋值
指针s和t指向相同的地址,赋值过程并没有产生新的字符串 - 指针不能反向赋值给字符串
#include <stdio.h>
int main () {
char s[] = "salt";
char* t;
t = s;
printf("s:%s :%p\n",s,s);
printf("t:%s :%p\n",t,t);
}
1.6 3 结果
1.7 字符串与函数
1.7.1 字符串传参
- 与数组类似,但不需要传递字符串长度
void PrintStr(char* s){
printf("%s\n",s);
}
1.7.2 字符串返回
- 字符串返回只能使用指针
char*
2. 练习
- 统计
输入字符串s
,打印出字符串s
的长度(不包含'\0'
)。
输入字符串s
和字符c
,打印出字符c
在字符串s
中出现的次数。
#include <stdio.h>
int GetLength(char* s){
int count = 0;
for(int i=0;'\0' != s[i];i++){
count++;
}
return count;
}
int main()
{
char s[256];
scanf("%s",s);
int len = GetLength(s);
printf("length:%d\n",len);
}
2.1(1) 结果
#include <stdio.h>
int GetCtimes(char* s,char c){
int count = 0;
for(int i=0;'\0' != s[i];i++){
if(s[i] == c) count++;
}
return count;
}
int main()
{
char s[256];
char c;
scanf("%s %c",s,&c);
int times = GetCtimes(s,c);
printf("times:%d\n",times);
}
2.1(2) 结果
- 查找
输入字符串s
和字符c
,打印出c
在字符串s
中的第一次出现的位置(第一个字符位置为0
,s
不包含c
返回-1
)。
输入字符串s
和字符c
,打印出c
在字符串s
中的最后一次出现的位置(第一个字符位置为0
,s
不包含c
返回-1
)。
#include <stdio.h>
int GetFirstPosition(char* s,char c){
int times = -1;
for(int i=0;'\0' != s[i];i++){
if(s[i] == c){
times = i;
break;
}
}
return times;
}
int GetLastPosition(char* s,char c){
int times = -1;
for(int i=0;'\0' != s[i];i++){
if(s[i] == c){
times = i;
}
}
return times;
}
int main()
{
char s[256];
char c;
scanf("%s %c",s,&c);
int times = GetFirstPosition(s,c);
printf("The first position is %d.\n",times);
int times1 = GetLastPosition(s,c);
printf("The last position is %d.\n",times1);
}
2.2 结果一
2.2 结果二
- 替换
输入字符串s
、数字n
和字符c
,用字符c
替换字符串s
中n
位置的字符,打印出替换结果。
输入字符串s
、字符c1
和字符c2
,用字符c2
替换字符串s
中c1
,打印出替换结果。
#include <stdio.h>
void Replace(char* s,char c1,char c2){
for(int i=0;'\0' != s[i];i++){
if(s[i] == c1){
s[i] = c2;
}
}
}
int main(){
char s[256];
char c;
int n;
scanf("%s %d %c",s,&n,&c);
printf("%s.\n",s);
s[n] = c;
printf("%s.\n",s);
getchar();
char c1,c2;
scanf("%c %c",&c1,&c2);
Replace(s,c1,c2);
printf("%s.\n",s);
}
2.3 结果
- 逆序/反序
输入字符串s
,打印出字符串s
的反序。LeetCode 344. 反转字符串
输入字符串s
,判断字符串是否是回文。
#include <stdio.h>
int GetLength(char* s){
int count = 0;
for(int i=0;'\0' != s[i];i++){
count++;
}
return count;
}
// 对折
// 4个元素:交换2次 0 1 2 3 length/2 = 2
// 5个元素:交换两次
void ReverseOrder(int length,char* s){
char temp;
for(int i=0;i < length/2;i++){
temp = s[i];
s[i] = s[length-1-i];
s[length-1-i] = temp;
}
}
int main(){
char s[256];
scanf("%s",s);
printf("%s\n",s);
ReverseOrder(GetLength(s),s);
printf("%s\n",s);
}
2.4 结果一
2.4 结果二
- 输入一个年月日时分秒组成的数字,按照XXXX年XX月XX日XX时XX分XX秒打印出来。例如:输入20190311180301,打印出2019年3月11日18时3分1秒。
#include <stdio.h>
void PrintfStr(int begin_num,int length,char* s){
for(int i=begin_num;i<begin_num+length;i++){
printf("%c",s[i]);
}
}
int main(){
char s[15];
scanf("%s",s);
printf("%s\n",s);
PrintfStr(0,4,s);
printf("年");
PrintfStr(4,2,s);
printf("月");
PrintfStr(6,2,s);
printf("日");
PrintfStr(8,2,s);
printf("时");
PrintfStr(10,2,s);
printf("分");
PrintfStr(12,2,s);
printf("秒\n");
}
scanf()
用法
#include <stdio.h>
int main()
{
int year,month,day,hour,min,sec;
scanf("%4d%2d%2d%2d%2d%2d",&year,&month,&day,&hour,&min,&sec);
printf("%d年%02d月%02d日%02d时%02d分%02d秒\n",year,month,day,hour,min,sec);
}
2.5 结果
\
- 交换
实现字符串交换函数void swap(char* s1,char* s2)
// 只适用于两个长度相同的字符串
void Swap(char* s1,char* s2){
// 不会改变外界值 需要传入二维指针
/*
char* t = s1;
s1 = s2;
s2 = t;
*/
for(int i=0;'\0' != s1[i];i++){
char t = s1[i];
s1[i] = s2[i];
s2[i] = t;
}
}
7.拼接
实现字符串拼接函数char* stract(char* s1,char* s2)
// 将s2拼接到s1后面
char* Strcat(char* s1,char*s2){
char* res = s1;
// 找到s1的‘\0’位置
while('\0' != *s1) s1++;
while('\0' != *s2){
/*
*s1 = *s2
s1++;
s2++;
*/
// a++ 返回a b++ 返回b -> *a = *b -> a+1 b+1
*s1++ = *s2++;
}
*s1 = '\0';
return res;
}
8.拷贝
实现字符串拷贝函数char* strcpy(char* s1,char* s2)
// 将s2拷贝到s1
char* Strcpy(char* s1,char* s2){
char* res = s1;
while('\0' != *s2){
*s1++ = *s2++;
}
*s1 = '\0';
return res;
}
9.比较
实现字符串相等判断函数bool strcmp(char* s1,char* s2)
// 判断两个字符串是否完全相等
bool Strcmp(char* s1,char* s2){
while(*s1++ == *s2++){
if('\0' == *s1 && '\0' == *s2){
return true;
}
}
return false;
}
- 6-9 总:
#include <stdio.h>
#include <stdbool.h>
// 只适用于两个长度相同的字符串
void Swap(char* s1,char* s2){
// 不会改变外界值 需要传入二维指针
/*
char* t = s1;
s1 = s2;
s2 = t;
*/
for(int i=0;'\0' != s1[i];i++){
char t = s1[i];
s1[i] = s2[i];
s2[i] = t;
}
}
// 将s2拼接到s1后面
char* Strcat(char* s1,char*s2){
char* res = s1;
// 找到s1的‘\0’位置
while('\0' != *s1) s1++;
while('\0' != *s2){
/*
*s1 = *s2
s1++;
s2++;
*/
// a++ 返回a b++ 返回b -> *a = *b -> a+1 b+1
*s1++ = *s2++;
}
*s1 = '\0';
return res;
}
// 将s2拷贝到s1
char* Strcpy(char* s1,char* s2){
char* res = s1;
while('\0' != *s2){
*s1++ = *s2++;
}
*s1 = '\0';
return res;
}
// 判断两个字符串是否完全相等
bool Strcmp(char* s1,char* s2){
while(*s1++ == *s2++){
if('\0' == *s1 && '\0' == *s2){
return true;
}
}
return false;
}
int main () {
char s1[] = "salt";
char s2[] = "star";
printf("s1:%s s2:%s\n",s1,s2);
printf("----------------------------------swap----------------------------------\n");
Swap(s1,s2);
printf("s1:%s s2:%s\n",s1,s2);
printf("----------------------------------stract---------------------------------\n");
char* strcat_res = Strcat(s1,s2);
printf("strcat_res:%s\n",strcat_res);
// char s[14] = "sugar";
// printf("s3:%s\n",Strcat(s,Strcat(s1,s2)));
printf("----------------------------------strcpy---------------------------------\n");
char a[6];
char* b = "sugar";
printf("a:%s\n",Strcpy(a,b));
printf("----------------------------------strcmp---------------------------------\n");
char p1[] = "salt";
char p2[] = "salt";
char p3[] = "star";
char p4[] = "sugar";
if(Strcmp(p1,p2)){
printf("p1 = p2\n");
}else{
printf("p1 != p2\n");
}
if(Strcmp(p1,p3)){
printf("p1 = p3\n");
}else{
printf("p1 != p3\n");
}
if(Strcmp(p1,p4)){
printf("p1 = p4\n");
}else{
printf("p1 != p4\n");
}
}
6-9 总 结果
3. 字符串指针
- 初始化
- 用字面量初始化
- 用字面量初始化的字符串指针不能修改
-
char* s
不能用{'s','a','l','t','\0'}
方式初始化
char* s ="salt";
- 可以用字符数组赋值给字符指针
char s[] = "salt";
char* ptr = s;
- 字符数组本质是数组,
char s[] = "salt";
可以看做以下代码简写:
char s[] = {'s','a','l','t','\0'};
- 字符串指针本质是指针,
char *s = "salr";
可以看作以下代码简写:
const char t[] = "salt";
cahr* s = t;
3.1 sizeof()
与strlen()
strlen()
头文件:#include<string.h>
.. 返回字符串\0
前的字符个数
#include <stdio.h>
#include <string.h>
int main(){
// 字符数组
char s[] = "salt";
// 字符串指针
char* ptr = "salt";
printf("sizeof(s): %ld\n",sizeof(s));
printf("sizeof(ptr): %ld\n",sizeof(ptr));
printf("strlen(s): %ld\n",strlen(s));
printf("strlen(ptr): %ld\n",strlen(ptr));
}
3.1 结果
s
为字符数组:
sizeof(s)
获取s
的大小(char
:1) : 1*5 = 5
strlen(s)
:salt
:4ptr
为字符串指针
sizeof(ptr)
获取ptr
大小,ptr
本身为指针,故大小为:8
strlen(ptr)
:salt
:4
3.2 替换字符
- 修改字符数组
#include <stdio.h>
#include <string.h>
int main(){
// 字符数组
char s[] = "salt";
// 字符串指针
char* ptr = "salt";
printf("s: %s\n",s);
s[2] = '0';
printf("s: %s\n",s);
}
3.2(1) 结果
- 不能修改字面量初始化的字符串指针
#include <stdio.h>
#include <string.h>
int main(){
// 字符数组
char s[] = "salt";
// 字符串指针
char* ptr = "salt";
printf("s: %s\n",s);
s[2] = '0';
printf("s: %s\n",s);
printf("ptr: %s\n",ptr);
*(ptr+2) = '0';
printf("ptr: %s\n",ptr);
}
并不能打印出修改后的字符串
3.2(2) 结果
- 修改指向字符数组的字符串指针
#include <stdio.h>
#include <string.h>
int main(){
char s[] = "salt";
char* ptr = s;
*(ptr+2) = '0';
printf("s: %s\n",s);
printf("ptr: %s\n",ptr);
}
3.2(3) 结果
- 修改地址
字符串指针能修改地址
字符数组不能修改地址
#include <stdio.h>
int main(){
char* p = "Hello";
p = "World";
char arr[] = "Hello";
// arr = "World";
printf("p: %s\n",p);
printf("arr: %s\n",arr);
}
选择:
1.如果需要构造字符串使用数组;如果需要处理字符串使用指针(指向字符数组的指针);
2.字符串不需要修改使用字符串字面量初始化的字符串指针;
3.字符串需要修改使用字符串字面量初始化的字符数组。
4.字符串const
1.const
字符数组
- 无法修改
const
字符数组:read-only
- 指向
const
字符数组的字符串指针
#include <stdio.h>
#include <string.h>
int main(){
const char arr[] = "Hello World";
char* ptr = arr;
*ptr = 'h';
*(ptr+6) = 'w';
printf("%s\n",ptr);
}
4.2 结果
能否被修改是指指针指向的值能否被修改。
const
的限制只针对定义为const
的变量。此程序定义的字符串指针并不是const
类型。
5.字符串函数
6.0
、\0
与'\0'
-
'\0'
表示字符串的结束,不属于字符串的一部分。计算字符串长度时不包含'\0'
。