从0学习编程——C语言基础

数据类型

为什么对数据进行分类:节约存储空间,提高运行速度。

整型

类型字节数范围
(signed) char1-128~127
(signed) short2-32678~32767
(signed) int4正负20亿
(signed) long4/8(电脑位数决定)正负20亿/9开头19位整数
(signed) long long89开头19位整数
unsigned char10~255
unsigned short20~65535
unsigned int40~40亿
unsigned long4/80~40亿/1开头20位整数
unsigned long long81开头20位整数

浮点

类型字节
float4
double8
long double12/16

注意:采用科学计算法,二进制与真实数据之间需要翻译,因此计算整数要比整型要慢。小数点后六位有效。

模拟

char

字符其实就是符号或图案,在内存中存储的是整数,需要显示时会根据ASCII表中的对应关系显示出相应的符号或图案。
‘\0’ 0 特殊字符,字符串的结束标志。
‘0’ 48
‘A’ 65
‘a’ 97

bool

布尔 先有了C语言之后才有 bool 类型,所有C语言不可能有真正布尔类型,stdbool.h头文件对布尔类型做的模拟。

可以使用sizeof计算类型的字节数。

变量

程序运行期间数值可以变化的叫变量,相当于存储数据的盒子。

定义

类型 变量名;
int num;
取名规则:
1、由字母、数字、下划线组成
2、不能以数字开头
3、不能与关键字重名。
4、见名知义(功能、类型、范围)
注意:变量的默认值是随机,为了安全要给初始化,一般初始化为0。

使用

赋值:num = 10;
参与运算:num * 100;

输入、输出

int printf(const char *format, ...);

功能:输出数据
format:双引号包含的格式信息(提示信息+占位符)
…:变量列表
返回值:输出字符个数

int scanf(const char *format, ...);

功能:输入数据
format:双引号包含的格式信息(占位符)
…:变量地址列表
返回值:成功输入变量的个数
注意:scanf需要的是变量类型和变量地址,变量地址=&变量名

类型占位符

C语言通过占位方式来传递变量的类型。
%hhu %hu %u %lu %llu
%hhd %hd %d %ld %lld
%f %lf %LF

常量

程序运行期间数值不能变化的叫常量

常数类型
100默认int
100llong
100lllong long
100uunsigned int
100luunsigned long
100lluunsigned long long
3.14默认double类型
3.14ffloat
3.14llong double

格式化输入输出

%nd 显示n个字符宽度,不够则补空格,右对齐
%-nd 显示n个字符宽度,不够则补空格,左对齐
%0nd 显示n个字符宽度,不够则补0
%n.mf 显示n个字符宽度(小数点算一位),不够则补空格,m表示小数点后的位数(四舍五入)
%g 不显示小数点后多余的0

运算符

自变运算符

++/-- 使变量的值自动加1或减1
前自变:立即有效
后自变:下一条语句才有效
注意:不要一行代码中多次使用自变运算符;

算术运算符

±* / %
整数/整数结果没有小数点。
/ % 除数不能为零,否则会产生浮点数例外,核心转储。

关系运算符

> < >= <= == !=
比较的结果是 0 或 1 比较结果还能继续参与运算。
10 < n < 100 结果永远为真,与数学中的运算规则不同。

逻辑运算符

&& || !
会先把运算对象转换逻辑值,0转换成假,非0转换为真。
A && B 一假即假
A || B 一真即真
!A 求反
&& || 具有短路特性,当左边的值可以确定表达式结果,右边不同计算。

三目运算符

运算对象有三个部分
A?B:C; 判断A的值如果为真执行B,如果为假执行C。
该语句不能使用流程控制语句,因为它必须要有运算结果。

赋值运算符

+= *= /= …
a += b; a = a+b;
a = b; a = ab;

位运算符

& | ~ ^ >> <<

类型转换

自动类型转换

只有相同类型的数据才能进行运算,不同类型数据转换成相同类型再进行云计算。
转换规则(以不丢失数据为基础,适当牺牲一些空间):
1、字少的向字节多的转。
2、有符号向无符号转。
3、整型向浮点型转。

强制类型转换

(类型)数据 有丢失数据的风险,慎重使用。

分支语句

if(表达式)//单分支
{
    表达式值为真,执行此处代码。
}

if(表达式)//双分支
{
    表达式值为真,执行此处代码。
}
else
{
    表达式值为假,执行此处代码。
}

if(表达式1)//多分支
{
    表达式1值为真,执行此处代码。
}
else if(表达式2)
{
    表达式2值为真,执行此处代码。
}   
else
{
    表达式1和2都为假,执行此处代码。
}

开关语句

switch(n)//运算结果必须是整型
{
    case val: // val必须是整常量 ,如果val等于n,则打开执行开关
        ... 
       break; // 关闭执行开关
    注意:如果每个cast后都有break,就形成了分支结构。
    default:// 如果所有的case都没有匹配成功则打开执行开关
}

case a … b: 判断一个范围,此为GNU编译器独有的语法,不建议使用。

eg:

输入一个月份,判断季节。
123 春天
456 夏天
789 秋天
10 11 12 冬天
other 输入的月份有误

#include<stdio.h>

int main()
{
char month = 9;
printf("输入一个月份:");
scanf("%hhd",&month);
switch(month)
{
	case 1 : printf("春天\n"); break;
	case 2 : printf("春天\n");break;
	case 3 : printf("春天\n");break;
	case 4 : printf("夏天\n");break;
	case 5 : printf("夏天\n");break;
	case 6 : printf("夏天\n");break;
	case 7 : printf("秋天\n");break;
	case 8 : printf("秋天\n");break;
	case 9 : printf("秋天\n");break;
	case 10 : printf("冬天\n");break;
	case 11 : printf("冬天\n");break;
	case 12 : printf("冬天\n");break;
	default : printf("error");
}
return 0;
}

循环语句

循环就是让一段代码反复执行,达到你想要的结果。
在介绍循环之前,我们先来了解下列两个语法。
break
跳出循环,但只能跳一层。
continue
结束本次循环,进入下次循环。

for

for一种比较灵活且危险(与其它循环相比)的一种循环。
一般使用一个变量来引导它的运行,这个变量就叫作循环变量。

for([1];[2];[3])
{
    [4];
}

1、给循环变量赋初值,C99标准才可以定义循环变量。
此处定义的循环变量,只能for循环内使用。
2、判断循环变量的是否到达边界。
4、被反复执行的代码,也叫循环体。
3、改变循环变量,防止变成死循环,一般对循环变量自加或自减。
eg
输入一个正整数,判断是否是素数

#include<stdio.h>
#include<stdint.h>

int main()
{
uint32_t num = 0;
printf("请输入一个正整数:");
scanf("%d",&num);
for(int i = 2; i < num; i++)
{
	if(0 == num%i)
	{
		printf("NO\n");
		return 0;
	}
}
printf("YES\n");
return 0 ;
}

while

while(条件) // 当条件为真执行循环体,为假时结束
{
    // 循环体
}

while循环相当于for循环的精简版本。
for循环负责解决明确知道循环次数的问题。
while负责解决只知道结束条件而不确定循环次数的问题。

do while

 do{
    循环体
}while(条件); 

先执行循环体,再判断循环条件,该循环至少执行一次。

循环嵌套

循环语句中包含循环语句。
外层循环执行一次,内存循环执行遍。

跳转语句

goto 可以在函数内任意跳转。
它可能会破坏已经设计好的分支或循环语句,因此绝大多数公司禁止使用。
但它在驱动编程时特别适合处理异常。

标签: // 位置
goto 标签;

eg
不使用循环计算N的阶乘

#include<stdio.h>

int main()
{
int i = 1, num = 0;
printf("请输入一个整数:");
scanf("%d",&num);
loop:
	if(num)
	{
		i *= num;
		num--;
		goto loop;
	}
	else
	{
		printf("%d",i);
	}
}

数组

什么是数组

变量的组合,是一种批量定义变量的方式。

一维数组

定义

类型 数组名[数量];
int arr[5];

使用

数组名[下标];

下标

从零开始,范围:0~数量-1。

遍历

与for循环配合,使用循环变量i当作数组的下标。

初始化

类型 数组名[数量] = {1,2,3,4,5,…};

1、数组与普通变量一样默认值是随机的,为了安全要对进行初始化。
2、这种初始化语法只能在定义数组时使用,而且必须使用常量初始化。
3、初始化数据过多,编译器会丢弃并产生警告。
4、初始化数据不够,编译器则会补0。
5、初始化数组时长度可以省略,编译器会自动统计数据的个数然后告诉数组。
计算数组长度:sizeof(arr)/sizeof(arr[0]) = 数组的长度

越界

为了程序的运算效率是不会检查数组的下标。
数组越界的后果:
1、一切正常。
2、段错误
3、脏数据
eg
定义一个长度为10的数组并初始化,找出数组中第二个大的值

#include<stdio.h>
int main()
{
int arr[10]={56,43,5,2,0,10,2,5,23,54};
int m[2]={arr[0] , arr[1]} , t = arr[0];
if(m[0] < m[1])
{
	t=m[0];
	m[0]=m[1];
	m[1]=t;
}
for(int i=0; i<10; i++)
{
	if(arr[i] > m[0])
	{
		m[1] = m[0];
		m[0] = arr[i];
	}
	else if(arr[i] > m[1] && arr[i] < m[0])
	{
		m[1] = arr[i];
	}
}
printf("%d\n",m[1]);
}

二维数组

定义

类型 数组名[行数][列数];
int arr[3][5];
对应的下标:
[0,0][0,1][0,2][0,3][0,4]
[1,0][1,1][1,2][1,3][1,4]
[2,0][2,1][2,2][2,3][2,4]

使用

数组名[行下标][列下标]
行下标:0 ~ 行数-1
列下标:0 ~ 列数-1

遍历

需要与双层for循环配合,外层循环负责遍历行,内层循环负责遍历列。

 for(int i=0; i<3; i++)
    {
        for(int j=0; j<5; j++)
        {
            printf("%d ",arr[i][j]);
        }
        printf("\n");
    }

初始化

类型 数组名[行数][列数] = {{第一行},{第二行},{第三行}};
eg
定义一个5*5的数组,找出其中的最小值下标,计算周围数字的和是多少。

#include<stdio.h>
int main()
{
int sum=0;
int arr[5][5] = {
{1,2,3,4,5},
{4,5,6,7,8},
{1,8,4,2,10},
{0,2,5,4,6},
{12,2,3,6,5}
};
int min = arr[0][0] , min_i = 0,min_j = 0;

//找出最小值的下标
for(int i=0;i<5; i++)
{
	for(int j=0; j<5; j++)
	{
		if(arr[i][j] < min)
		{
			min = arr[i][j];
			min_i = i;
			min_j = j;
		}
	}
}

//利用循环将最小值周边的值相加
for(int i=min_i-1; i <= min_i+1; i++)
{
	for(int j=min_j-1; j <= min_j+1; j++)
	{
		if(i<0 || j<0 || i>4 || j>4)
		{
			continue;
		}
		else
		{
			sum += arr[i][j];
		}
	}
}
sum -= arr[min_i][min_j];

	printf("%d",sum);
}

变长数组

定义数组时使用变量当作它长度,在代码编译期间数组的度是不确定的,当执行到数组的定义语句时它的长度才家有确定下来,一旦确定就无法更改了。
int a [n][n];
优点:可以根据实际情况来确定数组长度达到节约内存目的。
缺点:不可以初始化

位运算符

A & B 按位相与
01011010 0x5A
11000011 0xC3
--------------------
01000010 0x42
A | B 按位或
01011010 0x5A
11000011 0xC3
--------------------
11011011 0xDB
~A 按位求反
01011010 0x5A
10100101 0xA5
A ^ B
01011010 0x5A
11000011 0xC3
--------------------
10011001 0x99
A << n 把A补码左移n位,左边的丢弃,右边补0
01011010 << 4
10100000
A >> n 把A补码右移n位,右边的丢弃,左边补符号位
11000011 >> 4
11111100

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值