C语言学习笔记

C语言的发展历史

  • 起始于上世纪70年代
  • C语言是从B语言发展而来的,B语言是从BCPL发展而来的,BCPL是从FORTRAN发展而来的
  • FORTRAN是第一个高级程序设计语言(1950s)
  • BCPL和B都支持指针间接方式,所以C也支持
  • C语言还受到了PL/1(底层编程语言,接近于汇编)的影响,还和PDP-11的机器语言有很大的关系
  • 1973年3月,第三版的Unix上面出现了C语言的编译器
  • 1974年11月,第4版的Unix((System Four)发布,这个版本是完全用C语言写的
  • 最早的C叫做"K&R the C"-经典C
  • 1989年ANSI发布了一个标准-ANCI C
  • 1990年ISO接受了ANSI的标准-C89
  • C的标准在1995年和1999年两次更新C95和C99(目前最新版本)
  • 目前所有的编译器都支持C99

image-20220628183115881

第一个简单C程序

  #include<stdio.h>   //头文件

  int main() {
           //主函数
    printf("hello\n"); //打印输出
    return 0;          //结束
  }
  • ""里面的内容为字符串,原封不动的输出里面的内容
  • \n表示换行

printf做简单计算

  printf("%d",12+32);   //46

可以做加、减、乘、除、取余、括号

命令行编译和运行

编译:gcc hello.c 此时编译生成的文件为a.out

执行:./a.out ./是Unix为了保证安全的手段

若需要对.c文件进行编辑,可以用vi hello.c,i进行编辑,esc退出编辑,wq退出编辑

变量

    #include<stdio.h>

    int main() {
   
    int num = 0;  //定义变量初始值为0的变量
      printf("输入数字:\n");
      scanf_s("%d", &num);
      int end = 100-num;
      printf("100减去该数的结果是%d,\n",end);
      return 0;
    }

变量的定义:

<类型名称><变量名称>

变量的名字是一种标识符,基本的组成原则是:

标识符只能由字母、数字和下划线组成,数字不能出现在第一个位置上面,C语言的关键字不能作为标识符。

关键字:

image-20220629114010785

赋值与初始化

int price=0;

变量名为price,类型为int,赋值为0;

在计算机中,=是赋值,==是等于;

在变量定义的时候就进行赋值就叫做变量的初始化;

在一行里面若有多个变量,那么在进行赋值的时候必须一个一个的赋值,不能一次性把一个值赋给多个变量;

表达式

  int b=20;
  a=b-10;

表达式是一系列运算符算子的组合,用来计算一个值;

运算符:进行运算的动作 + - * /

算子:参与运算的值,可能是常量也可能是变量,还能是一个方法的返回值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jFnAJxHc-1657249548918)(https://s2.loli.net/2022/07/02/xiMTn7lHwpXQgRy.png)]

C语言中所有的变量在使用之前必须定义或声明,所有的变量必须具有确定的数据类型;


C99与ANSI C在变量定义上的区别:

ANSI C 只能在程序的开头定义变量

C99可以在程序的任何位置定义变量


读整数输入 scanf

  scanf("%d",&price)

price前面的**&**是必写的

要求sanf这个函数读入下一个整数,读到的结果赋值给变量price;

常量与变量

在程序运行过程中不变的数字是常量,会变的是变量,直接写在程序中的数字是直接量;

定义常量:

	const int AMOUNT = 100 ;

const是一个修饰符,加在int前面,给该变量加上一个不变的属性,一但初始化以后就不能再修改了,

将用户输入的两数相加:

  #include<stdio.h>

    int main() {
   
        int a ;
        int b ;
      printf("请输入两个整数:\n");
      scanf_s("%d %d", &a, &b);
      printf("%d+%d=%d\n", a, b, a + b);
      }

浮点数

  • 即为带小数点的数值

  • 两个整数的运算结果只能是整数

  • 10.0是浮点数

  • 在C中,10与10.0是两个完全不同的数

  • double为双精度浮点数,float 为单精度浮点数


占位符

数据类型 占位符
int %d
short %hd
unsigned int %u
unsigned short %hu
long(是int 的修饰,不是单独的数据类型,只是比int多了四个人字节的空间) %ld
unsigned long %lld
char %c
float(%g float默认是6位小数输出,可在%f中控制) %f和%g
double %lf和%lg
char %s
unsigned %u
八进制 %o 以0开头
十六进制 %x 以0x开头
二进制 无占位符
地址值、指针值 %p
* 去指针里地址指向的地方的值
& 取改值存储位置的地址值

运算

    //计算时间差
    #include<stdio.h>

    void main() {
   
      int hour1, minute1;
      int hour2, minute2;
      printf("请输入时间 小时,分钟\n");
      scanf_s("%d %d", &hour1, &minute1);
      printf("请输入时间 小时,分钟\n");
      scanf_s("%d %d", &hour2, &minute2);
      int time1 = hour1 * 60 + minute1;
      int time2 = hour2 * 60 + minute2;
      int time = time2 - time1;
      printf("时间差为:%d分钟",time);
    }

运算符的优先级

image-20220629154253260

单目运算:只有一个算子,例如 -a

对C来说,赋值也是一个运算,也有结果

结合关系
  • 一般自左向右
  • 单目±和赋值= 自右向左
例题:

image-20220629155220152

        #include<stdio.h>

      void main() {
   
        int x;
        scanf_s("%d", &x);
        double money = x * (1 + 0.033) * (1 + 0.033) * (1 + 0.033);
        printf("%f",money);
      }
交换两个变量的值
    #include<stdio.h>

    void main() {
   
      int a = 5;
      int b = 6;
      int c;
      c = a;
      a = b;
      b = c;
      printf("a=%d b=%d", a, b);
    }

复合赋值

即5个基本运算符(+ - * / %)与赋值运算符结合起来,形成

复合赋值运算符
  • +=
  • -=
  • *=
  • /=
  • %=

例:total+=5 等价于 total=total+5

递增递减运算符
  • ++

他们是单目运算符,算子必须是变量,作用就是给变量+1或者-1;

  • ++与–可以放在变量的前面,叫做前缀形势,放在变量后面叫做后缀形势
  • a++的值是a+1以前的值。而++a的值是a+1以后的值,无论哪个,a自己的值都+1了
    #include<stdio.h>

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

    printf("++a=%d\n", ++a);
    printf("a=%d\n", a);

  }	

做判断

if语句

if(条件成立){

(执行)

}

当然,也可以没有大括号,但是后面只能跟一句语句,而且不能跟分号,那么当if里面的条件满足时就会执行紧跟在if后面的那条语句。

嵌套的判断

当if的条件满足或者不满足的时候要执行语句也可以是一条if或if-else语句,这就是嵌套的if语句

else的匹配
  • 在不加大括号**{}**的情况下,else总是和最近的那个if匹配
  • 最好是在if或者else后面始终跟上大括号,防止编译器与自己的理解不一样
判断的条件
  • 计算两个值之间的关系,为关系运算

image-20220629190855543

  • 关系运算符的结果为整数,符合预期时结果为1,否则为0

1.优先级:所有的关系运算符的优先级比算术运算的低,但是比赋值运算的高

  • 7>=3+4 //1
  • int r=a>0 //a>0的结果为1,将1赋值给r

2.判断是否相等的==和!=的优先级比其他的低,而连续的关系运算是从左到右进行的

  • 5>3==6>4 //1
  • 6>5>4 //0
  • ab6
  • ab0

注释

  • // 两个**/**的单行注释
  • /* (注释内容)*/ 多行注释,也可用于行内注释

常见错误

分号问题

假如在if语句后面有接分号,那么就意味着在if语句后面有一条什么都不做的空白语句,分号后面的大括号里面的内容只是代码中很普通的语句,代码中可以将代码用大括号进行包裹,编译器也不会报错

	int a=0;
	if(a>0)
	;   //空白语句,执行完以后会执行下面的printf语句
	{
	printf("%d",a)
	}

错误使用==和=

例如

	int a=5,b=6;
	if ( a=b );
	printf("%d\n", a)

该if语句中,不会判断a与b是否相等,反而会将b的值赋给a

switch-case

    switch(type){
    case 1:
    printf("你好");
    break;
    case 2:
    printf("早上好");
    break;
    case 3:
    printf("晚上好");
    breakk;
    }
  • switch(控制表达式){

    case 常量:

    语句;

    break;

    case 常量:

    语句;

    break;

    default:

    语句;

    break;

    }

需要注意

  • 控制表达式只能是常量(int)
  • 常量可以是常数,也可以是常数计算的表达式(C99)
  • break的作用与Java中的类似,若没有break则会继续往下执行,有break则会离开当前switch-case
例题:成绩等级转换

image-20220630121259049

    #include<stdio.h>

    void main() {
   
      int gread = 0;
      scanf_s("%d", &gread);
      gread /= 10;
      switch (gread)
      {
   
      case (10):
        printf("A");
        break;
      case (9):
        printf("A");
        break;
      case (8):
        printf("B");
        break;
      case (7):
        printf("C");
        break;
      default:
        printf("E");
        break;
      }
    }

循环

1.while循环

案例(计算数字的位数):

    #include<stdio.h>

    void main() {
   
      int a = 0;
      int num = 0;
      scanf_s("%d", &a);
      
        num++;
        a=a / 10;//这两句的存在主要是为了处理0的位数,否则的话,0就会显示为0位数
      
      while (a>0)
      {
   
        num++;
        a=a / 10;
      }
      printf("%d",num);
    }

与Java类似,while循环当条件满足时会不断的执行后面大括号里面的代码(循环体),循环体内也要有改变条件的机会,否则可能会变成死循环

2.do-while循环

先无条件做do后面的语句,再进行条件判断

while结尾必须有分号

			do
      {
   
        <首先执行的循环体语句>
      }while(<循环条件>)

image-20220630152427165

案例:猜数游戏

    #include<stdio.h>
    #include <time.h>
    #include<stdlib.h>

    void main() {
   
      srand(time(0));
      int number = rand() % 100 + 1;
      int a;
      int count = 0;

      do {
   
        printf("输入猜的数:\n");
        scanf_s("%d", &a);
        count++;
        if (a > number) {
   
          printf("输入的数太大\n");
        }
        else if(a<number) {
   
          printf("输入的数太小\n");
        }
      } while (a != number);
      printf("用了%d次猜对",count);
    }

案例:算平均数

      #include<stdio.h>

      void main() {
   
        int sum = 0;
        int num;
        int count = 0;

        do {
   
          scanf_s("%d", &num);
          if (num != -1) {
   
            sum += num;
            count++;
          }
        } while (num != -1);
          int average = sum / count;
          printf("一共输入了%d个数字平均值为%d", count, average);
      }

案例:整数求逆

  • 一个整数是由1至多位数字组成的,如何分解出整数的各个位上的数字,然后加以计算:
  • 对一个整数做**%10的操作,就得到它的个位数**;
  • 对一个整数做**/10的操作,就去掉了它的个位数**;
  • 然后再对2的结果做**%10**,就得到原来数的十位数
  • 依此类推。

3.for循环

案例:求阶乘

    #include<stdio.h>

    void main() {
   
      int a;
      int factor = 1;
      scanf_s("%d", &a);
      for (int begin = 1; begin <= a; begin++) {
   
        factor *= begin;
      }
      printf("阶乘为:%d", factor);
    }

三种循环的选择

  • 若有固定次数,用for循环
  • 如果必须执行一次,用do…while循环
  • 其他情况用while循环

循环控制

素数:只能被1和自己整除的数,不包括1;

    //生成指定范围内的所有素数
    #include<stdio.h>

    void main() {
   
      printf("输入范围(1-__)已生成该范围内的所有素数\n");
      int x,a;
      scanf_s("%d", &a);
      for ( x = 1; x <= a; x++)
      {
   
        int i;
        int isPrime = 1;
        for (i = 2; i < x; i++) {
   
          if (x % i == 0) {
   
            isPrime = 0;
            break;
          }
        }
        if (isPrime == 1) {
   
          printf("%d ",x);
        }
      }
      return 0;
    }

循环的嵌套

可以不同的循环嵌套,也可以嵌套很多层循环

需要注意的是,计算循环的变量尽量不要一样

案例:凑硬币

      #include<stdio.h>

      int main() {
   
        int x;
        int one, two, five;
        x = 2;
        int exit = 0;
        for (one = 1; one < x*10; one++) {
   
          for (two = 1; two < x * 10 / 2; two++) {
   
            for ( five = 1; five < x*10/5; five++)
            {
   
              if (one + two * 2 + five * 5 == x * 10) {
   
                printf("能用%d个1角加%d个2角加%d个5角得到%d元\n", one, two, five, x);

                //当找到一种解决方案时就输出并停止
                goto out;
              }
            }
            }
            }
              out:
                return 0;



goto 语句

goto语句后面要接一个标号,这个标号是自己设置的,程序将会跳转到该标号的位置上去,声明标号时需要在标号后面接冒号,然后再接语句;

例如:

    ......
			goto out;
                  }
                  out:
                    return 0;
		......
  • 当有多层嵌套时,使用goto语句是非常方便的,除此以外,其他场合尽量不要使用,因为goto语句会破坏程序的结构性

案例:前n项求和

    //1  1/2   1/3  1/n求和
    #include<stdio.h>

    void main() {
   
      int i = 1;
      int n;
      scanf_s("%d", &n);
      double sum = 0.0;
      for (i = 1; i <= n; i++) {
   
        sum += 1.0 / i;
      }
      printf("%f", sum);
    }

数据类型

C语言是有类型的语言,C语言的变量必须:

  • 在使用之前定义
  • 确定类型
  • C++/Java更加强调类型,甚至对类型的检查比C更为严格
  • JavaScript、Python、PHP不看重类型,甚至不需要实现定义

类型安全

  • 支持强类型的观点有助于尽早发现程序中的简单错误
  • 反之的观点则认为会迫使程序员面对底层、实现而非事务逻辑
  • 总的来说,早期语言强调类型,面向底层的语言强调类型
  • C语言需要类型,但是对类型的安全检查并不够

C语言的数据类型

  • 整数
    • char 、 short、 int、 long、 longlong
  • 浮点数
    • float 、 double、 long double
  • 逻辑
  • bool(人为定义)
  • 指针
  • 自定义类型

exp:以上加粗部分的数据类型为C99的类型

不同点:

  1. 输出输入时的格式化: %d、%ld、%lf
  2. 表达数的范围:char<short<int<float<double
  3. 在内存中占据的大小也不同:1字节到16字节
  4. 内存中的表达形式:二进制数(补码)–整型、编码–浮点数

sizeof运算符

给出某个类型或变量在内存中所占据的字节数

1字节=8比特

注意:

  • 是静态运算符,结果在编译时刻就决定
  • 不要在sizeof()的括号里面做运算,这些运算是不会做的,例如:
    int a = 6;
    printf("sizeof(a++)=%d\n"
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值