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'
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,036评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,046评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,411评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,622评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,661评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,521评论 1 304
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,288评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,200评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,644评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,837评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,953评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,673评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,281评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,889评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,011评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,119评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,901评论 2 355

推荐阅读更多精彩内容