c语言学习笔记

本文介绍了C语言的基础知识,包括时间复杂度的计算方法,实参和形参的区别,以及冒泡排序算法的实现。学习路线涵盖了数据类型、运算符、控制结构等核心内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

c语言小知识

时间复杂度

时间复杂度的介绍在这里。
简单来说 就是一个程序 某条特殊语句的循环次数。(一般的,基本上之有循环才会带来时间复杂度)

综合起来:如果一个算法的执行次数是 T(n),那么只保留最高次项,同时忽略最高项的系数后得到函数 f(n),此时算法的时间复杂度就是 O(f(n))。为了方便描述,下文称此为大O推导法。

#include <stdio.h>
#include <string.h>
int main(){
	int a ,i ;
	scanf("%d", &a);
	for ( i = 0 ; i < a ; i ++)	{
		printf("%d\n" , i);
	}
	return 0;
}

在这个程序之中就是在for循环里 printf 循环了n次因此他的时间复杂度就是O(n)

#include <stdio.h>
#include <string.h>
int main(){
	int a ,i ;
	scanf("%d",&a);
	for ( i =1 ; i<a ; i = i * 2 ) {
		printf("%d\n",i);
	}
	return 0;
}

在这个程序中循环了 log2n次 因此他的时间复杂度就是O(log2n)

简单来说,计算时间复杂度的方法就是看某个循环语句内循环次数是多少

实参与形参

实参(argument):
全称为"实际参数"是在调用时传递给函数的参数. 实参可以是常量、变量、表达式、函数等, 无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值, 以便把这些值传送给形参。 因此应预先用赋值,输入等办法使实参获得确定值。

形参(parameter):
全称为"形式参数" 由于它不是实际存在变量,所以又称虚拟变量。是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传入的参数.在调用函数时,实参将赋值给形参。因而,必须注意实参的个数,类型应与形参一一对应,并且实参必须要有确定的值。

冒泡排序法

冒泡排序法介绍

冒泡排序法的代码实现其实也是很简单的
两次for 循环遍历就可以了

#include <stdio.h>

int main () 
{
    int nums[] = {3,5,6,1,2,4,4,5,67};


    for (int i = 0; i < sizeof(nums) / sizeof(nums[0]);i++)//第i次遍历
{
    for (int j = i + 1; j < sizeof(nums) / sizeof(nums[0]) - i - 1;j++)
    //第i次遍历,将从起始位置到末端这几个数字中最小的放在第i个位置
    {
            if (nums[i] > nums[j])//找到更小的就换
            {
                int temp = nums[i];
                nums[i] = nums[j];
                nums[j] = temp;
            }
    }


}
    for (int k = 0; k < sizeof(nums)/ sizeof(nums[0]); k++)
    {
        printf("%d" , nums [k]);

    }
        return 0;

}

另外除了字符串数组 例如 “abcdefg” 以及 “12,3,4,5,4”(每个元素都是由双引号的)
外数字数组是不能直接打印出来的一定得需要利用for循环遍历出来

基本学习路线

从数据类型-运算符-表达式-顺序程序设计-分支程序设计-循环控制结构-数组-函数-指针。
c语言数据类型

基本类型

常量和变量

与数据类型结合又可以分为整型变量,整型常量,浮点变量,浮点常量,字符变量,字符常量,枚举变量,枚举常量。

变量必须先进行定义在进行使用

#假如想使用整型变量a b c
int a,b,b;
#一次性可以多次定义变量,并且之间用逗号进行连接。

在这里插入图片描述
对于我一个新手而言,我的理解就是首先定义一个变量如整形变量k
便会出现一个框框,此时还没赋值,框框便为空,然后系统会给这个变量一个地址(好像与后文的指针有关联)。赋值之后框框就编程了

常量:可以不经过定义直接引用
而符号常量则需要定义

使用符号常量的好处是:
含义清楚;
能做到“一改全改”。
这个全局进行定义的也叫宏常量。

#include <stdio.h>

// 定义一个符号常量(一般来说符号常量都用大写字母来表示,以和变量区分开)
#define PRICE 30

void main(){
    int num,totle;
    num = 10; totle = num * PRICE;
    printf("总共金额为:%d \n",totle);
}

合法的整常量:十进制就不说了
在这里插入图片描述
除了宏常量外还有const常量
在这里插入图片描述
const常量相比于宏常量更加不容易出错,因为宏常量定义的预处理指令并不需要加" ; ",加了之后系统也不会进行判断,只会在替换之后才报错。
而const常量就没有这种烦恼。

整型

补充常识:一个字节byte = 8位bit
在这里插入图片描述
比如基本型int 为四个字节,32位,那么就最多可以表示2^32个数字
short int 短整型 为两个字节,16为,那么最多就表示2^16次方个数字
也即-32768~32767
此时就有一个叫做数据溢出的概念。
在这里插入图片描述
原本为a = 32767 + 1 的b应该等于32768但是现在却变为负数了,这就是因为超过了短整型 short int 的最大值32767所以导致了数据溢出。

实型(浮点型)

在这里插入图片描述

在这里插入图片描述

计算

算术运算符

主要有整数除法以及浮点数除法,算术运算符优先级跟加减乘除相同。
当运算优先级相同时,就涉及右结合(从右往左计算)和左结合
(从左往右进行计算)。

在这里插入图片描述
赋值语句也是右结合,也就是从右边往左边进行赋值。

除余运算
百分号%
在这里插入图片描述
此时就是利用到除余运算的灵活运用了。
如a%b 结果肯定是一个不超过b的一个值,那么就有如324分离出其百位十位个位的数的运算。(同时c语言规定在进行四则运算的时候,结果的数据类型跟前面数的类型应该相同,也就是124/100 = 1
在这里插入图片描述

得出来的结果就是3 2 4。
在这里插入图片描述
也就是说,rand在之后生成的数再利用取模运算进行映射。如a%b 结果肯定是一个不超过b的一个值,那么就有如324分离出其百位十位个位的数的运算。
在这里插入图片描述

增一减一运算符

在这里插入图片描述
当作为前缀的时候,就相当于一个自加语句(++n 等价于 n = n+1)
在这里插入图片描述
注意是先进行加一再使用n的值

而作为后缀的时候,就相当于先利用未自加的变量再将变量进行自加。
在这里插入图片描述
自加语句的执行效率比普通效率更加高

自动类型转化
也就是c会自动将两个不相同的数据类型转化成更加高级别的数据类型

在这里插入图片描述

比如:
在这里插入图片描述
此时最终打印出来的是

8.500000

这就是整型跟浮点数相加的时候,c自动将两个数都转化成更高级别的浮点数了。
这么做的目的是为了保证数据的精度。

强制类型转换
在这里插入图片描述
注意这个地方强制转化之后aver一定也得是(float)total 的数据类型,不然数据也会出错
在这里插入图片描述
c跟(float)b得是一种数据类型。
最终输出值才会是8.500000

数据的输入输出

数据的格式化键盘输出

转换控制符转换控制符说明
%d,%i以十进制格式输出一个整数
%o,%x以八进制或十六进制格式输出一个整数
%c输出一个字符
%s输出一个字符串

c语言里面的数据输入方式最常用的是scanf()
这个函数类似与python里面的input函数
在这里插入图片描述
假如是长整型的话就在%后面加一个L(小写)
%ld == 长整数型。
另外的%c character代表着以字符形式输出单个字符
在这里插入图片描述
格式修饰符
格式%m.nf n表示小数点之后的几位小数
在这里插入图片描述
注意一下m的意思就好

数据的格式化键盘输入

scanf("格式字符串",输入地址表)
scanf("%d%f",&a,&b) //&是取地址运算符

在这里插入图片描述
在这里插入图片描述
若是指定了位宽 那么就可以把两个数字自动的分割
在这里插入图片描述
在这里插入图片描述

若制定了scanf 的返回值那么其返回值就是 **正确读入的项数**
int a,b,c;
    
    c = scanf("%3d %2d",&a,&b);
    printf("a + b = %d\n",a+b);
    printf("%d\n",c);
    
    return 0;

此时c等于2

在这里插入图片描述
第一个错误是因为不能指定输入数据的精度
第二个是缺少地址运算符
第三个是因为加入了\n

单个字符的输入和输出

字符常量
3表示一个数字数值,而单引号‘3’则表示一种字符常量
同理‘b’也是一种字符常量。

转义字符
例如‘\n’代表着换行 因此这些加反斜杠的东西都是转义字符

字符输入输出函数
在这里插入图片描述
注意这个函数是单个字符的输入输出,也就是说

char ch;
ch = getchar();
//键入hello
putchar(ch);
最后输出结果是h

这里又涉及到大小写转化问题
在这里插入图片描述
大写英文字母 + 32 = 小写英文字母

getchar()是以行缓冲方式输入数据的,即用户在用getchar()从键盘输入字符时,程序并未直接读取用户输入,而是在用户按回车键以后将输入字符先放入到输入缓冲队列中,然后再从缓冲队列中读取字符。

也就是说当两个getchar函数一起出现时,你输入的东西先是一起被保存到缓冲区域,然后在经过getchar函数分开识别单个字符。

c格式符常见错误

在这里插入图片描述
此时的输出结果是:
在这里插入图片描述
这是因为第二个scanf函数读入了\n作为字符串并且输出了
这个时候有两种解决办法:

//在第二个scanf之前加一个 getchar()将\n调走
int a;
    char b;
    float c;

    printf("please enter an integer:\n");
    scanf("%d",&a);

    printf("please enter a characeter:\n");
    getchar();
    scanf("%c",&b);

    printf("please enter a float:\n");
    scanf("%f",&c);

    return 0;
//第二种方法就是在scanf函数里面加个空格
    scanf(" %c",&b);
    c格式符前面有个空格!!!!

经过这样的操作之后就可以正常的输入输出单个字符了

案例
假如要用户输入一个加法算式然后将算式跟结果输出要怎么操作


    int a,c;
    char b;
    

    printf("please enter an integer , a symbol and an integer:\n");
    scanf("%d %c%d",&a,&b,&c);

    printf("%d %c %d = %d",a,b,c,a+c);
    return 0;

结果就是
在这里插入图片描述
注意在加号前我加入了空格,而假如要忽略这个空格的影响,那就得在%c前面加一个空格。

"%d %c%d"

选择

关系逻辑符和运算逻辑符

算术运算符优先级高于判断运算符(== 以及 !=)

n % 2 == 0
//先进行的是除余运算 在进行的是判断是否相等的运算

真假性 (性比与python里面的bool类型)
true = 1 ,false = 0

逻辑运算符
and 为 && , or 为 || , 非为 !
算式运算符的优先级高于 逻辑运算符

案例
当表示一个闰年的时候

int year;
((year % 100 != 0 )&& (year % 4 == 0)) || (year % 400  == 0) 
这个句子就表示year 除余 一百不等于零和除余4 等于零跟 year 除余400 等于 0 
两个条件有一个成立就可以了

逻辑运算符的短路特性
比如在与 语句中如:

(a > 0) && (b++ >0)
假如当前面那个条件成立时,就不再执行后面的语句也就是
而假如前后位置互换一下结果可能就会改变了

b的值不会自加了!!!

条件语句

if else 条件语句
案例判断最大值

#include <stdio.h>

int main(){

    int a,b,max;

    printf("enter two numbers");
    scanf("%d %d",&a,&b);

    if (a>b)
    {
        max = a;
    }
    if (a<b)
    {    
    	max = b;
	}
    printf("the max is:%d",max);
    return 0;
    

}

同时这个判断语句也等于
条件表达式 max = a > b ? a : b;(意思就是说假如a比b大那么,把a赋值给max,反之亦然)
条件表达式语句可以放到printf语句之中

注意else始是与和他最近的if语句相配对的

开关语句

在这里插入图片描述
可以将开关语句理解成一个电梯,在按下某个确定的按钮时,电梯跳转到确定的位置,程序也执行确定的语句。而default语句就是输入的值在电梯楼层里面没有按钮,因此时错误的信息,此时执行的是default语句后面的句子。default通常用来处理错误的信息。

案例
设计一个分数与级别相对应的程序,比如98对应A;

#include <stdio.h>

int main()
{
    int score,mark;
    char grade;

    printf("please enter your score:");
    scanf("%d",&score);
    mark = score /10;

    switch (mark)
    {
    case 0:
    case 1:
    case 2:
    case 3:    
    case 4:
    case 5:
        grade = 'E';
        printf("your grade is %c",grade);
        break:
        
    case 6:
        grade = 'D';
        printf("your grade is %c",grade);
        break;

    case 7:
        grade = 'C';
        printf("your grade is %c",grade);
        break;

    case 8 :
        grade = 'B';
        printf("your grade is %c",grade);
        break;

    case 9 :
        grade = 'A';
        printf("your grade is %c",grade);
        break;

    
    default:
        printf("your score is wrong or too low");
        break;
    }

    return 0;

}

多个按钮可以对应一个楼层,也就是多个case可以对应一个语句
但是由于在边缘数据中比如-5,105,在mark = score /10;这个语句中体现的结果跟0-100中的数据是一样的,因此进行优化时还需进行一个条件表达式语句
mark = socre>0 && score<100 ? mark = score/10 : -1;
意思就是当分数在正常区间的时候就正常整除,否则就直接赋一个能放入default的值。

#include <stdio.h>

int main()
{
    int score,mark;
    char grade;

    printf("please enter your score:");
    scanf("%d",&score);
    mark = socre>0 && score<100 ? mark = score/10 : -1;
    //进行边缘数据检测!!!!!

    switch (mark)
    {
    case 0:
    case 1:
    case 2:
    case 3:    
    case 4:
    case 5:
        grade = 'E';
        printf("your grade is %c",grade);
        break:
        
    case 6:
        grade = 'D';
        printf("your grade is %c",grade);
        break;

    case 7:
        grade = 'C';
        printf("your grade is %c",grade);
        break;

    case 8 :
        grade = 'B';
        printf("your grade is %c",grade);
        break;

    case 9 :
        grade = 'A';
        printf("your grade is %c",grade);
        break;

    
    default:
        printf("your score is wrong or too low");
        break;
    }

    return 0;

循环

for 循环

在这里插入图片描述
案例
输入n个数字并且求和(比如4次)

#include <stdio.h>

int main()
{
    int i,sum = 0,m;

    for (i = 1; i <5 ;i++)
    {
        printf("please enter the %d number:\n",i);
        scanf("%d",&m);
        sum += m;
    }    

    printf("the sum is :%d",sum);

    return 0;

}

在这里插入图片描述
保证循环是可以终止的
执行循环体是必须改变一个或者多个变量,保证经过有限次循环之后,循环控制条件不再满足。

案例
输入一个数字,求出他的累加和(例如输入6 输出 sum = 6+5+4+。。。+1)

#include <stdio.h>

int main()
{
    int i,sum = 0,n;

    printf("please enter a number:\n");
    scanf("%d",&n);

    for (i = n; i > 0 ;i--)
    {
        sum += n;
        n -= 1;
    }    

    printf("the sum is :%d",sum);

    return 0;

}

在这里插入图片描述
方法二:逗号表达符
个人理解为等同于 &&。

while 和 do while语句

在这里插入图片描述

当型循环 while
意思就是先判断条件是否为真,然后再进行循环的执行

案例
仍然是上面for循环的案例 : 求阶乘

#include <stdio.h>

int main()
{
    int i,sum = 1,n,m;

    printf("please enter a number:\n");
    scanf("%d",&n);

    i = 0;
    m = n;
    while (i<n)
    {
        sum = sum * m;
        m--;
        i++;
    }
    printf("sum is:%d",sum);


    return 0;

}

直到型循环 do while
也是一种经典的标记型循环
在这里插入图片描述
这波就是先执行再求和再判断 假如条件为假时才退出循环。

递推

递推算法是一种用若干步可重复运算来描述复杂问题的方法。递推是序列计算中的一种常用算法。通常是通过计算前面的一些项来得出序列中的指定项的值。

案例
猴子吃桃问题
在这里插入图片描述

#include <stdio.h>

int main()
{
    int i,sum = 1,n,m;

    printf("please enter days:\n");
    scanf("%d",&n);

    i = 0;
    m = n;
    while (i<n-1)
    {
        sum = 2 *  (1 +sum );
        i++;
    }
    printf("sum is:%d",sum);


    return 0;

}

这样写的话,最关键的一句话就是sum = 2 * (1 +sum );
这一句话就是递推的关键代码。

在这里插入图片描述
循环最重要的就是多敲 多练

数组

指针(c的重头戏)

指针的概念:指针,是C语言中的一个重要概念及其特点,也是掌握C语言比较困难的部分。指针也就是内存地址,指针变量是用来存放内存地址的变量,不同类型的指针变量所占用的存储单元长度是相同的,而存放数据的变量因数据的类型不同,所占用的存储空间长度也不同。有了指针以后,不仅可以对数据本身,也可以对存储数据的变量地址进行操作。

在这里插入图片描述
其中pa就是指针变量。
指针相当于一个真实的地址,因此当形参的地址被赋值为一个指针变量的时候,那么将指针变量改变的时候就必然会将实参改变。

在这里插入图片描述

函数指针

在这里插入图片描述

#include <stdio.h>
#include <string.h>
int main()
{
	int a ,i ;

	int (*f)(int , int)	;//定义函数指针的格式

	f = fun;//如 &a一样 这种形式就是将这个函数的地址赋值给 指针f
}

fun(int a , int b)
{

	printf("%d",a + b)	;

}

泪目 由于笔者时间紧迫 因此得快点进入c++ 以及数据结构算法的学习,因此c语言的学习笔记就此暂停,等到以后有时间的话会进行详细的补充的。感谢各位的浏览,大佬亲喷蟹蟹。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值