C:字符串

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. 通过长度进行遍历
//1. 通过长度进行遍历
for(int i=0;i<n;i++){
  printf("%c ",str[i]);
}
    1. 未知长度进行遍历
//2. 未知长度进行遍历
for(int i=0;'\0' != str[i];i++){
  printf("%c ",str[i]);
}
    1. 指针方式遍历
      ++运算符的优先级高于*解引用。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. 练习

  1. 统计
    输入字符串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) 结果
  1. 查找
    输入字符串s和字符c,打印出c在字符串s中的第一次出现的位置(第一个字符位置为0s不包含c返回-1)。
    输入字符串s和字符c,打印出c在字符串s中的最后一次出现的位置(第一个字符位置为0s不包含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 结果二
  1. 替换
    输入字符串s、数字n和字符c ,用字符c替换字符串sn位置的字符,打印出替换结果。
    输入字符串s、字符c1和字符c2 ,用字符c2替换字符串sc1,打印出替换结果。
#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 结果
  1. 逆序/反序
    输入字符串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 结果二
  1. 输入一个年月日时分秒组成的数字,按照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 结果

\

  1. 交换
    实现字符串交换函数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:4

  • ptr为字符串指针
    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
  1. 指向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'
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容