C语言复习:字符串和一级指针

字符串基本操作

字符数组初始化方法

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是修饰指针变量,还是修饰所指向的内存空变量

猜你喜欢

转载自www.cnblogs.com/love-DanDan/p/8930595.html