学习笔记
数组
- 为什么需要数组:
- 为了解决大量同类型数据的存储和使用问题
- 为了模拟现实世界
- 数组的分类:
- 一维数组:
- 怎样定义一维数组:
- 为n个变量连续分配存储空间
- 所有的变量数据类型必须相同
- 所有变量所占的字节大小必须相等
例子: int a[5];
- 有关一维数组的操作:
- 初始化 :
a. 完全初始化
int a[5] = {1,2,3,4,5};
b.不完全初始化:(未被初始化的元素自动为0)
int a[5] = {1,2,3};
c.不初始化:(所有元素都是垃圾值)
int a[5];
d.清零:
int a[5] = {0};
错误写法:
int a[5];
a[5] = {1,2,3,4,5};
只有在定义数组的同时才可以整体赋值,其他情况下整体赋值都是错误的
a[5] = 100; //这是错误的,因为没有a[5]这个元素,最大的是a[4]
int a[5] = {1,2,3,4,5};
int b[5];
如果要把a数组中的值全部复制给b数组:
错误的写法 : b = a //错误,因为a,b不能代表这些元素
//一维数组名不代表数组中所有的元素,一维数组名代表数组第一个元素的地址
正确的写法应为:
for (i = 0;i < 5; ++i)
b[i] = a[i];
应用:
赋值 , 排序 , 求最大最小值 , 倒置 , 查找 , 插入 , 删除 - 初始化 :
- 怎样定义一维数组:
- 二维数组:
int[3][4]:
总共是12个元素,可以当做3行4列看待
a[i][j]即表示第i+1行第j+1列的元素:a[2][3]便表示第3行第4列的元素
int a[m][n] :该二维数组最右下角位置的元素只能是a[m-1][n-1]
初始化:
int a[3][4] = {1, 2, 3, 4, 5, 6, 7, 8 , 9, 10, 11, 12}
int a[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
应用:
对二维数组排序
求每一行的最大值
判断矩阵是否对称
矩阵的相乘
- 多维数组
是否存在多维数组?
:不存在,因为内存是线性一维的
n维数组就可以当做每个元素是n-1维数组的一维数组
比如:
int a[3][4];该数组是含有3个元素的一维数组,只不过每个元素都可以再分成4个小元素
int a[3][4][5];该数组是否有3个元素的一维数组,只不过每个元素都是4行5列的二维数组
函数:
-
为什么需要函数
- 函数避免了重复性操作
- 有利于程序的模块化
-
什么叫函数
- 逻辑上:
能够完成特定功能的独立的代码块 - 物理上:
- 能够接收数据(也可以不接收)
- 能够对接收的数据进行处理
- 能够将数据处理的结果返回(也可以不返) 总结: 函数是个工具,它是为了解决大量类似问题而设计的函数可以当做是一个黑匣子(左边接收数据,右边输出结果,不需要知道内部是如何运作处理的)
- 逻辑上:
-
如何定义函数
函数的返回值 函数的名字(函数的形参列表)
{
函数的执行体;
}- 函数定义的本质是详细描述函数之所以能够实现某个特定功能的具体方法
- return;表达式的含义:
- 终止被调函数,向主调函数返回表达式的值
- 如果表达式为空,则只终止函数,不向主调函数返回任何值
- break是用来终止循环和switch的,return是用来终止函数的
例如:
void f()
{
return;//return只用来终止函数,不向主调函数返回任何值
}
int f()
{
return 10;//1. 终止函数; 2.向主调函数返回10
}
3. 函数返回值的类型也称为函数的类型,因为如果函数名前的返回值类型和函数执行体中的return;表达式中的类型不同的话,则最终函数返回值的类型以函数名前的返回值类型为准
例如:
int f()
{
return 10.5;//因为函数的返回值类型是int ,所以最终f返回的值是10而不是10.5
} -
函数的分类
-
有参函数和无参函数
-
有返回值函数和无返回值函数
-
库函数和用户自定函数
-
值传递函数和地址传递函数
-
普通函数和主函数(main函数)
一个程序必须有且只能有一个主函数;
主函数可以调用普通函数,而普通函数不能调用主函数;
普通函数可以相互调用;
主函数是程序的入口,也是程序的出口;
-
-
注意的问题
- 函数调用和函数定义的顺序:
如果函数调用写在了函数定义的前面,则必须加函数前置声明 - 函数前置声明:
1. 告诉编译器即将可能出现的若干个字母代表的是一个函数
2. 告诉编译器即将可能出现的若干个字母所代表的函数的形参和返回值的具体情况
3. 函数声明是一个语句,末尾必须加分号
4. 对库函数的声明是通过#include<库函数所在的文件的名字.h>来实现的 - 形参和实参:
个数相同 , 位置一一对应 , 数据类型必须相互兼容
- 函数调用和函数定义的顺序:
-
如何在软件开发中合理的设计函数来解决实际问题:
一个函数的功能尽量单一,独立
多多学习 ,多多模仿大佬们的代码
函数是c语言的基本单位,类似java,c#,c++的基本单位 -
常用的系统函数
double sqrt(double x) -- 用于求x的平方根
int abs(int x) -- 用于求整数x的绝对值
double fabs(double x) -- 用于求浮点数x的绝对值 专题: -
递归: 简单说程序调用自身的编程技巧叫递归。递归的思想是把一个大型复杂问题层层转化为一个与原问题规模更小的问题,问题被拆解成子问题后,递归调用继续进行,直到子问题无需进一步递归就可以解决的地步为止。
使用递归需要避免出现死循环,为了确保递归正确工作,递归程序应该包含2个属性:
- 基本情况,基本情况用于保证程序调用及时返回,不在继续递归,保证了程序可终止。
- 递推关系,可将所有其他情况拆分到基本案例。
变量的作用域与存储方式
- 按作用域分:
- 全局变量:
在所有函数外部定义的变量叫全局变量
使用范围:从定义位置开始到整个程序结束 - 局部变量:
例:
void f(int i)
{
int j = 20;
}
i和j都属于局部变量
使用范围:只能在本函数内部使用 - 注意的问题:
全局变量和局部变量命名冲突的问题:在一个函数内部如果定义的局部变量的名字和全局变量的名字一样时,局部变量会屏蔽掉全局变量
- 全局变量:
在所有函数外部定义的变量叫全局变量
- 按变量的存储方式:
-
静态变量
-
自动变量
-
寄存器变量
-
代码实操
把一个数组元素给全部倒过来
#include <stdio.h>
int main()
{
int a[7] = {1, 2, 3, 4, 5, 6, 7};
int i, j;
int t;
i = 0;
j = 6;
while (i < j)
{
t = a[i];
a[i] = a[j];
a[j] = t;
i++;
--j;
}
for (i = 0; i<7; ++i)
printf("%d\n",a[i]);
return 0;
}
运行结果:
二维数组的使用:
#include <stdio.h>
int main()
{
int a[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
int i, j;
//输出数组的内容:
for (i = 0; i < 3; ++i)
{
for (j = 0; j < 4; ++j)
printf("%-5d ", a[i][j]); //-表示左对齐 , 5表示长度
printf("\n");
}
return 0;
}
运行结果:
函数的运用:
#include <stdio.h>
void max(int i, int j) //max是函数的名字,i和j是形式参数,简称形参
{
if (i > j)
printf("%d\n", i);
else
printf("%d\n", j);
}
int main()
{
int a, b, c, d, e, f;
a = 1, b = 2;
c = 3, d = 9, e = -5, f = 100;
max(a, b);
max(c, d);
max(e, f);
return 0;
}
运行结果:
函数举例:
# include<stdio.h>
int f(void) //括号中的void表示该函数不能接收数据;int表示函数返回值是int类型的
{
return 10; //向主调函数返回10
}
void g(void) //函数名前面的void表示该函数没有返回值
{
//return 10; //错误, 与上一行行首的void相矛盾
}
int main(void)
{
int j = 88;
j = f();
printf("%d\n",j);
// j = g(); //错误, 因为g函数没有返回值
return 0;
}
全局变量与局部变量:
#include <stdio.h>
int k = 1000;
void g()
{
printf("k=%d\n", k);
}
void f(void)
{
g();
printf("k = %d\n", k);
}
int main(void)
{
f();
return 0;
}
运行结果:
习题:
2000:
#include <stdio.h>
int main(void)
{
char a, b, c, t;
while (scanf("%c%c%c%*c", &a, &b, &c) != EOF) //%*c表示读取一个字符但是并不赋值给变量,从而滤去回车
{
if (a > b)
{
t = a;
a = b;
b = t; //对两个数值进行对换
}
if (a > c)
{
t = a;
a = c;
c = t;
}
if (b > c)
{
t = b;
b = c;
c = t;
}
printf("%c %c %c\n", a, b, c);
}
return 0;
}
运行结果:
2001:
#include <stdio.h>
#include <math.h>
int main()
{
double x1, x2, y1, y2;
double dis;
while (scanf("%lf %lf %lf %lf", &x1, &y1, &x2, &y2) != EOF)
{
dis = sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2));
printf("%.2lf\n", dis);
}
return 0;
}
运行结果:
2002
#include <stdio.h>
#define PI 3.1415927
int main(void)
{
double r, v;
while (scanf("%lf", &r) != EOF)
{
v = (4 * PI * r * r * r) / 3;
printf("%.3lf\n", v);
}
return 0;
}
运行结果:
2003
#include <stdio.h>
int main()
{
double num;
while (scanf("%lf", &num) != EOF)
{
if (num > 0)
printf("%.2lf\n", num);
else
{
num = 0 - num;
printf("%.2lf\n", num);
}
}
return 0;
}
运行结果:
2004
#include <stdio.h>
int main(void)
{
int t;
while (scanf("%d", &t) != EOF)
{
if (t <= 100 && t >= 90)
printf("A\n");
else if (t <= 89 && t >= 80)
printf("B\n");
else if (t <= 79 && t >= 70)
printf("C\n");
else if (t <= 69 && t >= 60)
printf("D\n");
else if (t <= 59 && t >= 0)
printf("E\n");
else
printf("Score is error!\n");
}
return 0;
}
运行结果:
2005
代码:paste.ubuntu.com/p/XT5z7c2vT…
运行结果:
2006
#include <stdio.h>
#include <math.h>
int main()
{
int n, i, num, pro;
while (scanf("%d", &n) != EOF)
{
pro = 1;
for (i = 0; i < n; i++)
{
scanf("%d", &num);
if (num % 2 != 0)
{
pro = pro * num;
}
}
printf("%d\n", pro);
}
return 0;
}
运行结果:
2007
#include <stdio.h>
int main(void)
{
int m, n, t;
while (scanf("%d %d", &m, &n) != EOF)
{
int sum1 = 0, sum2 = 0; //sum的值每次都应该初始化
if (m > n)
{
t = m;
m = n;
n = t;
}
for (int i = m; i <= n; i++)
{
if (i % 2 == 0)
sum1 += i * i;
else
sum2 += i * i * i;
}
printf("%d %d\n", sum1, sum2);
}
return 0;
}
运行结果: