字符串基本操作

字符数组初始化方法

int main()

{

    //1 {}号法 初始化列表

    //数组初始化有2种方法 默认元素个数、指定元素个数

    char buf1[] = { 'a', 'b', 'c', 'd', 'e' };    //若没有指定长度,默认数组长度即为参数个数

                                                //若指定长度,指定长度小于参数个数→报错;buf长度多于初始化个数,会自动在后面补充零。

    char buf2[6] = { 'a', 'b', 'c', 'd', 'e' };

    char buf3[6] = { 'a', 'b', 'c', 'd', 'e' };

    //char buf4[5] = {'a', 'b', 'c', 'd', 'e'};

    printf("buf3:%s", buf3);

    system("pause");

}

//在C语言中使用字符数组来模拟字符串

//C语言中的字符串是以'\0'结束的字符数组

//C语言中的字符串可以分配于栈空间,堆空间或者只读存储区

int main12()

{

    //1 用字符串来初始化数组

    char buf2[] = { 'a', 'b','c','d','\0' };

    //2 字符串常量初始化一个字符数组

    char buf3[] = { "abcde" };

    char buf4[] = "abcde";

    char buf5[100] = "abcde";

 

    printf(" strlen(buf5) :%d \n", strlen(buf5));

    printf(" sizeof(buf4) :%d \n", sizeof(buf5));

    printf(" sizeof(buf4) :%d \n", sizeof(buf4));

}

sizeof与strlen的区别:

strlen()求字符串的长度,注意字符串的长度不包含\0

sizeof(类型)字符串类型的大小,包括\0;

数组法和指针法操作字符串

03 字符串操作:数组法,下标法

字符数组名,是个指针,是个常量指针;

字符数组名,代表字符数组首元素的地址,不代表整个数组的。

如果代表这个数组,那需要数组数据类型的知识!

//字符串操作方法 数组下标法 指针法

int main()

{

    int i = 0;

    char buf[100] = "abcde";

    char *p = NULL;

 

    //下标法

    for (i = 0; i<100; i++)

    {

        printf("%c", buf5[i]);

    }

    printf("\n");

 

    //指针法1

    for (i = 0; i<100; i++)

    {

        printf("%c", *(buf5 + i));

    }

    //buf5是个指针,是个常量指针

 

    //指针法2

    printf("\n");

    p = buf5;

    for (i = 0; i<100; i++)

    {

        printf("%c", *(p + i));

    }

    //buf5是个指针,是个常量指针

}

推演过程为:i变0+i, 去[]号加*号

//其实本质:指针*p间接寻址,操作内存;

//[]:其实是编译器为我们做了*p操作而已

3.2字符串做函数参数

深入理解指针的关键是什么?

注意

指针和数组的巨大区别

char *p = "abcdefg";

char *buf = "abcdefg";

一维字符串内存模型:两种

void copy_str01(char *from, char *to)

{

    for (; *from != '\0'; from++, to++)

    {

        *to = *from;

    }

    *to = '\0';

}

 

void copy_str02(char *from, char *to)

{

    while (*from != '\0')

    {

        *to++ = *from++;

    }

    *to = '\0';

}

 

void copy_str03(char *from, char *to)

{

    while ((*to = *from) != '\0')//不用在后面添加'\0'因为\0已经复制过去了;复制\0之后才判断不满足条件从而退出循环

    {

        to++;

        from++;

    }

}

 

void copy_str04(char *from, char *to)

{

    while ((*to++ = *from++) != '\0')

    {

        ;

    }

}

 

int copy_str05_good(const
char *from, char *to)//就这个最好,因为考虑到了指针本身为空(野指针)的情况

{

    if (from == NULL || to == NULL)

    {

        printf("func copy_str05_good() err. (from==NULL || to==NULL)\n");

        return -1;

    }

 

    while ((*to++ = *from++) != '\0')

    {

        ;

    }

    return 0;

}

典型错误知多少

char *str_cnct(char *x, char* y) /*简化算法*/

{

    char str3[80];

    char *z = str3;     /*指针z指向数组str3*/

    while (*z++ = *x++);

    z--;     /*去掉串尾结束标志*/

    while (*z++ = *y++);

    z = str3;         /*将str3地址赋给指针变量z*/

    return(z);

}

语法没问题,但是逻辑有错,错在没有规避"下级的数据不能用于上级"的错误。

修改字符常量结果会如何

char *p = "abcdefg";

Modify p[1] = '1';

段错误!

04字符串操作易错

//你往哪里输入数据

int main()

{

    char buf[2000];

    char *p = NULL;

    p = buf;

    printf("\n请输入一个字符串:");

    scanf("%s", p);//野指针

    printf("%s", p);

 

    getchar();

    getchar();

    return 0;

}

3.3库函数api

快速的上手api是一种能力!

建立正确的程序运行示意图,(内存四区及函数调用堆栈图)是根本保障!!

#include
<stdio.h>

#include
<string.h>

 

int main1()

{

    char buf1[100];

    char buf2[200];

    strcpy(buf1, "111");//将后面的字符串复制到前面的缓存中

    printf("%s", strcat(buf1, "222"));

    getchar();

    return 0;

}

 

int main2()

{

    char *string1 = "1234567890";

    char *string2 = "747DC8";

    int length;

    //在字符str1中查找,与str2中任意字符有公共交集的个数

    length = strcspn(string1, string2);

    printf("Character where strings intersect is at position %d\n", length);//len=3

 

    getchar();

    return 0;

}

 

//strnset函数: 将字符串的前n个字符设置为指定字符

//测试程序修改如下

int main3()

{

    char string[] = "abcdefghijklmnopqrstuvwxyz";

    char letter = 'x';

    printf("string before strnset: %s\n", string);

    strnset(string, letter, 13);

    printf("string after strnset: %s\n", string);

    getchar();

    return 0;

}

 

int main4()

{

    char *string1 = "abcdefghijklmnopqrstuvwxyz";

    char *string2 = "onm";

    char *ptr;

    ptr = strpbrk(string1, string2); //strpbrk()函数检索两个字符串中首个相同字符的位置

    if (ptr)

        printf("strpbrk found first character: %c\n", *ptr);

    else

        printf("strpbrk didn't find character in set\n");

    getchar();

    return 0;

 

}

 

int main5()

{

    char input[16] = "abc,d";

    char *p;

    /* strtok places a NULL terminator

    in front of the token, if found */

    p = strtok(input, ",");

    if (p) printf("%s\n", p);

    /* A second call to strtok using a NULL

    as the first parameter returns a pointer

    to the character following the token */

    p = strtok(NULL, ",");

    if (p) printf("%s\n", p);

 

    getchar();

    return 0;

}

 

//典型的状态函数

int main()

{

    char str[] = "now # is the time for all # good men to come to the # aid of their country";

    //char delims[] = "#";

    char *delims = "#";

    char *result = NULL;

    result = strtok(str, delims);

    while (result != NULL) {

        printf("result is \"%s\"\n", result);

        result = strtok(NULL, delims);

    }

    printf("----------==========----------\n");

    printf("%s", str);

 

    getchar();

 

    return 0;

}

3.4字符串相关一级指针内存模型

void main()

{

    char buf[20]= "aaaa";

    char buf2[] = "bbbb";

    char *p1 = "111111";

    char *p2 = malloc(100); strcpy(p2, "3333");

 

    system("pause");

    return ;

}

字符串反转模型

 

3.6一级指针(char *)易错模型分析

char *(字符串)做函数参数出错模型分析

建立一个思想:是主调函数分配内存,还是被调用函数分配内存;

void copy_str21(char *from, char *to)

{

 

    if (*NULL = '\0' || *to!='\0')

    {

        Printf("func copy_str21() err\n");

return;

    }

 

 

    for (; *from!='\0'; from++, to++)

    {

        *to = *from;

    }

    *to = '\0';

}

//字符串逆序

int main()

{

    //char p[1024] ={0};

char *p ={0}; p = NULL;

 

    char to[100];

    copy_str21(p, to); 

C语言中没有你不知道的,只有你不会调

Java语言中没有你不会调的,只有你不知道

不断修改内存指针变量

 

02越界

越界 语法级别的越界

char buf[3] = "abc";

03不断修改指针变量的值

越界

void copy_str_err(char *from, char *to)

{

    for (; *from != '\0'; from++, to++)

    {

        *to = *from;

    }

    *to = '\0';

    printf("to:%s", to);

    printf("from:%s", from);

}

 

04你向外面传递什么

1、临时str3内存空间

// char *str_cnct(x,y) /*简化算法*/

//     char *x,*y;

char *str_cnct(char *x, char* y) /*简化算法*/

{

    char str3[80];

    char *z = str3;     /*指针z指向数组str3*/

    while (*z++ = *x++);

    z--;     /*去掉串尾结束标志*/

    while (*z++ = *y++);

    z = str3;         /*将str3地址赋给指针变量z*/

    return(z);

}

2、经验要学习

while (*z++ = *x++);

z--;     /*去掉串尾结束标志*/

char *str_cnct(char *x, char* y) /*简化算法*/

{

    char * str3 = (char *)malloc(80)

        char *z = str3;     /*指针z指向数组str3*/

    while (*z++ = *x++);

    z--;     /*去掉串尾结束标志*/

    while (*z++ = *y++);

    z = str3;         /*将str3地址赋给指针变量z*/

    return(z);

}

char *str_cnct(char *x, char* y) /*简化算法*/

{

    If(x == NULL)

    {

        Return NULL;

    }

    char * str3 = (char *)malloc(80)

        char *z = str3;     /*指针z指向数组str3*/

    while (*z++ = *x++);

    z--;     /*去掉串尾结束标志*/

    while (*z++ = *y++);

    z = str3;         /*将str3地址赋给指针变量z*/ note:

    return(z);

 

}

Main()

{

    Char *p = str_cnct("abcd", "ddeee");

    If(p != NULL) { Free(p); p = NULL }//yezhizhen

}

int getKeyByValude(char *keyvaluebuf, char *keybuf, char *valuebuf, int * valuebuflen)

{

    int result = 0;

    char *getbuf = new
char[100];

    memset(getbuf, 0, sizeof(getbuf));

 

    char *trimbuf = new
char[100];

    memset(trimbuf, 0, sizeof(trimbuf));

 

    int destlen = strlen(keyvaluebuf);

 

    if (keybuf == NULL || keyvaluebuf == NULL || valuebuf == NULL/* || valuebuflen == NULL*/)

    {

        result = -1;

        return result;

    }

 

    if (strstr(keyvaluebuf, keybuf) == NULL)// strstr函数返回一个指针,它指向字符串str2 首次出现于字符串str1中的位置,如果没有找到,返回NULL。

    {

        result = -1;

        return result;

    }

    else

    {

        for (int i = 0; i < destlen; i++)

        {

            if (*keyvaluebuf == '=')

            {

                *keyvaluebuf++;

                break;

            }

            keyvaluebuf++;

        }

        while (*keyvaluebuf != '\0')

        {

            *valuebuf = *keyvaluebuf;

            valuebuf++;

            keyvaluebuf++;

        }

        *valuebuf = '\0';

    }

 

    int len = strlen(valuebuf);

    return result;

}

 

//char *p = "abcd11111abcd2222abcdqqqqq"; //字符串中"abcd"出现的次数。

//要求你自己写一个函数接口,并且写出测试用例。

//完成功能为:求出"abcd"字串出现的次数

//输入:

int getSubCount(char *str, char *substr, int * mycount)

{

    int ret = 0;

    char *p = str;

    char *sub = substr;

    int count = 0;

 

    if (str==NULL || substr==NULL || mycount == NULL)

    {

        ret = -1;

        return ret;

    }

 

    //char *p = "abcd11111abcd2222abcdqqqqqabcd";

    //char *p2 = NULL;

    //p2 = p;

    do

    {

        p = strstr(p, sub);

        if (p!= NULL)

        {

            count++;

            //++后缀操作符优先级高,所以先执行*p操作 然后地址++

            *mycount++;

            p = p + strlen(sub);

        }

        else

        {

            break;

        }

    } while (*p != '\0');

    //printf("count:%d \n", count);

 

    //mycount是实参的地址 *(实参的地址)

    *mycount = count;

    return ret;

 

05重复的错误何时休

#include
"stdio.h"

#include
"stdlib.h"

#include
"string.h"

 

void copy_str21_modify(char *from, char *to)

{

    int i = 0;

    if (*from != '\0')//要先考虑空串

    {

        printf("ddddd");

    }

    for (; *from != '\0'; from++, to++)

    {

        *to = *from;

    }

    *to = '\0';

    printf("to:%s", to);

    printf("from:%s", from);

}

 

void copy_str_err(char *from, char *to)

{

    for (; *from != '\0'; from++, to++)//要先考虑空串

    {

        *to = *from;

    }

    *to = '\0';

    printf("to:%s", to);

    printf("from:%s", from);

}

 

//字符串逆序

int mainaaaa()

{

    char buf1[100] = "abcdefg";

    char to[100];

    copy_str_err(buf1, to);

}

 

 

//越界场景

int main00000000000()

{

    char from[5] = "abcde";

    printf("\n %s", from);

    getchar();

    return 0;

}

 

3.7const专题

  1. const基础知识(用法、含义、好处、扩展)

 

int main()

{

    const
int a;

    int
const b;

    //上面两者一样

 

    const
char *c;

    char * const d; //这样限定指针的话就要为它赋初值,不然没有任何意义

    char buf[100]

    const
char * const e;

 

    return 0;

}

 

Int func1(const)

初级理解:const是定义常量  const意味着只读

含义:

//第一个第二个意思一样 代表一个常整形数

//第三个 c是一个指向常整形数的指针(所指向的内存数据不能被修改,但是本身可以修改)

//第四个 d 常指针(指针变量不能被修改,但是它所指向内存空间可以被修改)

//第五个 e一个指向常整形的常指针(指针和它所指向的内存空间,均不能被修改)

Const好处

//合理的利用const,

//1指针做函数参数,可以有效的提高代码可读性,减少bug;

//2清楚的分清参数的输入和输出特性(参数列表中被const限定了的是传入参数)

结论:

//指针变量和它所指向的内存空间变量,是两个不同的概念。。。。。。

//看const 是放在*的左边还是右边 看const是修饰指针变量,还是修饰所指向的内存空变量

C语言复习:字符串和一级指针的更多相关文章

  1. C语言复习-字符串与指针

    C语言复习-字符串与指针 例一: [字符串处理 去除C代码中的注释] C/C++代码中有两种注释,/* */和//.编译器编译预处理时会先移除注释.就是把/*和*/之间的部分去掉,把//以及之后的部分 ...

  2. 【C语言】字符串常量与指针

  3. C语言用一级指针处理字符串的反思

    1.一级指针处理字符串的常见方式 如果使用单个指针,不方便对字符串本身进行操作,只适合遍历. 使用两个指针, 两个指针和字符串大致有两个常见处理方式: (1)两个指针从字符串首部开始向后移动,同时处理 ...

  4. c语言基础学习07_关于指针的复习

    ============================================================================= 指针变量之间赋值是需要兼容的. 例如:int ...

  5. C语言中的数组和指针以及字符串

    数组名同时也是该数组首元素的地址,而指针提供了一种用来使用地址的符号方法,因此指针能够很有效地处理数组. 将一个整数加给指针,这个整数会和指针所指类型的字节数相乘,然后所得的结果会加到初始地址上 da ...

  6. C语言复习:指针知识

    指针知识体系搭建 指针强化 指针是一种数据类型 指针也是一种变量,占有内存空间,用来保存内存地址 测试指针变量占有内存空间大小:sizeof(指针名); 2)*p操作内存 在指针声明时,*号表示所声明 ...

  7. C语言指针系列 - 一级指针.一维数组,二级指针,二维数组,指针数组,数组指针,函数指针,指针函数

    1. 数组名 C语言中的数组名是一个特殊的存在, 从本质上来讲, 数组名是一个地址, 我们可以打印一个指针的值,和打印一个数组的值来观察出这个本质: int nArray[10] ={ 0 }; in ...

  8. go语言之字符串、指针、数组、切片、结构struct、面向对象

    一: 字符串 概述: Go 语言将字符串作为 种原生的基本数据类型,字 符串的初始化可以使用字符串字面量. (1)字符串是常量,可以通过类 数组 索引访问其字节单元,但是不能修改某个字节的值 (2)宇 ...

  9. C语言一级指针与二级指针

    指针的概念 指针就是地址, 利用这个地址可以找到指定的数据 指针就是地址, 那么在使用的时候, 常常会简单的说 指针变量为指针 指针变量就是存储地址的变量 int *p1;// 申请了一个变量, 即在 ...

随机推荐

  1. junit中线程需要注意的问题

    Junit主线程执行完毕后,就会结束进程,不关注是否有其他线程在运行.当Junit运行完毕后,如果其他线程还没有执行完毕,那么不会再执行. 使用CountDownLatch,保证启动的线程运行结束后, ...

  2. [UE4]控制流

    虽然官方文档说复杂的蓝图循环是会跨域多帧运行,但实际上测试下来,如果在循环体进行大量复杂的运算,不足以在一帧内完成时,游戏就会在当前帧卡住,直到循环结束为止. 一.Switch Switch可以在所有 ...

  3. 为什么QQ空间和QQ邮箱都是IE默认打开?

    为什么QQ空间和QQ邮箱都是IE默认打开? 我已经设置成chrome为默认浏览器了 原文转载至:https://zhidao.baidu.com/question/390662851068217285 ...

  4. Go语言 函数,工程管理

    Go语言 函数,工程管理 1.无参无返回值函数的使用 package main import "fmt" func main() { // 无参无返回值函数的调用:函数名() fu ...

  5. SSL&HTTPS简单介绍

    这篇是最近看SSL和HTTPS的一个简单性总结,其中内容大部分都是参考网络上的内容,自己归纳整理了下. SSL介绍 HTTPS介绍 HTTP请求数据工作流程: l  用户在浏览器中输入网址,并告诉浏览 ...

  6. nonlocal和global

    获取变量时遵循LEGB原则,修改变量时需要global/nonlocal进行修改 global # global的使用 函数外定义了全局变量: global关键字在函数内会修改全局变量 函数外没定义全 ...

  7. Linux性能优化 第一章 性能追踪建议

    1.1常用建议1.1.1记大量的笔记(记录所有的事情)在做性能调优问题的时候很重要的一个操作就是记录下所有的事情,包括每一个输出.执行的结果.可以新建一个文件夹,然后把结果的文件都塞到该文件夹内.包括 ...

  8. isNAN的使用方法及介绍

    NaN为 Not a Number isNaN()函数在接到一个值后,会尝试将这个值转换为数值. alert(isNaN(NaN)); //true alert(isNaN(25)); //false ...

  9. dns 域名地址

    Public DNS+ 是属于 腾讯云旗下的公共 DNS 服务.拥有 80 多条国内线路和 4 条海外线路,有 BGP Anycast 技术,也是国内首家支持谷歌 ECS (edns-client-s ...

  10. Vue.js模拟百度下拉框

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...