c语言保姆级笔记九-指针(下)

复习

函数(把一些完成一个特定功能的代码集合到一起,变成一个函数)

*

***

*****

*

***

*****

void print_star() //函数定义

{

printf(" *\n");

printf("***\n");

printf("*****\n");

}

int main()

{

print_star();

}

带参数,返回值的函数

求最大值

int max(int a, int b)

{

returna > b ? a : b;

}

int main()

{

intx = max(3, 5); //3---> a 5---> b

}

指针(指针变量: 保存一个地址)

int a = 10;

int *p;

p = &a;

*p = 20;

指针也可以指向一个数组

int a[5] = {10, 20, 30, 40, 50};

int *p;

p = a;

*(p + 1) = a[1];

*(p + 2) = a[2];

....

指针可以作为函数的参数

求n个学生的学生成绩总和

int get_sum(int *p, int n)

{

inti, sum = 0;

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

{

sum+= *(p + i); //sum += p[i];

}

returnsum;

}

int main()

{

inta[] = {90, 80, 70, 60, 50};

intx = get_sum(a, 5);

}

作业讲解

作业:1 完成一个函数,输出

*

***

*****

*******

*********

#include <stdio.h>

void print_star(int n)

{

inti, j;

for(i= 0; i < n; i++) //有n层

{

//先输出空格

for(j= 0; j < n - i - 1; j++)

printf("");

//再输出星号

for(j= 0; j < 2 * i + 1; j++)

printf("*");

printf("\n");//输出换行

}

}

int main()

{

intn;

scanf("%d",&n);

print_star(n);

}

作业:2 完成字符串拷贝函数 mystrcpy(char *dst, char *src); //src (source 源头) dst(destination 目标)

#include <stdio.h>

void my_strcpy(char *dst, char *src)

{

while(*src!= '\0')

{

*dst = *src;

dst++;

src++;

}

*dst= '\0';

}

int main()

{

chara[] = "hello world"; //字符串有结束符'\0'

charb[100] = { 0 };

my_strcpy(b,a); //会将a字符串中的数据copy给 b

printf("bis %s\n", b);

}

void my_strcpy(char *dst, char *src)

{

inti = 0;

while(src[i]!= '\0')

{

dst[i]= src[i];

i++;

}

dst[i]= '\0';

}

void my_strcpy(char *dst, char *src)

{

while(*dst++= *src++); //linux源码, '\0' ====== 0

//1) *dst = *src //先赋值

//2) while(*dst) // 只要*dst 非0, 就继续执行

//3) src++, dst++

}

//linux源码, '\0' ====== 0

ascii码为0 数值0 字符‘0’是48

选择题

inta = 0;

while(a= 1) //1) a = 1 2) while(a)

{

printf("1111\n");

}

A 循环一次也不执行 B 循环执行一次 C 无限循环

int main()

{

chara[] = "hello world"; //字符串有结束符'\0'

charb[100] = { 0 };

my_strcpy(b,a); //会将a字符串中的数据copy给 b

printf("bis %s\n", b);

}

//指针的算术运算

+ - * / % ++ -- +1

两个指针不可以+ * / %, 但是可以 - 减

#include <stdio.h>

int main()

{

inta[5] = {10, 20, 30, 40, 50};

int*p = &a[0];

int*q = &a[2];

printf("%d\n",p + q); //两个指针不能加(因为两个地址相加完全没有任何意义)

printf("%d\n",q - p); //A ???? A 2 B 8 (两个指针相减,能算出 两个指针变量差有多少个元素)

printf("%d\n",*q - *p); //20(值相减)

}

p + 1 ????? (难点)

#include <stdio.h>

int main()

{

inta[5] = {10, 20, 30, 40, 50};

int*p = a;

charb[] = "hello";

char*q = b;

//假设 a (0x0000 1100) b(0x0000 2200)

printf("pis %p, q is %p\n", p, q);

p++; //p ? p 加多少由 p指向的变量的类型决定(int a + sizeof(int) 4)

q++; //q ? (chara + sizeof(char) 1)

printf("pis %p, q is %p\n", p, q);

}

//指针的关系运算

指针 > < == !=

== 是什么意思(如果两个指针相等,说明他们共同指向了一个变量)

#include <stdio.h>

int main()

{

inta[5] = {10, 20, 30, 40, 50};

int*p = a;

int*q = a;

if(p== q)

{

printf("pand q point same\n");

}

else

{

printf("different\n");

}

}

//空指针 : 在 c语言中用 NULL 代表空指针

用法:

#include <stdio.h>

int main()

{

int*p; //p 因为没指向有效变量,又被称为野指针

*p= 20;

printf("*pis %d\n", *p);

}

//Segmentation fault (core dumped) 段错误

//如果 使用了一个非法内存,就出这个错误

1) 数组越界 int a[10]; a[100]= 99; //越界,因为a只有10个元素

2) 使用了一个指针,但是未初始化,直接 *p 操作

为了避免野指针,通常在 p 不知道该指向谁时,那么赋值为 NULL

#include <stdio.h>

int main()

{

int*p = NULL; //避免野指针

if(p!= NULL)

{

*p= 20;

printf("*pis %d\n", *p);

}

}

练习

1 写一个函数,计算数组中成绩小于60的人数

#include <stdio.h>

int get_low_60(int *p, int n)

{

inti, sum = 0;

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

{

if(p[i]< 60)

{

sum++;

}

}

returnsum;

}

int main()

{

inta[10] = {60, 20, 30, 40, 50, 76, 69, 85, 73, 72};

intx = get_low_60(a, 10);

printf("xis %d\n", x); //5

}

2 写一个函数,查找一个字符串中某个字母出现的次数

#include <stdio.h>

int find_word(char *p, char c)

{

intj = 0;

while(*p!= '\0')

{

if(*p== c)

{

j++;

}

p++;

}

returnj;

}

int main()

{

chara[] = "hello world";

intx = find_word(a, 'l');

printf("xis %d\n", x); //3

}

3 编写一个函数,完成下面功能,能将Hello World! 转换成Lipps Asvph!

#include <stdio.h>

void change_passwd(char *p)

{

while(*p!= '\0')

{

if((*p>= 'a' && *p <= 'v') || (*p >= 'A' && *p <= 'V') )

{

*p= *p + 4;

}

elseif((*p >= 'w' && *p <= 'z') || (*p >= 'W' && *p <='Z'))

{

*p= *p + 4 - 26;

}

p++;

}

}

int main()

{

charpasswd[] = "Hello World!";

change_passwd(passwd);

printf("%s\n",passwd); //Lipps Asvph!

}

如果想实现用一个函数,交换两个数

//写一个swap, 交换两个数

#include <stdio.h>

void swap(int a, int b) //a 和 b交换了,但x, y没换

{

intt;

t= a;

a= b;

b= t;

}

int main()

{

intx = 5, y = 9;

swap(x,y); //交换x 和 y

printf("xis %d, y is %d\n", x, y); //x is 9, yis 5

}

函数参数值传递,无法改变实参的值

/那么上面的问题就可以采用地址传递

#include <stdio.h>

void swap(int *a, int *b) //

{

intt;

t= *a;

*a= *b;

*b= t;

}

int main()

{

intx = 5, y = 9;

swap(&x,&y); //x 的地址给 a, y 的地址 给b

printf("xis %d, y is %d\n", x, y); //x is 9, yis 5

}

函数参数传递,有两种方式

///值传递,改变不了实参的值,就是把实参的值传递给形参,然后形参 进行运算

///地址传递,可以改变实参的值,形参是一个指针变量,实参传递的是变量的地址(形参通过地址间接改变形参的值)

练习1

编写函数fun:从n个学生的成绩中统计出低于平均分的学生人数,由函数值返回,

平均分存放在形参*ptr_aver所指的存储单元中(即平均分由参数返回)。

函数原型为:int fun( float *s, int n, float*ptr_aver );

例如:若输入8名学生的成绩如下

80.5 60 72 90.5 98 51.5 88 64

则低于平均分的学生人数为:4(平均分:75.5625)。

#include <stdio.h>

int fun(float *s, int n, float*ptr_aver)

{

floatsum = 0;

inti = 0, count = 0;

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

{

sum+= s[i]; //sum += *(s + i);

}

*ptr_aver= sum / n;

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

{

if(s[i]< *ptr_aver)

count++;

}

returncount;

}

int main()

{

floata[8] = {80.5, 60, 72, 90.5, 98, 51.5, 88, 64};

floataver = 0;

intx = fun(a, 8, &aver);

printf("%d(aver:%.4f)\n",x, aver);

}

///sizeof (能求出某个变量占用的内存空间大小)

int *p;

char *q;

类型? sizeof() ?

p int *(整型指针) 4

*p int (整型) 4

q char *(字符型指针) 4

*q char (字符型) 1

int (4) char (1) 无论什么指针(4) : 原因: 因为指针存的就是地址,无论什么地址,都是4

#include <stdio.h>

int main()

{

int*p;

char*q;

printf("sizeof(*p)%d, sizeof(p) %d\n", sizeof(*p), sizeof(p));

printf("sizeof(*q)%d, sizeof(q) %d\n", sizeof(*q), sizeof(q));

}

int a[5]; a = 0x00001100

a 数组的首地址

&a[0] 第一个元素a[0] 的地址 0x0000 1100

&a[2] 第三个元素a[2] 的地址 0x0000 1108

a <=====> &a[0]

变量(全局变量、局部变量)

变量定义

int a;

float b;

char c;

变量定义规范

1) 变量尽量小写

2) 变量定义时要清晰的表达出变量的含义 (尽量不要简写, 尽量不要用拼音)

3) 命名方式有3种

StudentName 大驼峰命名法

studentName 小驼峰命名法

student_name linux风格

局部变量(定义在函数中的变量属于局部变量)

例1:

#include <stdio.h>

void fun()

{

intx; //x 是局部变量,只在fun中有效

}

int main()

{

x= 100; //此处使用x 就出错(编译器会认为 x未定义)

}

hello.c:8:2: error: ‘x’ undeclared(first use in this function)

undeclared 未定义

例2:

#include <stdio.h>

void fun()

{

intx = 100;

}

int main()

{

intx = 200; //不同函数中可以有同名变量,不冲突

printf("xis %d\n", x); // 200

}

例3:

#include <stdio.h>

void fun()

{

intx = 100; //

}

int main()

{

intx; //局部变量如果未初始化,默认值为 随机数

fun();

printf("xis %d\n", x); //??? 随机值

}

局部变量特点 : 放在函数里面的变量是局部变量

1) 两个不同函数中可以有同名局部变量

2) 局部变量只在函数中有效

3) 参数和局部变量也不能同名

4) 局部变量如果没付初值,那么值为 随机值

///全局变量(定义在函数外面的变量是全局变量,在程序的任何位置都可以访问)

例1:

#include <stdio.h>

int x = 100;

int main()

{

printf("xis %d\n", x); //(B) //A 0 B 100 C 编译失败

}

例2:

#include <stdio.h>

int x = 100;

void fun()

{

x= 200;

}

int main()

{

fun();

printf("xis %d\n", x); //(B) //A100 B 200 C 0 D 编译失败

}

例3:

#include <stdio.h>

int x = 100;

void fun()

{

intx = 200; //局部变量可以和全局变量同名

}

int main()

{

printf("xis %d\n", x); //(A) //A 100 B 200 C 0 D 编译失败

}

例4:

#include <stdio.h>

int x; //全局变量未赋初值,默认为0

void fun()

{

intx = 200;

}

int main()

{

fun();

printf("xis %d\n", x); //C A 随机数 B 200 C 0 D 编译失败

}

1) 定义在函数外面的变量是全局变量

2) 全局变量在程序的任何位置都可以使用

3) 只要有一个地方改了全局变量,其他地方也改

4) 全局变量默认值为 0

5) 全局变量不能同名,

//函数声明(作用是告诉编译器,此函数是长什么样的)

函数的定义尽量放在函数调用的前面,函数先定义再调用

例:

#include <stdio.h>

int main()

{

intx = max(3, 5);

}

int max(int a, int b)

{

returna > b ? a : b;

}

如果函数定义在函数调用的下面,函数就要先声明一下

#include <stdio.h>

int max(int a, int b); //函数声明

int main()

{

intx = max(3, 5);

}

int max(int a, int b)

{

returna > b ? a : b;

}

函数的声明:

1) void fun(); ///要注意:有" ;"

2) 函数的声明不需要函数体

3) 函数的声明一定与定义一致

4) 函数的声明尽量放在头文件中

作业

1. 写一个函数,能输出n阶杨辉三角形 (输出的阶数,通过参数传递)

2. n只猴子围坐成一个圈,

按顺时针方向从1到n编号。

然后从1号猴子开始

沿顺时针方向从1开始报数,

报到m的猴子出局,

再从刚出局猴子的下一个位置重新开始报数,

如此重复,直至剩下一个猴子

它就是大王。

设计并编写程序,实现如下功能:

(1) 要求由用户输入开始时的猴子数n(8)、

报到的数m(4)。

(2) 给出当选猴王的编号。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值