今日学习内容:函数庶事,初识数组,定义数组,数组的例子*2,数组运算,二维数组,取地址运算,指针
笔记:
1.函数庶事
调用函数时逗号为标点符号如:f(a,b) 不是逗号运算符 而f((a,b))这里面的逗号才是逗号运算符
函数可以嵌套调用但不能嵌套定义
int main() 也是个函数
2.初试数组
数组,有能力记下每个输入的数
#include <stdio.h>
int main()
{
int x;
double sum = 0;
int cnt = 0;
int number[100]; //定义数组
scanf("%d", &x);
while (x != -1) //-1是作为一个结束词来结束输入
{
number[cnt] = x; //对数组中的元素赋值
sum += x;
cnt++;
scanf("%d", &x);
}
if (cnt > 0)
{
int i;
double average = sum / cnt;
for (i = 0; i < cnt; i++)
{
if (number[i] > average)
{
printf("%d\n", number[i]); //使用数组中的元素 并遍历数组
}
}
}
return 0;
}
程序危险 输入的数据可能超过100个
2.定义数组
- <类型> 变量名[元素数量]
- int grades[100];
- double weight [20];
元素数量必须是整数
数组:一种容器
其中所有元素都有相同类型
一旦创建不能改变大小
在赋值号右边是读,左边是写
数组单元:每个单元就是数组类型的一个变量
放在[]里的数叫下标/索引,下标从0开始记数
可创建int a[0] 可存在但没用
3.数组例子:统计个数
#include <stdio.h>
int main()
{
const int number = 10; //数组大小
int x;
int count[number]; //定义数组
int i;
for (i = 0; i < number; i++) //初始化数组 遍历数组去给每个元素赋值
{
count[i] = 0;
}
scanf("%d", &x);
while (x != -1)
{
if (x >= 0 && x <= 9)
{
count[x]++; //数组参与运算
}
scanf("%d", &x);
}
for (i = 0; i < number; i++) //遍历数组做输出
{
printf("%d : %d .\n", i, count[i]);
}
return 0;
}
4.数组运算
#include <stdio.h>
int search(int key, int a[], int length);
int main(void)
{
int a[] = { 2,4,6,7,1,3,5,9,11,13,23,14,32, }; //数最后加个逗号更便
{
int i;
printf("%lu\n", sizeof(a));
printf("%lu\n", sizeof(a[0]));
for (i = 0; i < sizeof(a)/sizeof(a[0]); i++)
{
printf("%d\t", a[i]);
}
printf("\n");
}
int x;
int loc;
printf("请输入一个数字:");
scanf("%d", &x);
loc = saerch(x, a, sizeof(a)/sizeof(a[0])); //与以上数字无关
if (loc != -1)
{
printf("%d在第%d个位置上\n", x, loc);
}
else
{
printf("%d不存在\n", x);
}
return 0;
}
int search(int key, int a[], int length)
{
int ret = -1;
int i;
for (i = 0; i < length; i++)
{
}
}
数组大小 sizeof给出整个数组占内容的大小,单位:字节
sizeof(a)/sizeof(a[0])=得到的数组单元数 一旦修改初始数据,不需要修改遍历代码
数组的赋值:变量本身不能被赋值
循环结束条件不能是<=… 离开循环后不能用i的值来做数组元素的下标
5.数组例子:素数
可用循环的次数判断程序的效率
//从2到x-1测试是否可以整除
#include <stdio.h>
int isPrime(int x)
{
int ret = 1;
int i;
if (x == 1 ||
(x % 2 == 0 && x != 2))
ret = 0;
for (i = 3; i < x; i += 2)
{
if (x % i == 0)
{
ret = 0;
break;
}
}
return ret;
}
//如果x是偶数 立刻... 否则要循环(n-3)/2+1 遍 n很大时则循环n/2遍
6.二维数组(几对方括号[])
遍历要两重循环(这玩意还涉及线性代数?!)
- 初始化:列数必须给,行数可由编译器自己数。每行一个{},用逗号分隔。最后逗号能存在。如省略表补零。
井字棋:
//读入井字棋矩阵
#include <stdio.h>
int main()
{
const int size = 3;
int board[size][size];
int i, j;
int num0fX;
int num0f0;
int result = -1; //-1 没人赢,1 X赢, 0 0赢
//读入矩阵
for (i = 0; i < size; i++)
{
for (j = 0; j < size; j++)
{
scanf("%d", &board[i][j]);
}
}
//检查行
for (i = 0; i < size && result == -1; i++)
{
num0f0 = num0fX = 0;
for (j = 0; j < size; j++)
{
if (board[i][j] == 1)
{
num0f0++;
}
}
if (num0f0 == size)
{
result = 0;
}
else if (num0fX == size)
{
result = 1;
}
}
return 0;
} //for走了三步看每一行的XX有几个 OO有几个
行列历遍差不多,变化于循环内外层,先走行还是列
能别这么难懂吗。。。。。。。。
7.取地址运算
-
sizeof:运算符,给出类型或变量在内存中占的字节数
sizeof(int) sizeof(i) -
运算符& :获得变量地址 则操作数必须是变量 int i;printf(“%x”, &i);
%x是指无符号以十六进制表示的整数
%u是指十进制无符号整数
&只是取出地址 但大小多少取决于编译器
架构 可以简单理解为不同的编译环境下编译会对地址产生影响 如(1字节=8bit(位),所以32位系统的内存地址对应4个字节,64位对应8个字节 但int不管系统是多少位应该都是4个字节)
&取地址的右边必须是一个变量
8.指针:(指针变量就是记录地址的变量)
int* p =&i; (意为把i的地址交给p p变量是个指针 *表示指针的意思)
int* p,q;
int *p,q;//都一样 都表示p是一个指针,指向一个int,q只是一个int类型的变量
星p是一个int,则p就是个指针了,而并不是说p是int星这种类型(没有这种类型)
而int*p,*q;才表示qp都是指针
指针变量:
- 变量值是内存的地址
- 普通变量的值是实际的值
- 指针变量的值是具有实际价值的变量的地址
(这段绕得头晕)
作参数的指针
void f (int *p);f函数要个int的指针,则在被调用的时候得到了某变量的地址:int i=0;f(&i);然后把地址传给指针
函数里可通过指针访问外面的i
数组小推车每个小推车只能一个石头,小推车石头能放另一个车上,但是他们干各自流程的事情,不知道他们在哪,也找不到他们于是有了小车编号 之前讲函数的时候有提到独立的变量空间 传值 如壁虎断尾;传地址 跑得了和尚跑不了庙
访问地址上的变量*
- *是个单目运算符,用来访问指针的值所表示的地址上的变量
- 可做右值也可做左值
- int k=*p / p=k+1;
p就是i的地址,※星p就是i的值,加了 ※星号可以通过地址访问i的值!!并改变i的值!!!就是p是地址对应的变量
传值就好比只说名字不说细节,传指针就相当于不说名字,但是把你的当前详细住址甚至精确到米的经纬度放进去了,顺着地址直接找到你
——————————————————————————————————————————————————————END
指针。。函数。。。。。。。好难。。。。。。。。。。。。
2024.8.20