1 标识符的书写
标识符采用如下两种方式书写:驼峰式,下划线式。
2 scanf()
标准C函数有输入输出缓冲区,Linux的函数无此。当使用scanf读取,输入非法时,使用scanf(“%*[^\n]”);scanf(“%*c”);从而不影响对后面读取数据的影响.
特别注意运行时,scanf的输入格式,空空格,打不打逗号。
scanf.c
#include<stdio.h>
int main() {
int num = 0, num1 = 0;
printf("请输入一个数字:");
scanf("%d",&num);
scanf("%*[^\n]");
scanf("%*c");
printf("请输入一个数字:");
scanf("%d",&num1);
printf("num是%d,num1是%d\n",num, num1);
return 0;
}
inbuf.c
#include <stdio.h>
int main() {
int num = 0;
for (;;) {
printf("请输入一个数字:");
if (scanf("%d", &num)) {
scanf("%*[^\n]");
scanf("%*c");
break;
}
else {
scanf("%*[^\n]");
scanf("%*c");
}
}
printf("num是%d\n", num);
return 0;
}
3 代码书写格式
一些需注意的代码格式:
关键字后面接空格,函数名后面不要空格
, ;不空格且向前靠拢
&& || != == >= <= = + - * / 这些操作符前后都要空格
++ 自减 [] . -> 前后都不空格
4 字符类型
字符类型是一种数据类型,其中包含了256个不同的字符。字符类型的名称是char,这种类型的数据使用两个单引号表示,例如‘a’表示字符a
ASCII码表记录了字符和数字之间的对应关系
‘a’——97(0x61)
‘A’——65(0x41)
‘0’——-48
所有字符分成两组,每组包含128个不同的字符,一组固定被转换成0到127之间的数字,另一组在某些计算机上被转换成-1到-128之间的数字,在另外一些计算机上被转换成128到255之间的数字
字符类型数据最好不要当成数字使用
unsigned char也是一种数据类型,表示无符号字符型,这种类型的数字范围固定从0到255,无符号字符类型数据可以当成数字使用
根据ASCII码表有如下结论:‘c’-‘a’=’C’-‘A’ ‘c’-‘a’=’2’-‘0’=2-0
‘\n’:换行符(表示前后内容分散在两个不同的行中)
‘\r’:回车符(表示后面的内容从行首开始)
‘\t’:制表符(保证后面的内容从某一段的开头开始输出)
‘\’:代表\
‘\”’:代表“
‘\”:代表‘
5 短整型与长整型
短整数也是一种数据类型,它的名称是short,短整数类型一共包含65536个不同的整数,范围是从-32768到32767
unsigned short是无符号短整数类型,无符号短整数类型的数字范围是从0到65536为止
长整数也是一种数据类型,它的名称是long,long类型包含2的32次方个不同的数字,其中一半是负数,另一半是非负数
unsigned long表示无符号长整数类型,数字范围是从0到2的32次方减一为止
在我们使用的计算机和编译器环境下int和long是一样的
6 浮点型
单精度浮点类型是一种表示带小数点数字的数据类型,它的名字是float
双精度浮点类型也是一种数据类型,它的名字是double
程序中不带小数点的数字都被看成是int类型的数字
程序中在不带小数点的数字后面加一个u表示这个数字是unsigned int类型的
程序中带小数点的数字被看成是double类型的数字
程序中在带小数点的数字后面加上一个f表示这个数字是float类型的
7 占位符匹配关系
char—————%c
short————–%hd
unsigned short—–%hu
long—————%ld
unsigned long——%lu
int—————-%d
unsigned int——-%u
float————–%f或%g
double————-%lf或%lg
打印字符串——————%s
占位符特殊用法
%3d 数字占3个位置
%03d 数字占三个位置,空的位置用0补充
%-3d 占3个位置,数字从最左边的位置开始输出
%7.2f 一共占7个位置,小数点后占2个位置
打印地址用%p格式,是十六进制的
8 各数据类型占内存大小
计算机的内存被划分成很多字节,任意两个字节的大小一样
所有变量都是由一个或多个连续的字节构成的
char,unsigned char————-1个字节
short,unsigned short———–2个字节
long,unsigned long————-4个字节
int,unsigned int—————4个字节
float————————–4个字节
double————————-8个字节
9 sizeof()
sizeof关键字可以计算一个变量或某个数据类型占的字节个数
1、给出指定数据类型所占内存的字节,如果括号里是数据,则返回给定数据在内存中占用的字节数
sizeof(char)—–> 1
size(5)——>4
2、不会对括号内的表达式进行计算
例如:
int a=2;
printf(“%d\n”,sizeof(a++));//a=2
3、如果括号里有不同类型的数据,会按照数据类型最长的数据来进行返回。
sizeof(3+2.5)———->8
10二进制与其他进制间转换
二进制是一种表示数字的方式,每个数位上是0或者是1,每个位置上的1代表的数字都是2的整数次方,最右边的位置编号为0,向左依次递增,编号为n的位置上的1对应的数字是2的n次方
每个字节可以划分成八个二进制位
二进制转换十进制
0110 0011=2^6+2^5+2^1+2^0=64+32+2+1=99
0101 1101=2^6+2^4+2^3+2^2+2^0=64+16+8+4+1=93
十进制转换二进制
71 ** ***1
35 0*** ***1
17 00** ***1
8 000* ***0
4 0000 ***0
2 0000 0**0
1 0000 00*1
0 0000 0000
0100 0111
除以2取余倒着写
另一种从十进制转二进制的方法
103=64+32+4+2+1 2^7=128 2^6=64
八进制也是一种表示数字的方式
01100010=01 100 010=0142 八进制数前面加0
占位符%o可以让输出为八进制
十六进制也是二进制的另外一种表示方式
01100010=0110 0010=0x62
a—-10 b—-11 c—-12 d—-13 e—-14 f—-15
十六进制打印的占位符是%x或%X
负数的二进制是相反数的二进制按位取反后加一的结果(补码)
按位取反加一的方法可以计算任何一个二进制数字的相反数,不管是正还是负
有符号数字的最左边二进制位叫做符号位,0表示正数,1表示负数
所有有符号类型的最小数的二进制都是左边一个1右边很多0
整数类型变量之间互相赋值,会保留原有二进制不变,但在新数据中的解释方式会改变,从大空间变到小空间,会丢掉部分,从小空间扩到大空间,多的位要取决于原数,原数若无符号,则多的位全为0,若有符号,则多的位取决于符号位
MinGW是windows操作系统里的gcc
11贪吃蛇小程序
//这里,附一个简单的用c写的贪吃蛇的程序,小蛇不能增长
snake.c
#include<stdio.h>
#include<time.h>
#include<stdbool.h>
#define APPLE '@'
#define SNAKEHEAD '+'
#define SNAKETAIL '-'
#define SIZE 10
typedef struct {
int row;
int col;
}Pos;
typedef struct {
Pos head;
Pos tail;
}Snake;
Snake snake;
Pos apple;
bool is_same(const Pos* pFirstPos, const Pos* pSecondPos) {
if ((pFirstPos->row == pSecondPos->row) && (pFirstPos->col == pSecondPos->col)) {
return true;
}
else {
return false;
}
}
void init_snake() {
int row = rand() % (SIZE - 2);
int col = rand() % (SIZE - 2);
int direction = rand() % 4;
snake.head.row = row;
snake.head.col = col;
switch(direction) {
case 0:
//尾巴在头上边
snake.tail.row = row - 1;
snake.tail.col = col;
break;
case 1:
//尾巴在头下面
snake.tail.row = row + 1;
snake.tail.col = col;
break;
case 2:
//尾巴在头左边
snake.tail.row = row;
snake.tail.col = col - 1;
break;
default:
//尾巴在头右边
snake.tail.row = row;
snake.tail.col = col + 1;
break;
}
}
void plant_apple() {
do {
apple.row = rand() % (SIZE - 2);
apple.col = rand() % (SIZE - 2);
} while ((is_same(&apple, &(snake.head))) || (is_same(&apple, &(snake.tail))));
}
void show_map() {
/*这里的row和col变量是局部变量,虽然和前面的全局变量同名,但是,由于局部优先原则,局部的覆盖了全局的。*/
int row = 0;
int col = 0;
for (row = 0; row < SIZE; row++) {
for (col = 0; col < SIZE; col++) {
if ((row == apple.row) && (col == apple.col)) {
printf("%c",APPLE);
}
else if ((row == snake.head.row) && (col == snake.head.col)) {
printf("%c",SNAKEHEAD);
}
else if ((row == snake.tail.row) && (col == snake.tail.col)) {
printf("%c",SNAKETAIL);
}
else {
printf(" ");
}
}
printf("\n");
}
}
void move_snake() {
/*这里direction和前面的一个direction都是局部变量,作用域不同,所以虽然同名,但互不影响*/
char direction;
int row = 0;
int col = 0;
printf("请输入移动的方向:(0表示向上,1表示向左,2表示向下,3表示向右)");
scanf("%c", &direction);
/*这里输入一个字符后还敲了回车键,这个也会进入到输入缓冲区中,所以下次你还没有输入,它就运行了*/
scanf("%*[^\n]");
scanf("%*c");
//fflush(stdin);//这里刷新输入缓冲区没用,必须清空
switch(direction) {
case 'w':
if ((snake.head.row - 1) >= 0) {
snake.tail.row = snake.head.row;
snake.tail.col = snake.head.col;
snake.head.row--;
}
break;
case 'a':
if ((snake.head.col - 1) >= 0) {
snake.tail.row = snake.head.row;
snake.tail.col = snake.head.col;
snake.head.col--;
}
break;
case 's':
if ((snake.head.row + 1) < SIZE){
snake.tail.row = snake.head.row;
snake.tail.col = snake.head.col;
snake.head.row++;
}
break;
default:
if ((snake.head.col = 1) < SIZE) {
snake.tail.row = snake.head.row;
snake.tail.col = snake.head.col;
snake.head.col++;
}
break;
}
if (is_same(&apple, &(snake.head)) || (is_same(&apple, &(snake.tail)))) {
plant_apple();
}
}
int main() {
/*rand()产生的是伪随机数字,每次执行是相同的。若要不同,以不同的值来初始化它,初始化的函数是srand()*/
/*time(0)可获得自1970年1月1日00:00:00以来的秒数*/
srand(time(0));
init_snake();
plant_apple();
while (1) {
show_map();
move_snake();
}
return 0;
}