C13-指针,字符串

对于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;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值