C13-指针,字符串

    xiaoxiao2022-07-06  194

    文章目录

    对于C12的笔记做出总结链接报错指针指针进阶指针有关运算数组和指针的关系字符串区分全局字符串与字符数组从字符串去理解各种字符串函数注意区分sizeof与strlen手工制作我们自己的字符串函数

    对于C12的笔记做出总结

    随机不够随机 因为我们在GetNewBrick设置了随机数种子

    看库源码:

    通过观看rand()函数可以知道

    int rand() { return holdrand = holdrand * 214013L + 2531011L; };

    其实每次rand都是排列好的了数字 是因为srand随机出第一位数字。(按照时间创造首次排位 初始化一次就可以了) 所以放在main开始处就不用每次调用的时候再重新刷新一次随机种子

    链接报错

    链接在以前笔记中已经谈及,链接是生成obj以后 生成exe的时候出现的问题 所以比编译错误更难查找的到 总结如下:

    全局变量的声明(不是实现),需要extern关键字声明放在头文件中实现放在cpp文件中

    如何不闪烁,并且实现任意位置输出 在C库函数,没有办法实现任意地方位置输出。 必须在window提供的函数去实现(API)。 使用必须包含window.h. 如果没有用到以前的彩色库文件 那么我们自己可以封装一个函数 帮助我们使想输出的东西,在任意位置输出 下面使用万能的Hello Word作为测试

    #include"stdafx.h" #include<stdio.h> #include<Windows.h> void MoveCursorTo(int nRow, int nCol) { COORD loc; loc.Y = nRow; loc.X = nCol; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), loc); } int main(void) { MoveCursorTo(10, 10); printf("Hello\r\n"); MoveCursorTo(20, 20); printf("World\r\n"); return 0; }

    通过F12得知 COORD是一个结构体

    输出结果验证正确 好做完上次笔记总结 今天来说一说指针

    指针

    C语言中发明了指针,使得我们可以直接方便操作内存,极大的提高了程序的灵活性 同时也提高了C语言程序员的门槛. 指针的基本语法 这里使用实例说明

    int main() { int nValue = 0x1234; char chValue = 'A'; short sValue= 0xCCDD; int* pnValue= NULL; char* pchValue = NULL; short* psValue = NULL; pnValue = &nValue; pchValue = &chValue; psValue = &sValue; //指针里面存放的是地址 printf("%p %p %p\r\n", pnValue, pchValue, psValue); printf("%p %p %p\r\n", &nValue, &chValue, &sValue); //解引用 加上* 就是这个地址所指到的东西 printf("%x %x %x\r\n", *pnValue, *pchValue, *psValue); printf("%x %x %x\r\n", nValue, chValue, sValue); return 0; }

    结果如下

    指针进阶

    指针有两个内涵 先用代码体会

    int main() { //定义指针 int* pnValue= NULL; char* pchValue = NULL; short* psValue = NULL; int nValue = 0xAABBCCDD; pnValue = &nValue; pchValue = (char*)&nValue; psValue = (short*)&nValue; //输出地址 printf("%p %p %p\r\n", pnValue, pchValue, psValue); //输出内容 printf("%x %x %X\r\n", *pnValue, *pchValue, *psValue); return 0; }

    结果如下

    可以知道地址是一样的,但是内容不同了 这就反映出指针的本质,它其实不仅仅是一个地址 指针包括两个内涵:

    地址(指向哪里)解释方式(如何把所指的东西取出来) 理解以上,就很快的明白了 为什么C语言不允许: 不同类型不能去指向 pValue=&nValue;

    指针有关运算

    与指针有关的运算除了,取地址 & 与解引用 * 以外还有

    +,-运算符++,-- 自增自减运算符 通过实例来学习: int main() { //定义指针 int* pnValue= NULL; int nValue = 0x1234; pnValue = &nValue; printf("%p\r\n", pnValue); printf("%p\r\n", pnValue-1); printf("%p\r\n", pnValue-2); printf("%p\r\n", pnValue+1); printf("%p\r\n", pnValue + 2); return 0; }

    可以看到以上的程序,不是简单的数学意义的相加减 而是(指向Type类型的指针):

    pValue+i的地址=pValue+i*sizeof(type);

    除此之外 两个指针是不能相加的,因为没有什么意义,但是同类型的指针是可以相减的

    int main() { char chArry[] = { 0, 3, 9 }; char* pchValue1 = chArry; char* pchValue2 = &chArry[2]; printf("%d\r\n", pchValue2 - pchValue1); return 0; }

    指针的相减不是数学意义的相减,实际上,两个指向type类型相减:

    p1-p2 所得的结果为: ((int)p1-(int)p2)/sizeof(type)

    它的直接意义,就是用来计算两个地址所隔的元素个数

    数组和指针的关系

    以前就提及到,数组的名字就是数组的首地址. 精确的讲数组名就是一个包含解释方式的数组首地址. 当数组作为参数传递的时候,实际会退化成指针传递.

    void MyFun(int arry[], int nCount) { printf("%d\r\n", arry[nCount]); printf("%d\r\n", *(arry + 2)); } int main() { int nArry[] = { 1, 2, 3 }; MyFun(nArry, 2); return 0; }

    字符串

    字符串不是C语言的基本数据类型,因为字符串生来变长 为了能够解决操作变长的数据,我们就需要约定,字符串怎么样才算结束 在C语言中的约定是 以0x00为结束符号. 实际上

    int main() { char *pchValue = "Hello"; "Hello"; return 0; }

    这里的单独"Hello"是没有出错的 其实这背后是做了很多的事情的.

    在局部区域分配一个空间,能够放下’h’ ‘e’ ‘l’ ‘l’ ‘o’ 五个字母,以及结束标志0x00将h e l l o所对应的ASCII值,填充到上一步区域中.将结束字符放在上一步区域的末尾,作为结束标志.将第一步分配空间的首地址,作为值返回

    区分全局字符串与字符数组

    int main() { char* pchValue = "hello";//全局区 只读 char chArry[] = "hello" ;//栈区 可读可写 printf("%s,%s\r\n", pchValue, chArry); chArry[0] = 'H'; printf("%s\r\n", chArry); pchValue[0] = 'H';//这里会产生中断 printf("%s\r\n", pchValue); return 0; }

    从字符串去理解各种字符串函数

    strlen: 计算字符串长度strcpy:复制字符串strcmp:比较字符串strcat : 连接字符串

    注意区分sizeof与strlen

    int main() { char* pchValue = "hello";//全局区 只读 char chArry[] = "hello" ;//栈区 可读可写 printf("%d\r\n", sizeof(pchValue)); // 4 printf("%d\r\n", sizeof(chArry)); //6 printf("%d\r\n", strlen(pchValue));// 5 printf("%d\r\n", strlen(chArry));//5 return 0; }

    pchValue所指的东西就是 字符串返回的首地址。 具体而言,当参数分别如下时,sizeof返回的值表示的含义如下:

    数组——编译时分配的数组空间大小;指针——存储该指针所用的空间大小(存储该指针的地址的长度,是长整型,应该为4);类型——该类型所占的空间大小;对象——对象的实际占用空间大小;函数——函数的返回类型所占的空间大小。函数的返回类型不能是void。 strlen(…)是函数,要在运行时才能计算。参数必须是字符型指针(char*)。当数组名作为参数传入时,实际上数组就退化成指针了。功能是:返回字符串的长度 退化对比程序如下 int main() { char chArry[20] = "hello"; printf("%d\r\n", sizeof(chArry)); // 根据上面描述可以知道 但运行对象为数组的时候 编译时候分配的空间 printf("%d\r\n", strlen(chArry));// 计算的是退化为指针后的数组 return 0; }

    为了更加熟悉函数,我们自己制作自己的字符串函数吧

    手工制作我们自己的字符串函数

    先在MSDN上找到原型 strlen

    #include"stdafx.h" #include<stdio.h> #include<string.h> size_t Mystrlen(const char *string) { int ReCount = 0; while (*string != '\0') { ReCount++; string++; } return ReCount; } int main() { printf("%d\r\n",Mystrlen("HelloWorld")); return 0; }

    strcmp

    int Mystrcmp(const char *string1, char *string2) { int nRet = 0; while (*string1 != '\0') { if (*string2 != '\0') { nRet = *string1 - *string2; if (nRet != 0) { return *string1 - *string2; } } else { return *string1 - *string2; } string1++; string2++; } return *string1 - *string2; }

    strcpy

    char* Mystrcpy(char *str1, char *str2) { char *pContent = NULL; pContent = str1; while (*str1 != '\0'&&*str2 != '\0') { *str1= *str2; str1++; str2++; } *(str1) = '\0';//后面的数据处理为0 return pContent; }

    strcat

    char* Mystrcat(char *str1, const char *str2) { char *pnContent = NULL; pnContent = str1; while (*str1 != '\0') { str1++; } while (*str1 == '\0'&&*str2!='\0') { *str1 = *str2; str1++; str2++; } return pnContent; }
    最新回复(0)