C语言入门
实例–方程根
掌握内容:
1.定义变量
2.c语言中,方程根的表示是sqrt 并且导入#include <math.h>文件包
#include<stdio.h>;
#include <math.h>
//首先定义变量
//C语言的根号是:sqrt() 需要导入<math.h>的包
int main03(void) {
//把三个系数保存在计算机
int a = 1;//=不等于相等,而是赋值 ==才是相等
int b = 5;
int c = 6;
float delta;//存放的是b*b-4ac
delta = b * b - 4 * a * c;
float x1;//其中一个解
float x2;
if (delta > 0) {
x1 = (-b + sqrt(delta)) / (2 * a);
x2 = (-b - sqrt(delta)) / (2 * a);
printf("两个解,x1=%f,x2=%f\n",x1,x2);
}
else if (delta == 0) {
x1 = (-b) / (2 * a);
x2 = x1;//右边赋值给左边
printf("一个解,x1=x2=%f\n",x1);
}
else
{
printf("无解");
}
return 0;
}
//ax ^ 2 + bx + c = 0;
//对标称有一定的概念
数据类型
基本数据类型:
整数
整形 int --- 4
短整型 short int --- 2
长整型 long int ---8
浮点数
单精度浮点数 --float --4
双精度浮点数 --double --8
字符
char --1
#include<stdio.h>;
int main(void) {
//int i = 10;
//printf("%d\n", i);
char i = 'A';
printf("%c\n", i);
return 0;
}
复合类型数据
结构体
枚举
共用体
键盘的输入以及输出
Prinf()&&Scanf():
Scanf() ----【通过键盘将数据输入到变量中】
两种用法:
用法一:Scanf(“输入控制符”,输入参数)
功能:将从键盘输入的字符转化为输入控制符所规定格式的数据,然后存入以输入参数的值为地址的变量当中。
用法二:Scanf(“非输入控制符 输入控制符”,输入控制符)
功能:将从键盘输入的字符转化为输入控制符所规定格式的数据,然后存入以输入参数的值为地址的变量中
注意:非输入控制符必须原样输入
#include <stdio.h>
int main(void) {
int i;
scanf("%d", &i);//&i表示i的地址,&是一个取地址值
printf("i=%d\n", i);
return 0;
}
#include<stdio.h>
int main(void) {
int i, j, k;
printf("请输入三个数,中间以逗号相隔");
scanf_s("%d,%d,%d", &i, &j, &k);
printf("i=%d,j=%d,l=%d\n", i, j, k);
return 0;
}
如何使用Scanf编写出高质量的代码?
1.使用Scanf之前最好先使用printf提示用户以什么样的方式来输入
2.Scanf中尽量不要使用非控制输入符,尤其是\n
3.应该编写代码对用户的非法输入做适当的处理[非重点]
while((ch=getchar())!=’\n’)
continue;
#include<stdio.h>
int main(void) {
int i;
char ch;
//吃苦以及静心
scanf_s("%d", &i);//把从键盘取出的字符以十进制的方式复制给i
printf("i=%d\n", i);//把i里面的内容以十进制的内容进行输出,所以不需要加地址值
scanf_s("%c", &ch);
printf("ch=%c\n", ch);
return 0;
}
运算符的分类
两个数字进行替换:i-5,j-6 ---->i=6;j=5
#include<stdio.h>
int main(void) {
int i = 3;
int j =5;
// i = j; I=5
// j = i;J=5
//互换变量是最简单的以及最常用的 记住!
//正确的互换I与J的方法:
int t;//定义临时变量
t = i;
i = j;
j = t;
printf("i=%d,j=%d\n", i, j);
return 0;
}
三个数字以从大到小的方式进行排序
#include<stdio.h>
int main(void) {
int a, b, c;
printf("请输入三个整数(中间以空格分隔):");
scanf_s("%d %d %d", &a, &b, &c);
int t;
//编写代码完成a是最大值,b是中间值,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("%d %d %d\n",a,b,c);
return 0;
}
一些说明
//算法题–>把答案看懂并且背诵
//看编程书一定要有答案,并且可执行进行运行 重点是看懂程序
//判断一个数是否是素数
//判断一个数是否是回文数
//编程实现求一个十进制数字的二进制形式
//求把一个数字的每位是奇数的数字取出来并且形成新的数字
//求一个数倒过去的数字
//必须借助敲代码出错 能看懂但是敲错了 以及改代码 正确的思路:—>看代码—>敲代码---->改代码
//如何看懂一个程序:第一步:1.流程 2.每个语句的功能 3.试数 对一些小算法的程序:尝试自己去编程,如果自己解决不了,就看答案,关键❤ 是把答案看懂,看懂之后自己尝试修改程序,并且知道修改程序后造成不同结果的原因
//照着答案去敲–>调试错误–>自己独立,不看答案敲出来
//函数 流程 指针
IF语句
If语句中常见的一些错误:
-
空语句的问题
if(3>2) ;
-
两个条件都满足,显示第一个
-
else if(if不能去掉)
-
分号的
#include<stdio.h>
int main(void) {
if (3 > 2)
printf("哈哈哈哈哈哈\n");
else if(3>1)
printf("AAAAAAAAAAAAA\n");
else
printf("BBBBBBBBBB\n");
return 0;
}
循环
为什么需要循环?
For循环
1.求1-10之间的奇数之和
- 了解For循环的流程是什么 1–>2–>4–>3
- sum得赋值
- 循环次数的计算
不说了,直接上代码(╹▽╹)
#include<stdio.h>
int main(void) {
int i;
int sum=0;//如果不赋值还是那个数
int count = 0;
for (int i = 1; i < 10000; i += 2) {//i+=2 ---i=i+2
sum = sum + i; //sum+=i ----sum=sum+i
count++;
}
printf("%d\n", sum);
printf("%d\n", count);
}
2.1-10间能被3整除的总数以及循环次数
#include<stdio.h>
int main(void) {
int i;
int sum = 0;
int count = 0;
for (int i = 3; i <= 10; i++) {
if (i % 3 == 0) //如果能被3整除
sum = sum + i;
count++;
//printf("sum=%d\n", sum); //这里是赋值
}
printf("sum=%d\n", sum);//跳出for循环才是sum
printf("一共循环了:%d\n", count);
return 0;
}
强制数据类型转换
- 格式:(数据类型)(表达式)
- 功能:把表达式的值强制转化为前面所执行的数据类型
- 例子:
(int)(4.5+2.2) 6
(float)(5) 5.000000
❤ sum=sum+(float)(1/i) 这样写是不对的 因为(1/i)是整形,没有小数位
#include<stdio.h>
int main(void) {
int i;
float sum = 0;
for (int i = 1; i <= 100; i++) {//i<101
sum = sum + 1 / (float)(i);
//sum=sum+(float)(1/i) 这样写是不对的 因为(1/i)是整形,没有小数位
}
printf("sum=%f\n", sum);
return 0;
}
浮点型
float与double都不能保证可以精确的存储的一个小数
为什么循环中更新的变量不能定义成浮点型?
回答: 因为不饿能保证所有的狮子都可以准确的进行存储
#include<stdio.h>
int main(void) {
float i;
float sum = 0;
for (i = 1.0; i <= 100; i++) {
sum = sum + 1/i;
}
printf("sum=%f\n", sum);
return 0;
}
For循环练习
#include<stdio.h>
int main(void) {
int i ;
int sum = 0;
for (int i = 1; i < 101; i++) {
if (i % 2 == 1) {
sum += i;//sum=sum+i;
}
else if (i % 2 == 0) {
sum += i;//sum=sum+i;
}
}
printf("sum=%d\n", sum);
return 0;
}
1-100之间的奇数和以及偶数和循环次数,以及个数
#include<stdio.h>
int main(void) {
int i ;
int sum = 0;
int count = 0;
float avg;
for (int i = 1; i < 101; i++) {
if (i % 2 == 1) {
sum += i;//sum=sum+i;
count++;
avg = (float)sum / count;//sum是整形
}
else if (i % 2 == 0) {
sum += i;//sum=sum+i;
}
}
printf("sum=%d\n", sum);
printf("count=%d\n",count);
printf("avg=%f\n", avg);
return 0;
}
多层For循环嵌套
for(1;2;3)
语句A;
执行的流程【❤】
单个for循环的语句
多个for循环的嵌套语句
for(1;2;3) ①
for(4;5;6)②
A;③
B;④
两个语句:1-2-3 && 4
顺序:1–>2–>4–>5–>A–>6–>5–>A–>6–>!5–>3–>
for(1;2;3) ①
for(4;5;6){②
A;③
B;④}
整体一个语句
for(7;8;9)
for(4;5;6)
{
A;
B;
for(4;5;6)
C;
}
整体一个语句
顺序:1-->2-->4-->5-->A-->6-->5-->A-->6-->!5-->3-->
break与continue
break:
break如果用于循环是用来终止循环
break如果用于switch,则是用来终止switch
break不能直接用于if,除非If属于循环内部的一个子句
例子:
for (int i = 0; i <= 10; i++)
if (3 > 2)
break x;//终止的是for循环
#include<stdio.h>
int main(void) {
int i, j;
for (i = 0; i < 2; i++) {
for (j = 1; j < 4; j++)
break;//break只能终止距离他最近的循环
printf("NB\n");
}
return 0;
}
在多层的switch嵌套中,break只能终止距离他最近的switch
Continue
用于跳过本次循环余下的语句,转去判断是否需要执行下次循环
for (1; 2; 3)
A;
B;
continue;//执行完该语句之后,执行3,跳过C D
C;
D;
while(表达式)
A;
B;
continue;//执行完该语句后会执行表达式
C;
D;
流程控制 总复习
顺序
选择
循环
数组
为什么需要数组?
为了解决大量同类型数据存储和使用情况
为了用来模拟现实情况
#include<stdio.h>
int main(void) {
int a[5] = { 1,2,3,4,5 };//a表示数组名,5表示元素的个数,并且这五个元素分别是a[0],a[1],a[2]......
int i;
for (int i = 0; i < 5; i++)
printf("%d\n", a[i]);
//printf("%d\n", a[100]);--没有该元素
return 0;
}
数组的分类
一维数组
怎样定义一维数组:
为n个变量连续分配空间
所有的数据类型必须是一样的
所有变量所占的字节大小必须大小相等
例子:int a[5];
有关一维数组的操作:
初始化
完全初始化
int a[5]={1,2,3,4,5};
不完全初始化,为初始化的部分为0
int a[5]={1,2,3}
不初始化
int a[5];
清零
int a[5]={0};
错误写法:
int a[5];
a[5]={1,2,3,4,5}//错误
只有在定义数组的同时才可以整体赋值,其他情况下整体赋值都是错误的
int a[5]={1,2,3,4,5}
a[5]=100//没有a[5]这个元素
int a[5]={1,2,3,4,5}
int b[5];
错误写法:
b=a;//error
正确写法:
for(i=0;i<5;i++)
a[i]=b[i];
m
赋值
排序
求最大值/最小数值
倒置
#include<stdio.h>
int main12(void) {
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;
}
二维数组
int a[3][4];
总共是12个元素,可以当做3行4列看待,这12个元素的名字依次是
a[0][0] a[0][1]a[0][2]a[0][3]
a[1][0] a[1][1]a[1][2]a[1][3]
a[2][0] a[2][1]a[2][2]a[2][3]
#include<stdio.h>
int main13(void) {
int a[3][4] = {
{1,2,3,4},
{5,6,7,8},
{9,10,11,12}
};
//输出他的内容;
int i, j;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++)
printf("%-5d ",a[i][j]);//横着输入 -5表示左对齐
printf("\n");//在遍历四个数字之后 \n
}
return 0;
}
三维数组
C语言学习的第二个重点–函数
为什么需要函数
避免了重复性操作
有利于程序的模块化
#include<stdio.h>
void(max)(int i, int j) {
if (i > j)
printf("%d\n", i);
else
printf("%d\n", j);
}
int main(void) {
int a, b, c, d, e, f;
a = 1, b = 4, c = 6, d = 12, e = 14, f = 33;
max(a, b);
max(c, e);
return 0;
}
什么叫函数
逻辑上:能够完成特定功能的独立的代码块
物理上:
能够接收数据【当然也可以不接受数据】
能够对接受的数据进行处理
能够将数据处理的结果返回【当然也可以不返回任何值】
总结:函数是个工具,它是为了解决大量类似问题而设计的
函数可以当做是一个黑匣子
#include <stdio.h>
int f(void) {//括号中的void表示不能接收数据 函数返回的类型是int
return 10;//向主调函数返回10
}
void g(void) {//函数前面的void表示该函数没有返回值
// return 10; error与第八行行首的void矛盾
}
int main02(void) {
int j = 88;
j = f();
printf("%d\n", j);
//j = g();
return 0;
}
如何定义函数
函数的返回值 函数的名字(函数的形参列表){
函数的执行体
}
- 函数定义的本质是详细描述函数之所以能够实现某个特定功能的具体方法
- return 表达式;的含义
终止被调函数,向主调函数返回表达式的值
如果表达式为空,则只终止函数,不向被调函数返回任何值
void f(){
return;//return只用来终止函数,不向主调函数返回任何值
}
int f(){
return 10;//第一:终止函数 第二:向主调函数返回10
}
- 函数返回值的类型也称为函数的类型,因为如果,函数名前的返回值类型和函数执行体中的return表达式;中表达式的类型不同的话,则最终函数返回值的类型以函数名前的返回值类型为准
#include<stdio.h>
int f() {
return 10.5;//因为函数的返回值类型是int,所以最终f返回值的是10而不是10.5
}
int main03(void) {
int i = 99;
double x = 6.6;
x = f();
return("%d\n", x);
return 0;
}
break与return的区别
return是用来终止函数的,而不是终止循环的
break是用来终止循环跟swirch的
#include<stdio.h>
void f(void) {
int i;
for (int i = 0; i < 5; i++) {
printf("大家辛苦了!");
//break; 终止循环
return;//终止函数
}
printf("同志们辛苦了");
}
int main04(void) {
f();
return 0;
}
函数的分类
有参函数和无参函数
有返回值函数和无返回值函数
库函数和用户自定函数
值传递函数和地址传递函数
普通函数和主函数(main函数)
一个程序必须有且只能有一个主函数
主函数可以调用普通函数 普通函数不能调用主函数
主函数可以相互调用
主函数是程序的入口,也是程序的出口
注意的问题
函数调用和函数定义的顺序
如果函数调用写在了函数定义的前面,则必须加函数前置声明
函数前置声明:
1.告诉编译器即将可能出现的若干个字母代表的是一个函数
2.告诉编译器即将可能出现的若干个字母所代表的函数的形参和返回值的具体情况
3.函数声明是一个语句,末尾必须加分号 void f(void)
4.对库函数的声明是通过#include<库函数所在的文件的名字.h>来实现的
#include<stdio.h>
void f(void);//函数声明,分号不能丢掉
void g(void){
f();
}
int main(void){
f();
return 0;
}
void f(void){
printf("hhhh\n");
}
形参和实参
- 个数相同
- 位置一一对应
- 数据类型必须相互兼容
#include<stdio.h>
void f(int i) {//形参
printf("%d", i);
}
int main(void) {
f(5);//实参
return 0;
}
如何在软件开发中合理设计函数来解决实际的问题
一个函数的功能尽量独立,单一多学习,多模仿牛人的代码
函数时C语言的基本单位,类是JAV,C#,C++的基本单位
- 视频看完并且,补全代码
#include<stdio.h>
int main(void) {
int val;
int i;
int j;
scanf_s("%d", &val);
for (int i = 2; i < val; i++) {
//判断i是否属素数,是输出,否则不输出
for (j = 2; j < i; j++) {
if (0 == i % j)
break;
}
if (j == i)
printf("%d\n", i);
}
return 0;
}
常用的系统函数
《turboc 2.0实用大全》
double sqrt(double x)
求X的平方根
int abs(int x)
求X的绝对值
double fabs(double x)
求X的绝对值
专题:递归
参考:数据结构
变量的作用域和存储方式
按作用域分:
全局变量
在所有函数外部定义的
#include<stdio.h>
int k = 100;
void f(int i) {
int j = 20;
printf("%d\n", k);
}
int main(void) {
int i = 20;
f(88);
return 20;
}
局部变量
在一个函数内部定义的变量或者函数的形参 都统称为局部变量
按变量的存储方式
void f(int i) {
int j = 20;
}
静态变量
自动变量
寄存器变量
C语言的灵魂-- 指针
操作系统与计算机组成原理的基础知识
计算机核心的课程–数据结构
- 指针就是地址,地址就是指针
- 指针变量是存放地址的变量
- 指针和指针变量是两个不同的概念
- 但是要注意:通常我们叙述时会把指针变量简称为指针,实际上他们的含义并不一样
#include<stdio,h>
int main(void){
int * p;//p是变量的名字,int *表示p变量存放的是int类型变量的地址------->int *是在一起的
int i=3;
p=&i;//语法无误
P=i;//error,因为类型不一致,P只能存放int类型变量的地址,不能存放int类型的变量的值
p==55;//error 原因同上
return 0;
}
#include<stdio.h>
int main(void){
int *p;
//int *p 不表示定义了一个名字叫做*p的变量
//int *p 应该这样理解:p是变量名,p变量的数据类型是 int *类型
// 所谓int*:类型就是存放int变量地址的类型
int i=3;
p=&i;//P保存了i的地址,因此p指向i
//p不是i,i也不是p,更准确的来说,修改p的值不影响i的值,修改i的值也不影响p的值
//如果一个指针变量指向了某个普通变量,则*指针变量就完全等价于普通变量
//例子;如果p是个指针变量,并且p存放了普通变量i的地址 则p指向了普通变量i *p就完全等同于i
//或者说:在所有出现*p的地方都可以替换成i
// 在所有出现i的地方都可以替换成*p
//*p 就是以p的内容为地址的变量,
return 0;
}
-
操作系统
-
计算机组成原理
指针的重要性:
表示一些复杂的数据结构
快速的传递数据
使函数返回一个以上的值
能直接访问硬件
能够方便的处理字符串
是理解面向对象语言中引用的基础
总结:指针是C语言的灵魂
指针的定义
内存单元的编号
从零开始的非负整数
指针的分类
1.基本类型指针
2.指针和数组
3.指针和函数
4.指针和结构体
5.多级指针