文章目录
对于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;
}