Bootstrap

自学C语言——数据类型和变量(二)

接上一篇     自学C语言——C语言常见概念(二)&数据类型和变量(一)

4.变量

有了类型就可以创建变量

C语言中把经常变化的值称为变量,不变的值称为常量。

data_type name;
   |        |
   |        |
数据类型   变量名

创建变量

#include <stdio.h>
{
int num;
int age;//整型变量
int weight;
short n;
char ch;//字符变量
double dododo;//浮点型变量

return 0;
}

向内存申请空间数据类型说的算

变量在创建时给一个初始值叫初始化。

int age = 18;
int weight;
short n;
char ch = 'x';

变量的分类

全局变量:大括号{}外部,整个工程中都可以使用

局部变量:大括号{}内部,只能在自己所在的局部范围使用

int b = 10;//全局变量
int main()
{
int a = 100;//局部变量
printf......
}

原则:局部变量优先,必须使用全局变量的时候再使用。

当全局变量和局部变量名字相同的情况下,局部变量优先。

补充

内存区域的划分(栈区、堆区、静态区)

栈区:局部变量

堆区:malloc、calloc、realloc、free......动态内存管理

静态区:全局变量

在VS中,如果一个局部变量没有初始化,则不让使用,局部变量必须初始化

本质上一个局部变量不初始化的话,它的值是随机值

在 VS中,如果一个全局变量没有初始化,它的默认值为0

5.算数操作符

算数操作符+-*/%也称双目操作符

+和-

int main()
{
printf("%d\n",3 + 5);
return 0;
}
//运行结果为8
int main()
{
int a = 3;
int b = 7;
int m = a-b;
printf("%d\n",m);
return 0;
}
//运行结果为-4

 有两个操作数的操作符也叫双目操作符

*

int main()
{
printf("%d\n",3*5);
return 0;
}
//运行结果为15

/

两端都是整数除法得到的也是整数

int main()
{
printf("%d\n",8/4);
return 0;
}
//运行结果为2
int main()
{
printf("%d\n",6/4);
return 0;
}
//运行结果为1

 保留商,不显示小数

除号的两端都是整数的时候,得到的是商

除号的两端只要有一段是小数,得到的就是小数

int main()
{
printf("%d\n",6/4.0);
return 0;
}
//运行结果为1.500000

%f——打印小数

%lf——打印double类型小数

默认形况下打印6位小数

%

用于求两数相除的模(余)数。之能用于整数,不能用于浮点数。

int main()
{
printf("%d\n",6%4);
return 0;
}
//运行结果为2

负数求模的规则:结果的正负号由第一个运算数的正负号决定。

int main()
{
printf("%d\n",11%-5);//1
printf("%d\n",-11%-5);//-1
printf("%d\n",-11%5);//-1
return 0;
}

6.赋值操作符:=和复合赋值

 =

创建变量时给的值叫初始化,在变量创建好后,再给一个值,叫赋值。

int a = 100;//初始化
a = 200;//赋值

赋值操作符=可以随时给变量赋值。

连续赋值

int a=3;
int b=5;
int c=0;
c = b= a+3;//连续赋值,从右往左依次赋值

建议分开写

int a=3;
int b=5;
int c=0;
b= a+3;
c = b;

复合赋值

a = a + 5;
a += 5;

a = a - 1;
a -= 1;

也有*=、/=、%=以及>>=、<<=、&=、|=、^=

7.单目操作符:++、--、+(正号)、-(负号)

 只有一个操作数的操作符

++和--

int main();
{
int a = 4;
//a = a + 1;
//a += 1;
//a++;//后置++
++a;//前置++
return 0;
}

以上三种方式输出均为5,前置后置都是 自加1

前置++和后置++的区别

后置++:先使用,再+1

前置++:先+1,再使用

int a = 4;
int b = a++;//b=a,a=a+1
printf("%d\n", a);//5
printf("%d\n", b);//4

int a = 4;
int b = ++a;//a=a+1,b=a
printf("%d\n", a);//5
printf("%d\n", b);//5
前置--和后置--的区别

同上,前置和后置都是 自减1

+和-

+号可以省略

int main()
{
int a = -10;
int b = +10;
int c = -a;
printf("%d\n", c);

return 0;
}
//输出10

8.强制类型转换

 直接写出的字面值浮点数,编译器默认识别为double 

int a = 3.14;
int main();
{
double r = 6/4.0;
printf("%lf\n",r);
return 0;
}
//输出1.500000

int main();
{
double r = 6/(double)4;
printf("%lf\n",r);
return 0;
}
//输出1.500000

 浮点数强制转化 int类型 忽略小数位,只保留整数部分

int main()
{
int a =(int)3.14;
printf("%d\n", a);
return 0;
}
//输出3

//float 单精度浮点数   4个字节

//double 双精度浮点数   8个字节

9.scanf和printf介绍

printf——输出函数

基本用法

printf——printf format按照指定的格式在屏幕上打印

不会自动换行,需要加\n

使用库函数:#include <stdio.h>

占位符介绍

printf()可以在输出文本中指定占位符,占位符(可以用其他值占用)

int main()
{
printf("there are %d apples\n  ", 3);
return 0;
}
//输出there are 3 apples

 占位字符串用%s,"zhangsan"

占位符的第一个字符一律为百分号%

文本里可以有多个占位符,按顺序对应起来,如果有n个占位符,printf()的参数应该有n+1【格式串也算一个参数】个,如果参数个数小于占位符,printf()会输出内存中的任意值。

int main()
{
printf("%s says it is %d o'clock\n","zhangsan",8);
return 0;
}
//输出zhangsan says it is 8 o'clock
占位符列举 

%A:十六进制浮点数,字母输出为大写。

%a:十六进制浮点数,字母输出为小写。

%c:字符。//char

%d:十进制整数。//int

%e:科学计数法的浮点数,指数e为小写。

%E:科学计数法的浮点数,指数E为大写。

%i:基本等同于%d。

%f:小数。包含float和double类型。//float——%f  double——%lf

%g:6个有效数字的浮点数,炒货6个会自动转换成科学计数法,指数部分e为小写。

%G:同上,不过指数部分E为大写。

%hd:十进制short int 类型。

%ho:八进制short int 类型。

%hx:十六进制short int 类型。

%hu:unsigned short int 类型。

%ld:十进制long int 类型。

%lo:八进制long int 类型。

%lx:十六进制long int 类型。

%lu:unsigned long int 类型。

%lld:十进制long long int 类型。

%llo:八进制long long int 类型。

%llx:十六进制long long int 类型。

%llu:unsigned long long int 类型。

%Le:科学计数法表示的long double 类型浮点数。

%Lf:long double 类型浮点数。

%n:已输出的字符串数量。该占位符本身不输出,只将值存储在指定变量之中。

%o:八进制整数。

%p:指针。

%s:字符串。

%u:无符号整数(unsigned int)。

%x:十六进制整数。

%zd:size_t类型。

%%:输出一个%。


printf输出格式
限定宽度
int main()
{
printf("%5d\n",123);
return 0;
}
//输出:  123

限定最小宽度,超过可以, +右对齐左边补空格(默认),-左对齐右边补空格。

打印小数时," . "也算一个占位,小数默认后边六位。

int main()
{
printf("%+d",8);
return 0;
}
//输出:+8

 %+d,d为-8时输出-8

限定小数位

%.2f——小数点后保留两位

#include <stdio.h>
int main()
{
	printf("%.8f\n", 12.345);
	return 0;

}

会四舍五入,%.2d,d=12.347,输出12.35

可以同时限定最小宽度和小数位

printf("%12.2f\n",12.457); 
=
printf("%*.*f\n",12,2,12.457)
输出部分字符串 

%s默认全部输出

可以用%.5s指定输出长度(前5个字符),空格也算一个字符

#include <stdio.h>
int main()
{
	printf("%.5s", "hello whord");
	return 0;

}
//输出hello

 %.7s,输出:hello w

scanf——输入函数

#include <stdio.h>
int main()
{
	int n = 0;//初始化
	printf("请输入成绩:");
	scanf("%d", &n);//&——取地址
	printf("成绩是:%d\n", n);
	return 0;

}

#define _CRT_SECURE_NO_WARNINGS 1 (加前边防止报错)

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
	int n = 0;
	scanf("%d", &n);//&取地址操作符
	printf("n = %d\n", n);
	return 0;
}

基本用法 

scanf函数用于读取键盘输入

运行到scanf的时候会等待输入,按下回车后,处理输入将其存入变量。

原型定义在头文件stdio.h

语法同printf()类似

scanf("%d",&i);

 第一个参数叫格式字符串,里边放置占位符。后边是变量,可以存在多个变量。

int main()
{
	int i = 0;
	int j = 0;
	float x = 0;
	float y = 0;
	scanf("%d%d%f%f", &i, &j, &x, &y);
	printf("%d %d %.1f %f\n", i, j, x, y);
	return 0;
}

处理占位符时,会自动过滤空白字符,包含空格、制表符、换行符......

处理输入原理:用户的输入先放入缓存,按下回车键后,按照占位符对缓存进行解读。解读用户输入时,会从上一次遗留的第一个字符开始,知道读完缓存,或遇到第一个不符合条件的字符为止。

多个变量时可以一起输出也可以分开输出,可以一起输入也可以分开输入。

补充:

-4.0e3 = -4.0*10^3

0.45在内存中无法精确保存

scanf返回值

返回值为一个整数,表示成功读取到数据的个数

没有读取任何项或读取失败的话返回 0

如果在成功读取任何数据之前,发生了读取错误或者遇到读取到文件结尾,则返回常量EOF(-1)

int main()
{
	int a = 0;
	int b = 0;
	int c = 0;

	int ret = scanf("%d%d%d", &a, &b, &c);

	printf("ret = %d\n", ret);
	printf("a=%d b=%d c=%d\n", a, b, c);

	return 0;
}

 输出:

100 200 300
ret = 3
a=100 b=200 c=300

100 200 xyz
ret = 2
a=100 b=200 c=0

ctrlZ ctrlZ ctrlZ
ret = -1
a=0 b=0 c=0

//竞赛的OJ题目中,读取输入数据的时候会用到stanf返回值的判断

int main()
{
	int a = 0;
	int b = 0;
	int c = 0;

	int ret = scanf("%d%d%d", &a, &b, &c);

	if (ret == 3)
	{
		printf("a=%d b=%d c=%d\n", a, b, c);
	}
	else
	{
		printf("ret = %d\n", ret);
	}

	return 0;
}

 输出:

1 a 2

ret = 1

占位符

scanf()与printf()的占位符基本一致。

。。。  

%[ ]:在方括号中指定一组匹配的字符(%[0-9]),遇到不在集合中的字符,匹配会停止。

除了%c以外,其他占位符都会自动忽略起首的空白字符

%c会读取空格

如果要强制跳过字符前的空白字符,要在%c前加一个空格,表示跳过零个或多个空白字符,读取非空白字符。

scanf(" %c",%ch)

占位符%s:从当前第一个非空白字符开始读读取。直到遇到空白字符(空格,换行符,制表符等)为止。

scanf()遇到%s占位符时,会在字符串变量末尾存储一个空字符/0

int main()
{
	char arr[10];
	scanf("%s", arr);
	printf("%s\n", arr);

	return 0;
}

 输出:

123 123

123

int main()
{
	//输入的是字符串
	//字符串可以存放在字符数组中
	char arr[5];
	scanf("%s", arr);//arr是数组,数组名就是地址,所以不需要取地址
    printf("%s\n",arr)
	return 0;
}

 输出:

abc

abc

abcdefgh

abcdefgh(会报错)//scanf不安全的地方,读取数据的时候不会看目标空间是否足够

所以,储存字符串时,使用%s占位符时,应该指定读入字符串的最长长度,即写成%[m]s,其中的[m]时一个整数,表示读取字符串的最大长度,后面的字符将被丢弃。

int main()
{
	char name[11];
	scanf("%5s", name);
	printf("%s\n", name);

	return 0;
}

 输出:

123456789

12345

赋值忽略符*
int main()
{
	int year = 0;
	int month = 0;
	int day = 0;
	scanf("%d%d%d", &year, &month, &day);
	printf("%d-%d-%d\n", year, month, day);

	return 0;
}

 输出:

2021-6-1
2021--6--1//-6和-1

int main()
{
	int year = 0;
	int month = 0;
	int day = 0;
	scanf("%d-%d-%d", &year, &month, &day);
	printf("%d-%d-%d\n", year, month, day);

	return 0;
}

 输出:

2021-6-1
2021-6-1

 %号后面加*,表示读取完之后扔掉(上方 - 用%c代替)

int main()
{
	int year = 0;
	int month = 0;
	int day = 0;
	scanf("%d%*c%d%*c%d", &year, &month, &day);
	printf("%d-%d-%d\n", year, month, day);

	return 0;
}

输出:

2021/8/8
2021-8-8 

——————————End——————————

;