C plus plus

g源文件(.c) ——{编译}——链接文件(.obj) ——{链接}——可执行文件(.exe)

一个项目只有1个main函数

stdio(标准输入输出)  

输出格式

\n   换行
\r   控制键”home"
\f   换页符
\t   制表符"补够8位一个\t“
\b   退格符
\'   常量(')          //printf("%s\n","\'")
\"   常量(")          //printf("%s\n","\"")
\\   常量(\)          //printf("D:\\VS\\")  路径
\0   字符串结束标志
\a   触发win报警声

 占位符


%u   输出unsigned整数
%d   输出signed整数
%zd  输出sizeof的返回值
%c   输出单字符
%s   输出字符串
%f   输出float小数(小数点后6位)
%lf  输出double小数(小数点后6位)
%Lf  输出long double小数
%%   输出(%)
%p   输出指针地址

关键字(只能用这些预设的) 

auto break case char const continue default do double else enum
extern
float for goto if int long register return short signed sizeof
static
struct switch typedef union unsigned void volatile while

数据类型

-Bool     //0为false,非0为true

数据类型长度(sizeof中的表达式不参与计算)

#include <stdio.h>
int main()
{                                    //长度(byte)
printf("%zd\n", sizeof(char));        //1
printf("%zd\n", sizeof(_Bool));       //1
printf("%zd\n", sizeof(short));       //2
printf("%zd\n", sizeof(int));         //4
printf("%zd\n", sizeof(long));        //4
printf("%zd\n", sizeof(long long));   //8
printf("%zd\n", sizeof(float));       //4
printf("%zd\n", sizeof(double));      //8
printf("%zd\n", sizeof(long double));  //8

return 0;}

变量

<当局部变量和全局变量同名的时候,局部变量优先使用

<局部变量未初始化时,值是随机的。 全局变量未初始化时,值是0

<本来一个局部变量 存储在内存的栈区,但是被static 修饰后存储到了静态区。

      存储在静态区的变量和全局变量是一样的:生命周期就和程序的生命周期一样了,只有程序结        束,变量才销毁,内存才回收。但是作用域不变的。

一个全局变量/函数(默认是具有外部链接属性的)被static修饰,外部链接属性就变成了内部链接属性,使得这个全局变量/函数只能在本源文件内使用,不能在其他源文件内使用

        如果一个全局变量/函数,只想在所在的源文件内部使用,不想被其他文件发现,就可以使用
    static修饰

//函数定义文件
static int Add(int x, int y)
{
return x+y;
}

//源文件
#include <stdio.h>
extern int Add(int, int);
int main() {
int a =0;
int b =0;
scanf("%d %d",&a,&b)
printf("%d\n", Add(2, 3));
return 0;  }

 extern 是用来声明外部变量的  如:extern int  Add(int, int);

数组越界

(以下代码是vs2022,debug ,x86环境下)

int main()
{
int i = 0;
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
    for(i=0; i<=12; i++)
    {
        arr[i] = 0;
        printf("hehe\n");
    }
return 0;
}
>>>hehe(死循环打印ing)

越界的数组也赋值为 0

cause {    i 和 arr 数组之间恰好空出2个int 的存储空间 ;arr[12] = 0 时覆盖 i 的值,导致 i 一直循环 } (环境不同内存使用细节也不同)

solve: {先赋值arr[i]再赋值 i 就不会覆盖}

:
:
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int i = 0;
:
:

 

 算术操作符(算数运算符)

/ 除    //双方需有1个小数类型   printf("%f\n", 5.655 / 9);   >>0.628333
%取余   //双方只能用于整数,负数求模的规则是,结果的正负号由第一个运算数的正负号决定
        //printf("%d\n", 11 % -5);      >> 1
        //printf("%d\n",-11 % -5);      >> -1
a = a+3;  >>  a += 3;
a = a-2;  >>  a -= 2;

前置--   (先--后使用)
int a = 10;
int b = --a;    //先a = 9  ,后赋给b
printf("a=%d b=%d\n",a , b);   >> 9  9

后置--   (先使用后--)
int a = 10;
int b = a--;    //先a = 10赋给b  ,后a -1= 9
printf("a=%d b=%d\n",a , b);   >> 9  10

int a = (int)3.14;      // 将double型3.14强制类型转换为int类型,会丢失数据

printf

printf("%5d\n", 123);     >>_ _123    //指定最小宽度,左边补空格,右对齐
printf("%lf\n", 3.1648964);  >>3.164896    //6位小数
printf("%10.4lf\n", 3.1648964);  >>_ _ _ _3.1649  //10位宽,指定4小数位数,四舍五入
                  <<==>>printf("%*.*lf\n",10,4,3.1648964); 
printf("%+d\n", 12);   >>  +12  
printf("%+d\n", -12);  >>  -12   //自动带正负号
printf("%.5s\n", "alehuodha");  >>alehu   //输出部分字符串

 printf返回打印在屏幕上的字符的个数 :

#include <stdio.h>
int main()      {
	printf("-%d", printf("~%d", printf("%d", 43)));
//                              打印43,在屏幕上打印"43"这2个字符,返回2
//                在屏幕上打印 “~2” 这2个字符,返回2
//  在屏幕上打印 “-2” 这2个字符,返回2
	return 0;    }
>>43~2-2

Scanf (格式,&变量)

变量前面必须加上& 运算符(指针变量、数组除外)

返回值是一个整数,表示成功读取的变量个数。如果没有读取任何项,则返回0

按ctrl+z ,提前结束输入,

占位符

1.除了%c 以外,都会自动忽略起首的空白字符。如果要强制跳过字符前的空白字符,可以写成

scanf("_%c", &ch);

即%c 前加上一个空格,表示跳过零个或多个空白字符。

2.%s 从当前第一个非空白字符开始读起,直到遇到空白字符

scanf("%10s", name);      //限定输入的长度

3.赋值忽略符,把* 加在任何占位符的百分号后面,该占位符就不会返回值,解析后将被丢

scanf("%d%*c%d%*c%d", 2024, 9, 5);       >>2024 9 5          //防止格式错误读取失败

if分支 

有多个if 和else时else 总是跟最接近的if 匹配。注重大括号的作用!

上代码什么不打印,改进后为: 

#include <stdio.h>
int main()
{
int a = 0;
int b = 2;
if(a == 1)
    { 
        if(b == 2)
           printf("hehe\n"); 
    }
else
  printf("haha\n");

return 0;
}
>>haha

关系运算符

a == b;     //一个=是赋值操作,2个==才是判断
a != b;     //返回0为flase  或1为true 
a < b;
a > b;
a <= b;
a >= b;

*多个关系运算符不宜连用

条件操作符

b = a>5 ? 3:-3;
//为真就3,为假救-3

逻辑操作符: && (与)    ||(或)    !(非)

int year = 0;
scanf("%d", &year);
if((year%4==0 && year%100!=0) || (year%400==0))
printf("是闰年\n");

短路:

仅根据左操作数的结果就能知道整个表达式的结果,不再对右操作数进行计算

int main()
{
	int i = 0, a = 0, b = 2, c = 3, d = 4;
	i = a++||++b||d++;
	//  0      3
	//    true
//a++为0  往右算++b为3 ;前2个结果为true不再执行后面内容(未执行d++)

	printf("i =%d a = %d\n b = %d\n c = %d\nd = %d\n", i, a, b, c, d);
	return 0;
}
                                                      >>1 1 3 3 4

switch分支

switch语句中的default子句可以放在任意位置

case语句最好放在default之前,且case后的表达式只能是整形常量表达式

int func(int a)
{
    int b;
    switch (a)
    {
        case 1: b = 30;
        case 2: b = 20;
        case 3: b = 16;
        default: b = 0;
    }
    return b;   }
>>0

/*
该switch语句中所有分支下都没有增加break语句,
因此会从上往下顺序执行,最后执行default中语句返回。
*/

深入解读switch

switch (expression)    //expression必须是int\char表达式
{
case value1: statement
case value2: statement
default: statement   //值无法匹配每个case的时候,执行default
}
//根据表达式expression 不同的值,执行相应的case 分支。
//如果找不到对应的值,就执行 default 分支
// case 和value之间必须有空格
// 每一个case 语句中的代码执行完成后,需加break ,才能跳出这个switch语句。

#include <stdio.h>             
int main()
{
int n = 0;
scanf("%d", &n);
switch(n%3)
{
case 0:
printf("整除,余数为0\n");
break;
case 1:
printf("余数是1\n");
break;
case 2:
printf("余数是2\n");
break; 
}
return 0; }



#include <stdio.h> 
int main()  {
int day = 0;
scanf("%d", &day);
switch(day)
{
case 1:
case 2:
case 3:
case 4:
case 5:
printf("工作日\n");
break;

case 6:
case 7:
printf("休息日\n");
break;
}
return 0;   }

while循环

条件表达式的执行次数总是比循环体的执行次数多一次

  //例题:逆序打印
int main()
{
int n = 4131;
while(n)
{
printf("%d ", n%10);
n /= 10;                  //只取整数部分
}
return 0;
}
>>1 3 1 4 


#include <stdio.h>
int main()
{
int i = 1;
while(i<=10)
{   if(i == 5)
  break;                  //当i等于5后,就执行break,循环终止了
    printf("%d ", i);
i = i+1;  }
return 0;  }
>>1 2 3 4 

#include <stdio.h>
int main()
{	int i = 0;
	while (i < 10)
	{
		i++;
	  if (i == 5)
		continue;      //当i等于5时,直接跳过continue的(i=5)转入执行语句i++ 
		printf("%d ", i); 	}
	return 0;  }
>>1 2 3 4 6 7 8 9 10

for循环

for(初始化; 结束条件的判断; 循环变量的调整)
       只执行一条 循环语句;
 //初始化-条件判断为true-执行循环语句-变量调整-条件判断…………条件为flase结束

#include <stdio.h>
int main()
{
	int i = 0;
	for (i = 1; i <= 10; i+=4)
	{
		printf("%d~", i);
	}
	return 0;  }
>>1~5~9~


  //计算1~100之间3的倍数的数字之和
#include <stdio.h>
int main()
{
	int i = 0;
	int sum = 0;
	for (i = 3; i <= 10; i += 3)  //接产生3的倍数
	{
		sum += i;      //sum =sum + i;
	}
	printf("%d\n", sum);
	return 0;}
>>18   //3+6+9=18

do while循环

//先执行语句,后判断while
//至少执行一次循环语句,在判断

#include <stdio.h>
int main()
{	int n = 0;
	scanf("%d", &n);
	int count = 0;
	do	{
		count++;
		n = n / 10;    
	} while (n);   
                  //count   n
                   //0      123  (初始时)
                   //1      12
                   //2      1
                   //3      0
	printf("%d\n", count);
	return 0; }

找出100~200之间的素数

#include <stdio.h>
int main()   
{ 	int i = 0;
	for (i = 100; i <= 200; i++)  	//循环产生100~200的数字
	{		
            //判断 i是否为素数
		int j = 0;     //初始化
		int flag = 1;  //默认 i是素数
		for (j = 2; j < i; j++)    //j =1不行,任何数都可整除1就都不是素数
		{
			if (i % j == 0)
			{	flag = 0;  //不是素数,就break结束
				break;  
			}
		}
		if (flag == 1)         //是素数
			printf("%d ", i);
	}
return 0;  }

goto跳转语句

实现在同一个函数内跳转到标号点。

#include <stdio.h>
int main()
{
again:
	printf("\a\n");   
	goto again;   //连续发出win警告
		return 0;
}

优势:一次跳出多层嵌套循环,如简化3个break 才能跳出循环

*关机项目

/*
shutdown
-s 关机
-t 关机倒计时(秒)
-a 取消关机

system  (stdlib.h)

strcmp  (string.h)
格式:strcmp(str1,str2)==0  则为true
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int main()
{
	int b;
	int n = 7;
	for (b = 1; b < n; b++)
	{
		printf("\a\n");
		printf("公主看这里!");
	}
begin:
	printf("\a");
	
	system("shutdown -s -t 100");
	printf("\n正在支配电脑100秒后关机,请输入英文版'LVy'表示'我喜欢你'进行取消关机\n");
	char ywb[3];
	scanf("%s", ywb);
	printf("\a");
	if (strcmp("LVy", ywb) == 0)
	{
		system("shutdown -a");
	
		printf("我也喜欢你勒\n哈哈哈哈\n");
	}
	else goto begin;
	printf("\a");
	return 0;
}

猜数字游戏项目

#define _CRT_SECURE_NO_WARNINGS  //D:\VS\IDE\Common7\IDE\VC\VCProjectItems(原文件)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

	void game()     //猜数字环节
	{
		int r = rand() % 100 + 1;  //需要<stdlib.h>
		/*
		rand() % 100;					//生成0~99
		rand() % 100 + 1;				//生成1~100之间的随机数
		100 + rand() % (200 - 100 + 1)	 //生成100~200的随机数
		a + rand() % (b - a + 1)		//生成a~b的随机数
		*/
		int guess = 0;
		int count = 5;    //机会次数
		while (count)
		{
			printf("你还有%d次机会\n", count);
			printf("请猜数字>");
			scanf("%d", &guess);
			if (guess < r)
			{
				printf("猜小了\n");
			}
			else if (guess > r)
			{
				printf("猜大了\n");
			}
			else
			{
				printf("恭喜你,猜对了\n");
				break;
			}

		count--;        //跳出来后自减1
		}
		if (count == 0)    //为0时结束游戏
		{
			printf("你失败了,正确值是:%d\n", r);
		}
	}

	void menu()
	{
		printf("***********************\n");
		printf("****** 1. play ******\n");
		printf("****** 0. exit ******\n");
		printf("***********************\n");
	}

	int main()      //选择游戏模式
	{
		int input = 0;
		srand((unsigned int)time(NULL));    //利用时间戳生成随机数 
   
		/*	在调用 rand 函数之前先调用 srand 函数,
		通过 srand 函数的参数结果来设置rand函数生成随机数的时候的种子,
		只要种子在变化,每次生成的随机数序列也就变化起来了*/
		/*//	time(NULL);需要<time.h >
		调用time函数返回时间戳,这里没有接收返回值,只返回这个时间的差值*/

		do	{
			menu();       //调用meau函数
			printf("请选择>");
			scanf("%d", &input);
			switch (input)
			{
			case 1:
				game();       //调用game函数
				break;
			case 0:
				printf("游戏结束\n");
				break;
			default:
				printf("选择错误,重新选择\n");
				break;
			}
		} 
		while (input);     
	return 0;
} 
	    

一维数组

• 数组中存放的是>=1个数据,但是数组元素个数不能为0
• 数组中存放的多个数据,类型是相同的。

int math[20];  //存储某个班的20人的数学成绩


int arr[5] = {1,2,3,4,5};   //完全初始化

double arr2[6] = {1.5};    //不完全初始化    ,第一个元素初始化为1.5,剩余元素默认初始化为0.0

int arr3[3] = {1, 2, 3, 4};   //错误的初始化 ————初始化项太多

 一维下标引用操作符:从0开始的,假设数组有n个元素,最后一个元素的下标是n-1

printf("%d",arr[7]);         //输出的数为8

一维数组和二维数组     在内存中都是连续存放的 :int 数组类型的每两个相邻的元素之间地址相差4,由小到大。

#include <stdio.h>
int main()
{
	int arr[] = { 1,2,(3,4),5 };  
/*
里面总共有4个元素,(3,4)为逗号表达式,取后者  4,
因此数组中元素分别为:1,2,4,5
*/
	printf("%d\n", sizeof(arr));  
 //sizeof(arr)求的是整个数组所占空间的大小,即:4*sizeof(int)=4*4=16
	return 0;
}
>>16

                                                         printf("%zd\n", sizeof(int));         >>4 

手动输入输出数组

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

    for(i=0; i<10; i++)       //给数组输入想要的数据
    {
        scanf("%d", &arr[i]);    //作为数组元素时需要取 &地址
    }

    for(i=0; i<10; i++)         //使用for循环输出0~9的下标
    {
        printf("%d ", arr[i]);
    }                
return 0;  }

计算数组元素个数:sizeof    

数组所占内存空间,单位是byte

#include <stido.h>
int main()
{
    int arr[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17};
    int sz = sizeof(arr)/sizeof(arr[0]);   //计算出数组的元素个数
/*
sizeof(arr)      计算的是 数组所占内存的总空间,单位是byte
sizeof(arr[0])   计算一个元素所占的存储空间,单位是byte
*/
       for( int i =0; i <sz; i++)
       {
            printf("%d  ", arr[i]);       //循环打印数组元素
       }
  return 0;
}

二维数组

初始化时,一维数组可以省略数组大小            ;二维数组可以省略行,但是不能省略列   

如  int arr[][5] = { {1,2}, {3,4}, {5,6,7,8,9} };

二维下标引用操作符:行号与列号也是从0开始的

#include <stdio.h>
int main()
{
int arr[3][5] = {1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7};
printf("%d\n", arr[2][4]);
return 0;
}
>> 7

#include <stdio.h>
int main()
{
int arr[3][5] = {1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7};
 //输入
int i = 0; 
for(i=0; i<3; i++) //产生行号
    {    
        int j = 0;
        for(j=0; j<5; j++) //产生列号
          {
          scanf("%d", &arr[i][j]); //输入数据
          }
    }
/*
先第0行输入5个值到第4列跳出“ j ”的循环
先第1行输入5个值到第4列跳出“ j ”的循环
先第2行输入5个值到第4列跳出“ j ”的循环
*/

//输出
    for(i=0; i<3; i++) //产生3个行号
      {
        int j = 0;
      for(j=0; j<5; j++) //产生5个列号
        {
        printf("%d ", arr[i][j]); //输出数据
        }
                printf("\n");    //每行满5个值后换行
      }
return 0;   }

变长数组长度只有运行时才能确定,所以变长数组不能初始化

int n = 0;                                                                
   scanf("%d", &n);//根据输入数值确定数组的大小
int arr[n];                                                                

数组练习

#include <stdio.h>
#include <stdlib.h>     //cls函数
#include <string.h>     //strlen函数
#include <windows.h>    //Sleep函数
int main()     {
	char arr1[] = "welcome to  qhgdx";
	char arr2[] = "#################";
	int left = 0;                         //左起始上标
	int right = strlen(arr1) - 1;         //右起始下标

	printf("%s\n", arr2);
	while (left <= right)                 //保证在中心结束循环
	{
		Sleep(1000);                      //优先每次休眠1000毫秒,有停顿
		system("cls");                    //后每次清屏
		arr2[left] = arr1[left];
		arr2[right] = arr1[right];
		left++;
		right--;
		printf("%s\n", arr2);
	}
  printf("%s\n", arr2);                   //打印最终结果
	return 0;   }
>>
#################
w###############x
we#############dx
wel###########gdx
welc#########hgdx
welco#######qhgdx
welcom##### qhgdx
welcome###  qhgdx
welcome #o  qhgdx
welcome to  qhgdx

函数

各类库函数说明:https://zh.cppreference.com/w/c/header

自定义函数,用于复用,功能要单一

#include <stdio.h>
int Add(int x, int y)  
{
return x+y;           
}

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

    scanf("%d %d", &a, &b);
      int r = Add(a, b);      //把a+b的值赋值给 r
        printf("%d\n", r);
return 0;    }

<只是形式上存在的,不会向内存申请空间,不会真实存在的,====形参

<函数被调用时,为了存放实参传递过来的值,才向内存申请空间  ===实参

<调用函数时,形参和实参个数要对应,

<形参操作的数组和实参的数组是同一数组

<形参和实参都有自己的内存地址空间,地址是不一样的。

return 语句

<return后边可以是一个数值,也可以是一个表达式,如果是表达式则先执行表达式
<return后边为 null      ,适合返回类型是void的函数
<return返回的值和函数返回类型不一致,系统会自动将转换为函数的返回类型
<return语句执行后,函数就彻底返回,后边的代码不再执行
<函数中存在if等分支的语句,则要保证每种情况下都有return返回,否则会出现编译错误(判断语句为真为假都要考虑return)
<函数的返回类型没有指定时,编译器默认返回 int类型
<函数中没有 return语句,返回值就不确定了

函数嵌套使用

#include <stdio.h>                  //计算某年某月有多少天
#include <stdbool.h>

bool is_leap_year(int y)   {
    if(((y%4==0)&&(y%100!=0))||(y%400==0))    //判断是否为闰年
     return true;
    else
     return false;         }

int get_days_of_month(int y, int m)  {
    int days[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
// 月份               1  2    3   4   5   6   7  8    9   10  11  12
    int day = days[m];                        //得到每月的天数
        if (is_leap_year(y) ==true  &&  m == 2)
                day += 1;
                     return day;     }
int main()   {
int year = 0;
int month = 0;
scanf("%d %d", &year, &month);
    int d = get_days_of_month(year, month);
        printf("%d\n", d);
return 0;    }

<函数之间可以嵌套调用,但不能嵌套定义 

<C语言编译器对源代码进行逐行编译,函数先声明后使用  :

#应先定义函数,后调用函数  ;

#或者声明函数(包括返回类型、名称、形参类型),调用函数和定义函数

VS调试

程序中存在的问题 ==bug

找出并解决问题的过程叫称为调试,英文叫debug(消灭bug)(F10、F11)

Debug (调试版本)
包含调试信息,并且不作任何优化,这个版本是便于程序员直接调试程序
Release (发布版本)
进行了各种优化,使得程序在代码大小和运行速度上都是最优的,这个版本是用户使用的,无需包含调试信息
                     快捷键
F9 (创建、取消) 断点
F5 启动调试:直接跳到下一个断点处
F10 逐过程调试:跳过函数细节直接给出结果
F11 逐语句调试:进入函数内部观察细节
CTRL + F5 开始执行不调试:程序直接运行而不调试,直接使用
监视窗口内存

F10调试后,【调试】->【窗口】->【监视】

观察(变量、表达式)的值变化

F10调试后,【调试】->【窗口】->【内存】

观察内存中的值变化(地址、数据、解析)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值