- 运行环境:Dev-C++ 6.5
常用头文件
#include<stdio.h> //标准输入输出函数库(printf、scanf)
#include<time.h> //用于获得随机数
#include<windows.h> //控制dos界面
#include<stdlib.h> //即standard library标志库头文件,里面定义了一些宏和通用工具函数
#include<conio.h> //接收键盘输入输出
#include <math.h> //pow函数
#include <string.h>
- #include叫做文件包含命令,用来引入对应的头文件(.h文件)。#include 也是C语言预处理命令的一种。#include 的处理过程很简单,就是将头文件的内容插入到该命令所在的位置,从而把头文件和当前源文件连接成一个源文件,这与复制粘贴的效果相同。
#include 的用法有两种,如下所示:
#include <stdHeader.h>
#include “myHeader.h”
使用尖括号< >和双引号" "的区别在于头文件的搜索路径不同:
使用尖括号< >,编译器会到系统路径下查找头文件;
而使用双引号" ",编译器首先在当前目录下查找头文件,如果没有找到,再到系统路径下查找。
宏定义
/*******宏 定 义*******/
#define FrameX 13 //游戏窗口左上角的X轴坐标
#define FrameY 3 //游戏窗口左上角的Y轴坐标
#define Frame_height 20 //游戏窗口的高度
#define Frame_width 18 //游戏窗口的宽度
宏(Macro)是预处理命令的一种,它允许用一个标识符来表示一个字符串。
- #define N 100就是宏定义,N为宏名,100是宏的内容。在预处理阶段,对程序中所有出现的“宏名”,预处理器都会用宏定义中的字符串去代换,这称为“宏替换”或“宏展开”。宏定义是由源程序中的宏定义命令#define完成的,宏替换是由预处理程序完成的。
函数声明
- 所谓声明(Declaration),就是告诉编译器我要使用这个函数,你现在没有找到它的定义不要紧,请不要报错,稍后我会把定义补上。
int Test(int c);
void Te();
局部变量和全局变量
-
局部变量:定义在函数内部的变量称为局部变量(Local Variable),它的作用域仅限于函数内部, 离开该函数后就是无效的,再使用就会报错。
全局变量:在所有函数外部定义的变量称为全局变量(Global Variable),它的作用域默认是整个程序,也就是所有的源文件,包括 .c 和 .h 文件。#include <stdio.h> int n = 10; //全局变量 void func1() { int n = 20; //局部变量 printf("func1 n: %d\n", n); } void func2(int n) { printf("func2 n: %d\n", n); } void func3() { printf("func3 n: %d\n", n); } int main() { int n = 30; //局部变量 func1(); func2(n); func3(); //代码块由{}包围 { int n = 40; //局部变量 printf("block n: %d\n", n); } printf("main n: %d\n", n); return 0; }
输入输出
- 输入输出的一些格式控制符
#include <stdio.h> int main( ) { char str[100]; int i; printf( "Enter a value :"); scanf("%s %d", str, &i); printf( "\nYou entered: %s %d ", str, i); printf("\n"); return 0; }
判断语句if、switch
-
一个 if 语句 后可跟一个可选的 else 语句,也可不跟,else 语句在布尔表达式为 false 时执行。
#include <stdio.h> int main () { /* 局部变量定义 */ int a = 100; /* 检查布尔条件 */ if( a < 20 ) { /* 如果条件为真,则输出下面的语句 */ printf("a 小于 20\n" ); } else { /* 如果条件为假,则输出下面的语句 */ printf("a 大于 20\n" ); } printf("a 的值是 %d\n", a); return 0; }
-
一个 switch 语句允许测试一个变量等于多个值时的情况。每个值称为一个 case,且被测试的变量会对每个 switch case 进行检查。
#include <stdio.h> int main () { /* 局部变量定义 */ char grade = 'B'; switch(grade) { case 'A' : printf("很棒!\n" ); break; case 'B' : case 'C' : printf("做得好\n" ); break; case 'D' : printf("您通过了\n" ); break; case 'F' : printf("最好再试一下\n" ); break; default : printf("无效的成绩\n" ); } printf("您的成绩是 %c\n", grade ); return 0; }
循环语句while、for
- while循环,只要给定的条件为真,C 语言中的 while 循环语句会重复执行一个目标语句。退出while循环用break
#include <stdio.h>
int main ()
{
/* 局部变量定义 */
int a = 10;
/* while 循环执行 */
while( a < 20 )
{
printf("a 的值: %d\n", a);
a++;
if( a > 15)
{
/* 使用 break 语句终止循环 */
break;
}
}
return 0;
}
- for循环,多次执行一个语句序列,简化管理循环变量的代码。
for ( init; condition; increment )
{
statement(s);
}
下面是 for 循环的控制流:
- init 会首先被执行,且只会执行一次。这一步允许您声明并初始化任何循环控制变量。您也可以不在这里写任何语句,只要有一个分号出现即可。
- 接下来,会判断 condition。如果为真,则执行循环主体。如果为假,则不执行循环主体,且控制流会跳转到紧接着 for 循环的下一条语句。
- 在执行完 for 循环主体后,控制流会跳回上面的 increment 语句。该语句允许您更新循环控制变量。该语句可以留空,只要在条件后有一个分号出现即可。
- 条件再次被判断。如果为真,则执行循环,这个过程会不断重复(循环主体,然后增加步值,再然后重新判断条件)。在条件变为假时,for 循环终止。
#include <stdio.h>
int main ()
{
/* for 循环执行 */
for( int a = 10; a < 20; a = a + 1 )
{
printf("a 的值: %d\n", a);
}
return 0;
}
- do while,不像 for 和 while 循环,它们是在循环头部测试循环条件。在 C 语言中,do…while 循环是在循环的尾部检查它的条件。do…while 循环与 while 循环类似,但是 do…while 循环会确保至少执行一次循环。
- C 语言中的 continue 语句有点像 break 语句。但它不是强制终止,continue 会跳过当前循环中的代码,强迫开始下一次循环。对于 for 循环,continue 语句执行后自增语句仍然会执行。对于 while 和 do…while 循环,continue 语句会重新执行条件判断语句。
#include <stdio.h>
int main ()
{
/* 局部变量定义 */
int a = 10;
/* do 循环执行 */
do
{
if( a == 15)
{
/* 跳过迭代 */
a = a + 1;
continue;
}
printf("a 的值: %d\n", a);
a++;
}while( a < 20 );
return 0;
}
- goto语句C 语言中的 goto 语句允许把控制无条件转移到同一函数内的被标记的语句。
- 注意:在任何编程语言中,都不建议使用 goto 语句。因为它使得程序的控制流难以跟踪,使程序难以理解和难以修改。任何使用 goto 语句的程序可以改写成不需要使用 goto 语句的写法。
函数的定义
定义好的函数在使用之前需要声明,函数声明会告诉编译器函数名称及如何调用函数。
- 在 C 语言中,函数由一个函数头和一个函数主体组成。下面列出一个函数的所有组成部分:
- 返回类型:一个函数可以返回一个值。return_type 是函数返回的值的数据类型。有些函数执行所需的操作而不返回值,在这种情况下,return_type 是关键字 void。
- 函数名称:这是函数的实际名称。函数名和参数列表一起构成了函数签名。
- 参数:参数就像是占位符。当函数被调用时,您向参数传递一个值,这个值被称为实际参数。参数列表包括函数参数的类型、顺序、数量。参数是可选的,也就是说,函数可能不包含参数。
- 函数主体:函数主体包含一组定义函数执行任务的语句。
//定义一个修改控制台颜色的函数:
int color(int c)//更改窗口颜色
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),c);
return 0;
}
//定义一个修改控制台光标位置的函数:
void gotoxy(int x, int y)
{
COORD c;
c.X = x;
c.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
}
按键监听、随机数
#include <time.h>
#include <windows.h>
#include <conio.h>
#include <stdio.h>
int main()
{
//随机数生成
int n=0;
srand(time(NULL));
for(int i=0;i<10;i++)
{
n=rand();
printf("测试:%i\n",n);
}
while(1)
{
Sleep(100);//休息0.1秒
// char ch=getch();
if (kbhit())//判断是否有键盘输入
{
char ch=getch();//ASCII码值
if (ch==27)//判断是否Esc按键按下,其他的按键判断请查看ASCII码表
{
printf("按下");
printf("%d",ch);
break;
}
}
}
return 0;
}
指针
指针就是内存地址,指针变量是用来存放内存地址的变量。
- 指针的类型
定义 | 类型 |
---|---|
int i; | 定义 整型变量i |
int *p; | p为指向整型数据的指针变量 |
int a[n]; | 定义整型数组a,它有n个元素 |
int *p[n]; | 定义指针数组p,它由n个指向整型数据的指针元素组成 |
int (*p)[n]; | p为指向含N个元素的一维数组的指针变量 |
int f(); | f为返回整型函数值的函数 |
int *p(); | p为返回一个指针的函数,该指针指向整型数据 |
int (*p)(); | p为指向函数的指针,改函数返回一个整数型 |
int **p; | p为一个指针变量,它指向一个指向整型数据的指针变量 |
- 指针的使用,使用&运算符访问地址
#include <stdio.h>
int main ()
{
int var = 20; /* 实际变量的声明 */
int *ip; /* 指针变量的声明 */
ip = &var; /* 在指针变量中存储 var 的地址 ,*/
printf("var 变量的地址: %p\n", &var );
/* 在指针变量中存储的地址 */
printf("ip 变量存储的地址: %p\n", ip );
/* 使用指针访问值 */
printf("*ip 变量的值: %d\n", *ip );
return 0;
}
- 指针运算
#include <stdio.h>
const int MAX = 3;
int main ()
{
int var[] = {10, 100, 200};
int i, *ptr;
/* 指针中的数组地址 */
ptr = var;
for ( i = 0; i < MAX; i++)
{
printf("存储地址:var[%d] = %p\n", i, ptr );
printf("存储值:var[%d] = %d\n", i, *ptr );
/* 指向下一个位置 */
ptr++;
}
return 0;
}
- 定义指针数组
#include <stdio.h>
const int MAX = 3;
int main ()
{
int var[] = {10, 100, 200};
int i, *ptr[MAX];//定义指针数组ptr,它由MAX3个指向整数型数据的指针元素组成
for ( i = 0; i < MAX; i++)
{
ptr[i] = &var[i]; /* 赋值为整数的地址 */
}
for ( i = 0; i < MAX; i++)
{
printf("Value of var[%d] = %d\n", i, *ptr[i] );//打印指针数组中的数据
}
return 0;
}
- 指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链。通常,一个指针包含一个变量的地址。当我们定义一个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置。
-指针传递给函数,在函数中修改的值才有效
#include <stdio.h>
void swap(int *p1, int *p2){
int temp; //临时变量
temp = *p1;
*p1 = *p2;
*p2 = temp;
}
int main(){
int a = 66, b = 99;
swap(&a, &b);
printf("a = %d, b = %d\n", a, b);
return 0;
}
- 用数组作函数传参
数组是一系列数据的集合,无法通过参数将它们一次性传递到函数内部,如果希望在函数内部操作数组,必须传递数组指针。
#include <stdio.h>
int max(int *intArr, int len)//取数组中的最大值并返回
{
int i, maxValue = intArr[0]; //假设第0个元素是最大值
for(i=1; i<len; i++)
{
if(maxValue < intArr[i])
{
maxValue = intArr[i];
}
}
return maxValue;
}
int main(){
int nums[6], i;
int len = sizeof(nums)/sizeof(int);
//读取用户输入的数据并赋值给数组元素
for(i=0; i<len; i++)//循环给数组赋值
{
scanf("%d", nums+i);
}
printf("Max value is %d!\n", max(nums, len));
return 0;
}
- 从函数返回指针
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
/* 要生成和返回随机数的函数 */
int * getRandom( )
{
static int r[10];
int i;
/* 设置种子 */
srand( (unsigned)time( NULL ) );
for ( i = 0; i < 10; ++i)
{
r[i] = rand();
printf("%d\n", r[i] );
}
return r;
}
/* 要调用上面定义函数的主函数 */
int main ()
{
/* 一个指向整数的指针 */
int *p;
int i;
p = getRandom();
for ( i = 0; i < 10; i++ )
{
printf("*(p + [%d]) : %d\n", i, *(p + i) );
}
return 0;
}
数组操作
- 一维数组
一维数组初始化:
int a[5]={1,2,3,4,5};
对static数组元素不赋初值,系统会自动赋以0值。
static int a[5];
修改一维数组的值
#include <stdio.h>
int main()
{
static int Arr[5];
int *p;//定义一个指针变量
p=Arr;//将指针变量指向Arr
*(p+1)=100;//修改指针变量的第1个值
*(p+3)=999;//修改指针变量的第3个值
for (int i=0;i<=4;i++)
{
printf("数据:%i,%i",Arr[i],p[i]);
}
return 0;
}
- 二维数组
二维数组初始化:
int a[2][3]={{1,2,3},{4,5,6}};
static int b[2][2];
- 字符数组
char name1[4][10] = { “测试”, “Momo”, “Becky”, “Bush” };
char *name2[4] = { “测试”, “Momo”, “Becky”, “Bush” };
lenght = strlen(str); //这种方法只适用于字符串数组
int i=0;
while(str[i++] != ‘\0’);//这种方法适用于计算数组中实际元素多少
len = sizeof(str)/sizeof(str[0]);//这种方法适用于计算数组分配的总长度多少,包括空字符
#include <stdio.h>
int main()
{
char *name3[2][2] = {{"测试", "Momo"},{"Becky", "Bush" }};
// printf("%s\n",name3[0][0]);
int x=sizeof(*name3);
int y=sizeof(*name3[0]);
for (int i=0;i<=x;i++)
{
for (int j=0;j<=y;j++)
{
printf("%s\n",name3[i][j]);
}
}
return 0;
}
时间戳、日期转换
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
char *Time_I_S(time_t tick)//时间戳转日期
{
struct tm tm;
static char s[100];
memset(s, 0, sizeof(s));
tm = *localtime(&tick);
strftime(s, sizeof(s), "%Y-%m-%d %H:%M:%S", &tm);
return s;
}
long Time_S_I(char *str_time) //日期转时间戳 ,2021-12-12 12:12:12
{
struct tm stm;
int iY, iM, iD, iH, iMin, iS;
memset(&stm,0,sizeof(stm));
iY = atoi(str_time);
iM = atoi(str_time+5);
iD = atoi(str_time+8);
iH = atoi(str_time+11);
iMin = atoi(str_time+14);
iS = atoi(str_time+17);
stm.tm_year=iY-1900;
stm.tm_mon=iM-1;
stm.tm_mday=iD;
stm.tm_hour=iH;
stm.tm_min=iMin;
stm.tm_sec=iS;
/*printf("%d-%0d-%0d %0d:%0d:%0d\n", iY, iM, iD, iH, iMin, iS);*/
return mktime(&stm);
}
int main()
{
char str_time[50]="2021-06-30 16:56:01";
int out_time_i= Time_S_I(str_time);
printf("日期转时间戳:%ld\n", out_time_i);
// int t = time(NULL); // 获取当前时间戳
int t=1625043361;
char *out_time_s = Time_I_S(t);
printf("时间戳转日期:%s\n",out_time_s);
time_t now ;
time(&now) ;//获取系统当前时间
struct tm *tm_now ;//定义时间结构体
tm_now = localtime(&now);// 把整数的时间转换为struct tm结构体的时间
tm_now->tm_year=tm_now->tm_year+1900;//时间标准化
tm_now->tm_mon=tm_now->tm_mon+1;
printf("当前系统时间: %d-%d-%d %d:%d:%d\n",tm_now->tm_year, tm_now->tm_mon, tm_now->tm_mday, tm_now->tm_hour, tm_now->tm_min, tm_now->tm_sec);
return 0;
}
文件读写
- 对TXT文本进行读写操作,可以循环语句进行多次读写
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *test;
test=fopen("test.txt","r");//打开待读取文件
if (test==NULL)//文件写入
{
test=fopen("Test.txt","w");
fprintf(test,"host:\t%s\nusername:\t%s\npassword:\t%s\ndatabase:\t%s\n","set","set","set","set");//可多次写入
fclose(test);
}
//文件读取
char host[20];
char username[20];
char password[20];
char dbname[20];
fscanf(test,"host:\t%s\nusername:\t%s\npassword:\t%s\ndatabase:\t%s\n",host,username,password,dbname);//可多次读取
printf("host:%s\nusername:%s\npassword:%s\ndatabase:%s\n",host,username,password,dbname);
fclose(test);
return 0;
}