13 万字 C 语言从入门到精通保姆级教程2021 年版


友情提示:先关注收藏,再查看,13 万字保姆级 C 语言从入门到精通教程。

文章目录

计算机常识

  • 什么是计算机 ?

    • 顾名思义,就是能够进行数据运算的机器(台式电脑、笔记本电脑、平板电脑、智能手机)
    • 计算机_百度百科
  • 计算机的发明者是谁 ?

    • 关于电子计算机的发明者是谁这一问题,有好几种答案:
      • 1936年***英国数学家图灵***首先提出了一种以程序和输入数据相互作用产生输出的计算机***构想***,后人将这种机器命名为通用图灵计算机
      • 1938年***克兰德·楚泽***发明了首台采用***继电器***进行工作的计算机,这台计算机命名为***Z1***,但是继电器是机械式的,并不是完全的电子器材
      • 1942年***阿坦那索夫和贝利***发明了首台采用***真空管***的计算机,这台计算机命名为***ABC***
      • 1946年ENIAC诞生,它拥有了今天计算机的主要结构和功能,是通用计算机
  • 现在世界上***公认***的第一台现代电子计算机是1946年在美国宾夕法尼亚大学诞生的ENIAC(Electronic Numerical Integrator And Calculator)
  • 计算机特点是什么 ?
    • 计算机是一种电器, 所以计算机只能识别两种状态, 一种是通电一种是断电

    • 正是因为如此, 最初ENIAC的程序是由很多开关和连接电线来完成的。但是这样导致***改动一次程序要花很长时间***(需要人工重新设置很多开关的状态和连接线)

    • 为了提高效率,工程师们想能不能把程序和数据都放在存储器中, 数学家冯·诺依曼将这个思想以数学语言系统阐述,提出了存储程序计算机模型(这是所谓的冯·诺依曼机)

    • 那利用数学语言如何表示计算机能够识别的通电和断电两种状态呢?

      • 非常简单用0和1表示即可
      • 所以计算机能识别的所有指令都是由0和1组成的
      • 所以计算机中存储和操作的数据也都是由0和1组成的

0和1更准确的是应该是高电平和低电平, 但是这个不用了解, 只需要知道计算机只能识别0和1以及存储的数据都是由0和1组成的即可。


什么是计算机程序 ?

  • 计算机程序是为了告诉计算机"做某件事或解决某个问题"而用"***计算机语言***编写的命令集合(语句)

  • 只要让计算机执行这个程序,计算机就会自动地、有条不紊地进行工作,计算机的一切操作都是由程序控制的,离开程序,计算机将一事无成

  • 现实生活中你如何告诉别人如何做某件事或者解决某个问题?

    • 通过人能听懂的语言: 张三你去楼下帮我买一包烟, 然后顺便到快递箱把我的快递也带上来
    • 其实我们通过人能听懂的语言告诉别人做某件事就是在发送一条条的指令
    • 计算机中也一样, 我们可以通过计算机语言告诉计算机我们想做什么, 每做一件事情就是一条指令, 一条或多条指令的集合我们就称之为一个计算机程序

什么是计算机语言 ?

  • 在日常生活、工作中, 语言是人们交流的工具
    • 中国人和中国人交流,使用中文语言
    • 美国人和美国人交流,使用英文语言
    • 人想要和计算机交流,使用计算机语言
  • 可以看出在日常生活、工作中,人们使用的语言种类很多
    • 如果一个很牛人可能同时掌握了中文语言和英文语言, 那么想要和这个人交流既可以使用中文语言,也可以使用英文语言
    • 计算机其实就是一个很牛的人, 计算机同时掌握了几十门甚至上百门语言, 所以我们只要使用任何一种计算机已经掌握的语言就可以和计算机交流

常见的计算机语言类型有哪些 ?

  • 机器语言
    • 所有的代码里面只有0和1, 0表示不加电,1表示加电(纸带存储时 1有孔,0没孔)
    • 优点:直接对硬件产生作用,程序的执行效率非常非常高
    • 缺点:指令又多又难记、可读性差、无可移植性
  • 汇编语言
    • 符号化的机器语言,用一个符号(英文单词、数字)来代表一条机器指令
    • 优点:直接对硬件产生作用,程序的执行效率非常高、可读性稍好
    • 缺点:符号非常多和难记、无可移植性
  • 高级语言
    • 非常接近自然语言的高级语言,语法和结构类似于普通英文
    • 优点:简单、易用、易于理解、远离对硬件的直接操作、有可移植性
    • 缺点:有些高级语言写出的程序执行效率并不高
  • 对比(利用3种类型语言编写1+1)
    • 机器语言
      • 10111000 00000001 00000000 00000101 00000001 00000000
    • 汇编语言
      • MOV AX, 1 ADD AX, 1
    • 高级语言
      • 1 + 1

什么是C语言?

  • C语言是一种用于和计算机交流的高级语言, 它既具有高级语言的特点,又具有汇编语言的特点
    • 非常接近自然语言
    • 程序的执行效率非常高
  • C语言是所有编程语言中的经典,很多高级语言都是从C语言中衍生出来的,
    • 例如:C++、C#、Object-C、Java、Go等等
  • C语言是所有编程语言中的经典,很多著名的系统软件也是C语言编写的
    • 几乎所有的操作系统都是用C语言编写的
    • 几乎所有的计算机底层软件都是用C语言编写的
    • 几乎所有的编辑器都是C语言编写的

C语言历史

  • 最早的高级语言:FORTRAN–>ALGOL–>CPL–>BCPL–>C–>C++等

“初,世间无语言,仅电路与连线。及大牛出,天地开,始有 FORTRAN、 LISP、ALGOL 随之, 乃有万种语”

  • 1963年英国剑桥大学推出了CPL(Combined Programming Langurage)语言。 CPL语言在ALGOL 60的基础上接近硬件一些,但规模比较大,难以实现
  • 1967年英国剑桥大学的 Matin Richards(理查兹)对CPL语言做了简化,推出了 BCPL (Base Combined Programming Langurage)语言
  • 1970年美国贝尔实验室的 Ken Thompson(肯·汤普逊) 以 BCPL 语言为基础,又作了进一步的简化,设计出了很简单的而且很接近硬件的 B 语言(取BCPL的第一个字母),并用B语言写出了第一个 UNIX 操作系统。但B语言过于简单,功能有限
  • 1972年至1973年间,贝尔实验室的 Dennis.Ritchie(丹尼斯·里奇) 在 B语言的基础上设计出了C语言(取BCPL的第二个字母)。C语言即保持 BCPL 语言和B语言的优点(精练、接近硬件),又克服了他们的缺点(过于简单,数据无类型等)

C语言标准

  • 1983年美国国家标准局(American National Standards Institute,简称ANSI)成立了一个委员会,开始制定C语言标准的工作
  • 1989年C语言标准被批准,这个版本的C语言标准通常被称为ANSI C(C89)
  • 1999年,国际标准化组织ISO又对C语言标准进行修订,在基本保留原C语言特征的基础上,针对应该的需要,增加了一些功能,命名为***C99***
  • 2011年12月,ANSI采纳了ISO/IEC 9899:2011标准。这个标准通常即***C11,它是C程序语言的现行标准***

C语言现状


为什么要学习C语言?

  • 40多年经久不衰
  • 了解操作系统、编译原理、数据结构与算法等知识的最佳语言
  • 了解其它语言底层实现原理必备语言
  • 基础语法与其它高级语言类似,学会C语言之后再学习其它语言事半功倍,且知根知底

当你想了解底层原理时,你才会发现后悔当初没有学习C语言
当你想学习一门新的语言时, 你才会发现后悔当初没有学习C语言
当你使用一些高级框架、甚至系统框架时发现提供的API都是C语言编写的, 你才发现后悔当初没有学习C语言
学好数理化,走遍天下都不拍
学好C语言,再多语言都不怕


如何学好C语言

学习本套课程之前 学习本套课程中 学习本套课程之后
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gHyaoC72-1623039894713)(https://upload-images.jianshu.io/upload_images/647982-c724f6cd01191121.png?imageMogr2/auto-orient/strip)]
  • 如何达到这样的效果

工欲善其事必先利其器

编写C语言程序用什么工具 ?

  • 记事本(开发效率低)
  • Vim(初学者入门门槛高)
  • VSCode(不喜欢)
  • eclipse(不喜欢)
  • CLion(深爱, 但收费)
  • Xcode(逼格高, 但得有苹果电脑)
  • Qt Creator(开源免费,跨平台安装和运行)

什么是Qt Creator ?

  • Qt Creator 是一款新的轻量级集成开发环境(IDE)。它能够跨平台运行,支持的系统包括 Windows、Linux(32 位及 64 位)以及 Mac OS X
  • Qt Creator 的设计目标是使开发人员能够利用 Qt 这个应用程序框架更加快速及轻易的完成开发任务
  • 开源免费, 简单易用, 能够满足学习需求

集成开发环境(IDE,Integrated Development Environment )是用于提供程序开发环境的应用程序,一般包括代码编辑器编译器调试器和图形用户界面等工具。集成了代码编写功能、分析功能、编译功能、调试功能等一体化的开发软件服务套。


Qt Creator安装

  • 切记囫囵吞枣, 不要纠结里面的东西都是什么含义, 初学者安装成功就是一种成功

  • 下载Qt Creator离线安装包:

    • http://download.qt.io/archive/qt/
    • 极速下载地址:
    • 链接:https://pan.baidu.com/s/1gx0hNDBJkA2gx5wF1Jx34w
      提取码:0fg9
  • 以管理身份运行离线安装包

  • 下一步,下一步,下一步,等待ing…


    • +
      +
  • 注意安装路径中最好不要出现中文

  • 对于初学者而言全选是最简单的方式(重点!!!)





  • 配置Qt Creator开发环境变量





你的安装路径\5.11.0\mingw53_32\bin
你的安装路径\Tools\mingw530_32\bin

  • 启动安装好的Qt Creator

  • 非全选安装到此为止, 全选安装继续往下看
    • 出现这个错误, 忽略这个错误即可
  • 等待安装完毕之后解决刚才的错误
    • 找到安装目录下的strawberry.msi,双击运行




什么是环境变量?

  • 打开我们添加环境变量的两个目录, 不难发现里面大部分都是.exe的可执行程序
  • 如果我们不配置环境变量, 那么每次我们想要使用这些"可执行程序"都必须"先找到这些应用程序对应的文件夹"才能使用
  • 为了方便我们在电脑上"任何地方"都能够使用这些"可执行程序", 那么我们就必须添加环境变量, 因为Windows执行某个程序的时候, 会先到"环境变量中Path指定的路径中"去查找

为什么要配置系统变量,不配置用户变量

  • 用户变量只针对使用这台计算机指定用户
    • 一个计算机可以设置多个用户, 不同的用户用不同的用户名和密码
    • 当给计算机设置了多个用户的时候,启动计算机的时候就会让你选择哪个用户登录
  • 系统变量针对使用这台计算机的所有用户
    • 也就是说设置了系统变量, 无论哪个用户登录这台计算机都可以使用你配置好的工具

Qt Creator快捷键

如何创建C语言程序

  • 这个世界上, 几乎所有程序员入门的第一段代码都是Hello World.
  • 原因是当年C语言的作者Dennis Ritchie(丹尼斯 里奇)在他的名著中第一次引入, 传为后世经典, 其它语言亦争相效仿, 以示敬意

如何创建C语言文件





C语言程序组成

  • 手机有很多功能, “开机”,“关机”,“打电话”,“发短信”,"拍照"等等

  • 手机中的每一个功能就相当于C语言程序中的一个程序段(函数)

  • 众多功能中总有一个会被先执行,不可能多个功能一起执行

  • 想使用手机必须先执行手机的开机功能

  • 所以C语言程序也一样,由众多功能、众多程序段组成, 众多C语言程序段中总有一个会被先执行, 这个先执行的程序段我们称之为"主函数"

  • 一个C语言程序由多个"函数"构成,每个函数有自己的功能

  • 一个程序***有且只有一个主函数***

  • 如果一个程序没有主函数,则这个程序不具备运行能力

  • 程序运行时系统会***自动调用***主函数,而其它函数需要开发者***手动调用***

  • 主函数有固定书写的格式和范写

函数定义格式

  • 主函数定义的格式:
    • int 代表函数执行之后会返回一个整数类型的值
    • main 代表这个函数的名字叫做main
    • () 代表这是一个函数
    • {} 代表这个程序段的范围
    • return 0; 代表函数执行完之后返回整数0
int main() {
    // insert code here...
    return 0;
}
  • 其它函数定义的格式
    • int 代表函数执行之后会返回一个整数类型的值
    • call 代表这个函数的名字叫做call
    • () 代表这是一个函数
    • {} 代表这个程序段的范围
    • return 0; 代表函数执行完之后返回整数0
int call() {
    return 0;
}

如何执行定义好的函数

  • 主函数(main)会由系统自动调用, 但其它函数不会, 所以想要执行其它函数就必须在main函数中手动调用
    • call 代表找到名称叫做call的某个东西
    • () 代表要找到的名称叫call的某个东西是一个函数
    • ; 代表调用函数的语句已经编写完成
    • 所以call();代表找到call函数, 并执行call函数
int main() {
    call();
    return 0;
}
  • 如何往屏幕上输出内容
    • 输出内容是一个比较复杂的操作, 所以系统提前定义好了一个专门用于输出内容的函数叫做printf函数,我们只需要执行系统定义好的printf函数就可以往屏幕上输出内容
    • 但凡需要执行一个函数, 都是通过函数名称+圆括号的形式来执行
    • 如下代码的含义是: 当程序运行时系统会自动执行main函数, 在系统自动执行main函数时我们手动执行了call函数和printf函数
    • 经过对代码的观察, 我们发现两个问题
      • 并没有告诉printf函数,我们要往屏幕上输出什么内容
      • 找不到printf函数的实现代码
int call(){
    return 0;
}

int main(){
    call();
    printf();
    return 0;
}
  • 如何告诉printf函数要输出的内容
    • 将要输出的内容编写到printf函数后面的圆括号中即可
    • 注意: 圆括号中编写的内容必须用双引号引起来
printf("hello world\n");
  • 如何找到printf函数的实现代码
    • 由于printf函数是系统实现的函数, 所以想要使用printf函数必须在使用之前告诉系统去哪里可以找到printf函数的实现代码
    • #include <stdio.h> 就是告诉系统可以去stdio这个文件中查找printf函数的声明和实现
#include <stdio.h>

int call(){
    return 0;
}

int main(){
    call();
    printf("hello world\n");
    return 0;
}

如何运行编写好的程序

  • 方式1:
    • 点击小榔头将"源代码"编译成"可执行文件"
    • 找到编译后的源代码, 打开终端(CMD)运行可执行文件




  • 方式2
    • 直接点击Qt开发工具运行按钮


main函数注意点及其它写法

  • C语言中,每条完整的语句后面都必须以分号结尾
int main(){
    printf("hello world\n") // 如果没有分号编译时会报错
    return 0;
}
int main(){
    // 如果没有分号,多条语句合并到一行时, 系统不知道从什么地方到什么地方是一条完整语句
    printf("hello world\n") return 0;
}
  • C语言中除了注释和双引号引起来的地方以外都不能出现中文
int main(){
    printf("hello world\n"); // 这里的分号如果是中文的分号就会报错
    return 0;
}
  • 一个C语言程序只能有一个main函数
int main(){
    return 0;
}
int main(){ // 编译时会报错, 重复定义
    return 0;
}
  • 一个C语言程序不能没有main函数
int call(){ // 编译时报错, 因为只有call函数, 没有main函数
    return 0;
}
int mian(){ // 编译时报错, 因为main函数的名称写错了,还是相当于没有main函数
    return 0;
}
  • main函数前面的int可以不写或者换成void
#include <stdio.h>
main(){ // 不会报错
    printf("hello world\n");
    return 0;
}
#include <stdio.h>
void main(){  // 不会报错
    printf("hello world\n");
    return 0;
}
  • main函数中的return 0可以不写
int main(){ // 不会报错
    printf("hello world\n");
}
  • 多种写法不报错的原因
    • C语言最早的时候只是一种规范和标准(例如C89, C11等)
    • 标准的推行需要各大厂商的支持和实施
    • 而在支持的实施的时候由于各大厂商利益、理解等问题,导致了实施的标准不同,发生了变化
      • Turbo C
      • Visual C(VC)
      • GNU C(GCC)
    • 所以大家才会看到不同的书上书写的格式有所不同, 有的返回int,有的返回void,有的甚至没有返回值
    • 所以大家只需要记住最标准的写法即可, no zuo no die
#include <stdio.h>
int main(){
    printf("hello world\n");
    return 0;
}

Tips:
语法错误:编译器会直接报错
逻辑错误:没有语法错误,只不过运行结果不正确


C语言程序练习

  • 编写一个C语言程序,用至少2种方式在屏幕上输出以下内容
   *** ***
  *********
   *******
    ****
     **
  • 普通青年实现
printf(" *** *** \n");
printf("*********\n");
printf(" *******\n");
printf("  ****\n");
printf("   **\n");
  • 2B青年实现
printf(" *** *** \n*********\n *******\n  ****\n   **\n");
  • 文艺青年实现(装逼的, 先不用理解)
int  i = 0;
while (1) {
    if (i % 2 == 0) {
        printf(" *** *** \n");
        printf("*********\n");
        printf(" *******\n");
        printf("  ****\n");
        printf("   **\n");
    }else
    {
        printf("\n");
        printf("   ** ** \n");
        printf("  *******\n");
        printf("   *****\n");
        printf("    **\n");
    }
    sleep(1);
    i++;
    system("cls");
}

初学者如何避免程序出现BUG

                          _ooOoo_
                         o8888888o
                         88" . "88
                         (| -_- |)
                          O\ = /O
                      ____/`---'\____
                    .   ' \\| |// `.
                     / \\||| : |||// \
                   / _||||| -:- |||||- \
                     | | \\\ - /// | |
                   | \_| ''\---/'' | |
                    \ .-\__ `-` ___/-. /
                 ___`. .' /--.--\ `. . __
              ."" '< `.___\_<|>_/___.' >'"".
             | | : `- \`.;`\ _ /`;.`/ - ` : | |
               \ \ `-. \_ __\ /__ _/ .-` / /
       ======`-.____`-.___\_____/___.-`____.-'======
                          `=---='

       .............................................
              佛祖保佑                   有无BUG
━━━━━━神兽出没━━━━━━
         ┏┓    ┏┓
        ┏┛┻━━━━━━┛┻┓
        ┃        ┃
        ┃   ━    ┃
        ┃ ┳┛   ┗┳ ┃
        ┃        ┃
        ┃   ┻    ┃
        ┃          ┃
        ┗━┓    ┏━┛Code is far away from bug with the animal protecting
          ┃    ┃    神兽保佑,代码无bug
          ┃    ┃
          ┃    ┗━━━┓
          ┃        ┣┓
          ┃     ┏━━┛┛
          ┗┓┓┏━┳┓┏┛
           ┃┫┫ ┃┫┫
           ┗┻┛ ┗┻┛

      ━━━━━━感觉萌萌哒━━━━━━
        ´´´´´´´´██´´´´´´´
        ´´´´´´´████´´´´´´
        ´´´´´████████´´´´
        ´´`´███▒▒▒▒███´´´´´
        ´´´███▒●▒▒●▒██´´´
        ´´´███▒▒▒▒▒▒██´´´´´
        ´´´███▒▒▒▒██´                      项目:第一个C语言程序
        ´´██████▒▒███´´´´´                 语言: C语言
        ´██████▒▒▒▒███´´                   编辑器: Qt Creator 
        ██████▒▒▒▒▒▒███´´´´                版本控制:git-github
        ´´▓▓▓▓▓▓▓▓▓▓▓▓▓▒´´                 代码风格:江哥style
        ´´▒▒▒▒▓▓▓▓▓▓▓▓▓▒´´´´´              
        ´.▒▒▒´´▓▓▓▓▓▓▓▓▒´´´´´              
        ´.▒▒´´´´▓▓▓▓▓▓▓▒                   
        ..▒▒.´´´´▓▓▓▓▓▓▓▒                   
        ´▒▒▒▒▒▒▒▒▒▒▒▒                      
        ´´´´´´´´´███████´´´´´              
        ´´´´´´´´████████´´´´´´´
        ´´´´´´´█████████´´´´´´
        ´´´´´´██████████´´´´             大部分人都在关注你飞的高不高,却没人在乎你飞的累不累,这就是现实!
        ´´´´´´██████████´´´                     我从不相信梦想,我,只,相,信,自,己!
        ´´´´´´´█████████´´
        ´´´´´´´█████████´´´
        ´´´´´´´´████████´´´´´
        ________▒▒▒▒▒
        _________▒▒▒▒
        _________▒▒▒▒
        ________▒▒_▒▒
        _______▒▒__▒▒
        _____ ▒▒___▒▒
        _____▒▒___▒▒
        ____▒▒____▒▒
        ___▒▒_____▒▒
        ███____ ▒▒
        ████____███
        █ _███_ _█_███
——————————————————————————女神保佑,代码无bug——————————————————————

多语言对比

  • C语言
#include<stdio.h>
int main() {
    printf("南哥带你装B带你飞");
    return 0;
}
  • C++语言
#include<iostream>
using namespace std;
int main() {
    cout << "南哥带你装B带你飞" << endl;
    return 0;
}
  • OC语言
#import <Foundation/Foundation.h>
int main() {
    NSLog(@"南哥带你装B带你飞");
    return 0;
}
  • Java语言
class Test
{
    public static viod main()
    {
        system.out.println("南哥带你装B带你飞");
    }
}
  • Go语言
package main
import  "fmt" //引入fmt库
func main() {
    fmt.Println("南哥带你装B带你飞")
}

什么是注释?

  • 注释是在所有计算机语言中都非常重要的一个概念,从字面上看,就是注解、解释的意思
  • 注释可以用来解释某一段程序或者某一行代码是什么意思,方便程序员之间的交流沟通
  • 注释可以是任何文字,也就是说可以写中文
  • 被注释的内容在开发工具中会有特殊的颜色

为什么要使用注释?

  • 没有编写任何注释的程序
void printMap(char map[6][7] , int row, int col);
int main(int argc, const char * argv[])
{
    char map[6][7] = {
        {'#', '#', '#', '#', '#', '#', '#'},
        {'#', ' ', ' ', ' ', '#' ,' ', ' '},
        {'#', 'R', ' ', '#', '#', ' ', '#'},
        {'#', ' ', ' ', ' ', '#', ' ', '#'},
        {'#', '#', ' ', ' ', ' ', ' ', '#'},
        {'#', '#', '#', '#', '#', '#', '#'}
    };
    int row = sizeof(map)/sizeof(map[0]);
    int col = sizeof(map[0])/ sizeof(map[0][0]);
    printMap(map, row, col);
    int pRow = 2;
    int pCol = 1;
    int endRow = 1;
    int endCol = 6;
    while ('R' != map[endRow][endCol]) {
        printf("亲, 请输入相应的操作\n");
        printf("w(向上走) s(向下走) a(向左走) d(向右走)\n");
        char run;
        run = getchar();
        switch (run) {
            case 's':
                if ('#' != map[pRow + 1][pCol]) {
                    map[pRow][pCol] = ' ';
                    pRow++;//3
                    map[pRow][pCol] = 'R';
                }
                break;
            case 'w':
                if ('#' != map[pRow - 1][pCol]) {
                    map[pRow][pCol] = ' ';
                    pRow--;
                    map[pRow][pCol] = 'R';
                }
                break;
            case 'a':
                if ('#' != map[pRow][pCol - 1]) {
                    map[pRow][pCol] = ' ';
                    pCol--;
                    map[pRow][pCol] = 'R';
                }
                break;
            case 'd':
                if ('#' != map[pRow][pCol + 1]) {
                    map[pRow][pCol] = ' ';
                    pCol++;
                    map[pRow][pCol] = 'R';
                }
                break;
        }
        printMap(map, row, col);
    }
    printf("你太牛X了\n");
    printf("想挑战自己,请购买完整版本\n");
    return 0;
}
void printMap(char map[6][7] , int row, int col)
{
    system("cls");
    for (int i = 0; i < row; i++) {
        for (int j = 0; j < col; j++) {
            printf("%c", map[i][j]);
        }
        printf("\n");
    }
}

  • 编写了注释的程序
/*
     R代表一个人
     #代表一堵墙
//   0123456
     ####### // 0
     #   #   // 1
     #R ## # // 2
     #   # # // 3
     ##    # // 4
     ####### // 5

     分析:
     >1.保存地图(二维数组)
     >2.输出地图
     >3.操作R前进(控制小人行走)
      3.1.接收用户输入(scanf/getchar)
      w(向上走) s(向下走) a(向左走) d(向右走)
      3.2.判断用户的输入,控制小人行走
         3.2.1.替换二维数组中保存的数据
             (
                1.判断是否可以修改(如果不是#就可以修改)
                2.修改现有位置为空白
                3.修改下一步为R
             )
      3.3.输出修改后的二维数组
     4.判断用户是否走出出口
*/
// 声明打印地图方法
void printMap(char map[6][7] , int row, int col);
int main(int argc, const char * argv[])
{
    // 1.定义二维数组保存迷宫地图
    char map[6][7] = {
        {'#', '#', '#', '#', '#', '#', '#'},
        {'#', ' ', ' ', ' ', '#' ,' ', ' '},
        {'#', 'R', ' ', '#', '#', ' ', '#'},
        {'#', ' ', ' ', ' ', '#', ' ', '#'},
        {'#', '#', ' ', ' ', ' ', ' ', '#'},
        {'#', '#', '#', '#', '#', '#', '#'}
    };
    // 2.计算地图行数和列数
    int row = sizeof(map)/sizeof(map[0]);
    int col = sizeof(map[0])/ sizeof(map[0][0]);
    // 3.输出地图
    printMap(map, row, col);
    // 4.定义变量记录人物位置
    int pRow = 2;
    int pCol = 1;
    // 5.定义变量记录出口的位置
    int endRow = 1;
    int endCol = 6;
    // 6.控制人物行走
    while ('R' != map[endRow][endCol]) {
        // 6.1提示用户如何控制人物行走
        printf("亲, 请输入相应的操作\n");
        printf("w(向上走) s(向下走) a(向左走) d(向右走)\n");
        char run;
        run = getchar();
        // 6.2根据用户输入控制人物行走
        switch (run) {
            case 's':
                if ('#' != map[pRow + 1][pCol]) {
                    map[pRow][pCol] = ' ';
                    pRow++;//3
                    map[pRow][pCol] = 'R';
                }
                break;
            case 'w':
                if ('#' != map[pRow - 1][pCol]) {
                    map[pRow][pCol] = ' ';
                    pRow--;
                    map[pRow][pCol] = 'R';
                }
                break;
            case 'a':
                if ('#' != map[pRow][pCol - 1]) {
                    map[pRow][pCol] = ' ';
                    pCol--;
                    map[pRow][pCol] = 'R';
                }
                break;
            case 'd':
                if ('#' != map[pRow][pCol + 1]) {
                    map[pRow][pCol] = ' ';
                    pCol++;
                    map[pRow][pCol] = 'R';
                }
                break;
        }
        // 6.3重新输出行走之后的地图
        printMap(map, row, col);
    }
    printf("你太牛X了\n");
    printf("想挑战自己,请购买完整版本\n");
    return 0;
}

/**
 * @brief printMap
 * @param map 需要打印的二维数组
 * @param row 二维数组的行数
 * @param col 二维数组的列数
 */
void printMap(char map[6][7] , int row, int col)
{
    // 为了保证窗口的干净整洁, 每次打印都先清空上一次的打印
    system("cls");
    for (int i = 0; i < row; i++) {
        for (int j = 0; j < col; j++) {
            printf("%c", map[i][j]);
        }
        printf("\n");
    }
}

注释的分类

  • 单行注释

    • // 被注释内容
    • 使用范围:任何地方都可以写注释:函数外面、里面,每一条语句后面
    • 作用范围: 从第二个斜线到这一行末尾
    • 快捷键:Ctrl+/
  • 多行注释

    • /* 被注释内容 */
    • 使用范围:任何地方都可以写注释:函数外面、里面,每一条语句后面
    • 作用范围: 从第一个/*到最近的一个*/

注释的注意点

  • 单行注释可以嵌套单行注释、多行注释
// 南哥 // it666.com
// /* 江哥 */
// 帅哥
  • 多行注释可以嵌套单行注释
/*
// 作者:LNJ
// 描述:第一个C语言程序作用:这是一个主函数,C程序的入口点
 */
  • 多行注释***不能***嵌套多行注释
/* 
哈哈哈
     /*嘻嘻嘻*/
 呵呵呵 
*/

注释的应用场景

  • 思路分析
/*
     R代表一个人
     #代表一堵墙
//   0123456
     ####### // 0
     #   #   // 1
     #R ## # // 2
     #   # # // 3
     ##    # // 4
     ####### // 5

     分析:
     >1.保存地图(二维数组)
     >2.输出地图
     >3.操作R前进(控制小人行走)
      3.1.接收用户输入(scanf/getchar)
      w(向上走) s(向下走) a(向左走) d(向右走)
      3.2.判断用户的输入,控制小人行走
         3.2.1.替换二维数组中保存的数据
             (
                1.判断是否可以修改(如果不是#就可以修改)
                2.修改现有位置为空白
                3.修改下一步为R
             )
      3.3.输出修改后的二维数组
     4.判断用户是否走出出口
*/
  • 对变量进行说明
// 2.计算地图行数和列数
int row = sizeof(map)/sizeof(map[0]);
int col = sizeof(map[0])/ sizeof(map[0][0]);
  • 对函数进行说明
/**
 * @brief printMap
 * @param map 需要打印的二维数组
 * @param row 二维数组的行数
 * @param col 二维数组的列数
 */
void printMap(char map[6][7] , int row, int col)
{
    system("cls");
    for (int i = 0; i < row; i++) {
        for (int j = 0; j < col; j++) {
            printf("%c", map[i][j]);
        }
        printf("\n");
    }
}
  • 多实现逻辑排序
    // 1.定义二维数组保存迷宫地图
    char map[6][7] = {
        {'#', '#', '#', '#', '#', '#', '#'},
        {'#', ' ', ' ', ' ', '#' ,' ', ' '},
        {'#', 'R', ' ', '#', '#', ' ', '#'},
        {'#', ' ', ' ', ' ', '#', ' ', '#'},
        {'#', '#', ' ', ' ', ' ', ' ', '#'},
        {'#', '#', '#', '#', '#', '#', '#'}
    };
    // 2.计算地图行数和列数
    int row = sizeof(map)/sizeof(map[0]);
    int col = sizeof(map[0])/ sizeof(map[0][0]);
    // 3.输出地图
    printMap(map, row, col);
    // 4.定义变量记录人物位置
    int pRow = 2;
    int pCol = 1;
    // 5.定义变量记录出口的位置
    int endRow = 1;
    int endCol = 6;
    // 6.控制人物行走
    while ('R' != map[endRow][endCol]) {
        ... ...
    }

使用注释的好处

  • 注释是一个程序员必须要具备的良好习惯
  • 帮助开发人员整理实现思路
  • 解释说明程序, 提高程序的可读性
    • 初学者编写程序可以养成习惯:先写注释再写代码
    • 将自己的思想通过注释先整理出来,在用代码去体现
    • 因为代码仅仅是思想的一种体现形式而已

什么是关键字?

  • 关键字,也叫作保留字。是指一些被C语言赋予了特殊含义的单词
  • 关键字特征:
    • 全部都是小写
    • 在开发工具中会显示特殊颜色
  • 关键字注意点:
    • 因为关键字在C语言中有特殊的含义, 所以不能用作变量名、函数名等
  • C语言中一共有32个关键字
1 2 3 4 5 6 7 8
char short int long float double if else
return do while for switch case break continue
default goto sizeof auto register static extern unsigned
signed typedef struct enum union void const volatile

这些不用专门去记住,用多了就会了。在编译器里都是有特殊颜色的。 我们用到时候会一个一个讲解这个些关键字怎么用,现在浏览下,有个印象就OK了


关键字分类

什么是标识符?

  • 从字面上理解,就是用来标识某些东西的符号,标识的目的就是为了将这些东西区分开来
  • 其实标识符的作用就跟人类的名字差不多,为了区分每个人,就在每个人出生的时候起了个名字
  • C语言是由函数构成的,一个C程序中可能会有多个函数,为了区分这些函数,就给每一个函数都起了个名称, 这个名称就是标识符
  • 综上所述: 程序员在程序中给函数、变量等起名字就是标识符

标识符命名规则

  • 只能由字母(a~z、 A~Z)、数字、下划线组成
  • 不能包含除下划线以外的其它特殊字符串
  • 不能以数字开头
  • 不能是C语言中的关键字
  • 标识符严格区分大小写, test和Test是两个不同的标识符

练习

  • 下列哪些是合法的标识符
fromNo22 from#22 my_Boolean my-Boolean 2ndObj GUI lnj
Mike2jack 江哥 _test test!32 haha(da)tt jack_rose jack&rose

标识符命名规范

  • 见名知意,能够提高代码的可读性
  • 驼峰命名,能够提高代码的可读性
    • 驼峰命名法就是当变量名或函数名是由多个单词连接在一起,构成标识符时,第一个单词以小写字母开始;第二个单词的首字母大写.
    • 例如: myFirstName、myLastName这样的变量名称看上去就像驼峰一样此起彼伏

什么是数据?

  • 生活中无时无刻都在跟数据打交道

    • 例如:人的体重、身高、收入、性别等数据等
  • 在我们使用计算机的过程中,也会接触到各种各样的数据

    • 例如: 文档数据、图片数据、视频数据等

数据分类

  • 静态的数据

    • 静态数据是指一些永久性的数据,一般存储在硬盘中。硬盘的存储空间一般都比较大,现在普通计算机的硬盘都有500G左右,因此硬盘中可以存放一些比较大的文件
    • 存储的时长:计算机关闭之后再开启,这些数据依旧还在,只要你不主动删掉或者硬盘没坏,这些数据永远都在
    • 哪些是静态数据:静态数据一般是以文件的形式存储在硬盘上,比如文档、照片、视频等。
  • 动态的数据

    • 动态数据指在程序运行过程中,动态产生的临时数据,一般存储在内存中。内存的存储空间一般都比较小,现在普通计算机的内存只有8G左右,因此要谨慎使用内存,不要占用太多的内存空间
    • 存储的时长:计算机关闭之后,这些临时数据就会被清除
    • 哪些是动态数据:当运行某个程序(软件)时,整个程序就会被加载到内存中,在程序运行过程中,会产生各种各样的临时数据,这些临时数据都是存储在内存中的。当程序停止运行或者计算机被强制关闭时,这个程序产生的所有临时数据都会被清除。
  • 既然硬盘的存储空间这么大,为何不把所有的应用程序加载到硬盘中去执行呢?

    • 主要***原因就是内存的访问速度比硬盘快N倍***

  • 静态数据和动态数据的相互转换
    • 也就是从磁盘加载到内存
  • 动态数据和静态数据的相互转换
    • 也就是从内存保存到磁盘
  • 数据的计量单位
    • 不管是静态还是动态数据,都是0和1组成的
    • 数据越大,包含的0和1就越多
1 B(Byte字节) = 8 bit(位)
// 00000000 就是一个字节
// 111111111 也是一个字节
// 10101010 也是一个字节
// 任意8个0和1的组合都是一个字节
1 KB(KByte) = 1024 B
1 MB = 1024 KB
1 GB = 1024 MB
1 TB = 1024 GB

C语言数据类型

  • 作为程序员, 我们最关心的是内存中的动态数据,因为我们写的程序就是在内存中运行的
  • 程序在运行过程中会产生各种各样的临时数据,为了方便数据的运算和操作, C语言对这些数据进行了分类, 提供了丰富的数据类型
  • C语言中有4大类数据类型:基本类型、构造类型、指针类型、空类型


什么是常量?

  • "量"表示数据。常量,则表示一些固定的数据,也就是不能改变的数据
  • 就好比现实生活中生男生女一样, 生下来是男孩永远都是男孩, 生下来是女孩就永远都是女孩, 所以性别就是现实生活中常量的一种体现
    • 不要和江哥吹牛X说你是泰国来的, 如果你真的来自泰国, 我只能说你赢了

常量的类型

  • 整型常量

    • 十进制整数。例如:666,-120, 0
    • 八进制整数,八进制形式的常量都以0开头。例如:0123,也就是十进制的83;-011,也就是十进 制的-9
    • 十六进制整数,十六进制的常量都是以0x开头。例如:0x123,也就是十进制的291
    • 二进制整数,逢二进一 0b开头。例如: 0b0010,也就是十进制的2
  • 实型常量

    • 小数形式
      • 单精度小数:以字母f或字母F结尾。例如:0.0f、1.01f
      • 双精度小数:十进制小数形式。例如:3.14、 6.66
      • 默认就是双精度
      • 可以没有整数位只有小数位。例如: .3、 .6f
    • 指数形式
      • 以幂的形式表示, 以字母e或字母E后跟一个10为底的幂数
        • 上过初中的都应该知道科学计数法吧,指数形式的常量就是科学计数法的另一种表 示,比如123000,用科学计数法表示为1.23×10的5次方
        • 用C语言表示就是1.23e5或1.23E5
        • 字母e或字母E后面的指数必须为整数
        • 字母e或字母E前后必须要有数字
        • 字母e或字母E前后不能有空格
  • 字符常量

    • 字符型常量都是用’’(单引号)括起来的。例如:‘a’、‘b’、‘c’
    • 字符常量的单引号中只能有一个字符
    • 特殊情况: 如果是转义字符,单引号中可以有两个字符。例如:’\n’、’\t’
  • 字符串常量

    • 字符型常量都是用""(双引号)括起来的。例如:“a”、“abc”、“lnj”
    • 系统会自动在字符串常量的末尾加一个字符’\0’作为字符串结束标志
  • 自定义常量

    • 后期讲解内容, 此处先不用了解
  • 常量类型练习

123 1.1F 1.1 .3 ‘a’ “a” “李南江”

什么是变量?

  • "量"表示数据。变量,则表示一些不固定的数据,也就是可以改变的数据
  • 就好比现实生活中人的身高、体重一样, 随着年龄的增长会不断发生改变, 所以身高、体重就是现实生活中变量的一种体现
  • 就好比现实生活中超市的储物格一样, 同一个格子在不同时期不同人使用,格子中存储的物品是可以变化的。张三使用这个格子的时候里面放的可能是尿不湿, 但是李四使用这个格子的时候里面放的可能是面包

如何定义变量

  • 格式1: 变量类型 变量名称 ;
    • 为什么要定义变量?
      • 任何变量在使用之前,必须先进行定义, 只有定义了变量才会分配存储空间, 才有空间存储数据
    • 为什么要限定类型?
      • 用来约束变量所存放数据的类型。一旦给变量指明了类型,那么这个变量就只能存储这种类型的数据
      • 内存空间极其有限,不同类型的变量占用不同大小的存储空间
    • 为什么要指定变量名称?
      • 存储数据的空间对于我们没有任何意义, 我们需要的是空间中存储的值
      • 只有有了名称, 我们才能获取到空间中的值
int a;
float b;
char ch;
  • 格式2:变量类型 变量名称,变量名称;
    • 连续定义, 多个变量之间用逗号(,)号隔开
int a,b,c;
  • 变量名的命名的规范
    • 变量名属于标识符,所以必须严格遵守标识符的命名原则

如何使用变量?

  • 可以利用=号往变量里面存储数据
    • 在C语言中,利用=号往变量里面存储数据, 我们称之为给变量赋值
int value;
value = 998; // 赋值
  • 注意:
    • 这里的=号,并不是数学中的“相等”,而是C语言中的***赋值运算符***,作用是将右边的整型常量998赋值给左边的整型变量value
    • 赋值的时候,= 号的左侧必须是变量 (10=b,错误)
    • 为了方便阅读代码, 习惯在 = 的两侧 各加上一个 空格

变量的初始化

  • C语言中, 变量的第一次赋值,我们称为“初始化”
  • 初始化的两种形式
    • 先定义,后初始化
    • int value; value = 998; // 初始化
    • 定义时同时初始化
    • int a = 10; int b = 4, c = 2;
    • 其它表现形式(不推荐)
int a, b = 10; //部分初始化
int c, d, e;
c = d = e =0;
  • 不初始化里面存储什么?
    • 随机数
    • 上次程序分配的存储空间,存数一些 内容,“垃圾”
    • 系统正在用的一些数据

如何修改变量值?

  • 多次赋值即可
    • 每次赋值都会覆盖原来的值
int i = 10;
i = 20; // 修改变量的值

变量之间的值传递

  • 可以将一个变量存储的值赋值给另一个变量
 int a = 10;
 int b = a; // 相当于把a中存储的10拷贝了一份给b

如何查看变量的值?

  • 使用printf输出一个或多个变量的值
int a = 10, c = 11;
printf("a=%d, c=%d", a, c);
  • 输出其它类型变量的值
double height = 1.75;
char blood = 'A';
printf("height=%.2f, 血型是%c", height,  blood);

变量的作用域

  • C语言中所有变量都有自己的作用域
  • 变量定义的位置不同,其作用域也不同
  • 按照作用域的范围可分为两种, 即局部变量和全局变量

  • 局部变量
    • 局部变量也称为内部变量
    • 局部变量是在***代码块内***定义的, 其作用域仅限于代码块内, 离开该代码块后无法使用
int main(){
    int i = 998; // 作用域开始
    return 0;// 作用域结束
}
int main(){
    {
        int i = 998; // 作用域开始
    }// 作用域结束
    printf("i = %d\n", i); // 不能使用
    return 0;
}
int main(){
    {
        {
            int i = 998;// 作用域开始
        }// 作用域结束
        printf("i = %d\n", i); // 不能使用
    }
    return 0;
}

  • 全局变量
    • 全局变量也称为外部变量,它是在代码块外部定义的变量
int i = 666;
int main(){
    printf("i = %d\n", i); // 可以使用
    return 0;
}// 作用域结束
int call(){
    printf("i = %d\n", i); // 可以使用
    return 0;
}

  • 注意点:
    • 同一作用域范围内不能有相同名称的变量
int main(){
    int i = 998; // 作用域开始
    int i = 666; // 报错, 重复定义
    return 0;
}// 作用域结束
int i = 666; 
int i = 998; // 报错, 重复定义
int main(){
    return 0;
}
  • 不同作用域范围内可以有相同名称的变量
int i = 666; 
int main(){
    int i = 998; // 不会报错
    return 0;
}
int main(){
    int i = 998; // 不会报错
    return 0;
}
int call(){
    int i = 666;  // 不会报错
    return 0;
}

变量内存分析(简单版)

  • 字节和地址
    • 为了更好地理解变量在内存中的存储细节,先来认识一下内存中的“字节”和“地址”
    • 每一个小格子代表一个字节
    • 每个字节都有自己的内存地址
    • 内存地址是连续的

  • 变量存储占用的空间
    • 一个变量所占用的存储空间,和***定义变量时声明的类型***以及***当前编译环境***有关
类型 16位编译器 32位编译器 64位编译器
char 1 1 1
int 2 4 4
float 4 4 4
double 8 8 8
short 2 2 2
long 4 4 8
long long 8 8 8
void* 2 4 8
  • 变量存储的过程
    • 根据定义变量时声明的类型和当前编译环境确定需要开辟多大存储空间
    • 在内存中开辟一块存储空间,开辟时从内存地址大的开始开辟(内存寻址从大到小)
    • 将数据保存到已经开辟好的对应内存空间中
    int main(){
      int number;
      int value;
      number = 22;
      value = 666;
    }
    
    #include <stdio.h>
    int main(){
        int number;
        int value;
        number = 22;
        value = 666;
        printf("&number = %p\n", &number); // 0060FEAC
        printf("&value = %p\n", &value);   // 0060FEA8
    }
    

先不要着急, 刚开始接触C语言, 我先了解这么多就够了. 后面会再次更深入的讲解存储的各种细节。

printf函数

  • printf函数称之为格式输出函数,方法名称的最后一个字母f表示format。其功能是按照用户指定的格式,把指定的数据输出到屏幕上
  • printf函数的调用格式为:
    • printf("格式控制字符串",输出项列表 );
    • 例如:printf("a = %d, b = %d",a, b);
    • 非格式字符串原样输出, 格式控制字符串会被输出项列表中的数据替换
    • 注意: 格式控制字符串和输出项在数量和类型上***必须一一对应***

  • 格式控制字符串
    • 形式: %[标志][输出宽度][.精度][长度]类型

  • 类型
    • 格式: printf("a = %类型", a);
    • 类型字符串用以表示输出数据的类型, 其格式符和意义如下所示
类型 含义
d 有符号10进制整型
i 有符号10进制整型
u 无符号10进制整型
o 无符号8进制整型
x 无符号16进制整型
X 无符号16进制整型
f 单、双精度浮点数(默认保留6位小数)
e / E 以指数形式输出单、双精度浮点数
g / G 以最短输出宽度,输出单、双精度浮点数
c 字符
s 字符串
p 地址
#include <stdio.h>
int main(){
    int a = 10;
    int b = -10;
    float c = 6.6f;
    double d = 3.1415926;
    double e = 10.10;
    char f = 'a';
    // 有符号整数(可以输出负数)
    printf("a = %d\n", a); // 10
    printf("a = %i\n", a); // 10

    // 无符号整数(不可以输出负数)
    printf("a = %u\n", a); // 10
    printf("b = %u\n", b); // 429496786

    // 无符号八进制整数(不可以输出负数)
    printf("a = %o\n", a); // 12
    printf("b = %o\n", b); // 37777777766

    // 无符号十六进制整数(不可以输出负数)
    printf("a = %x\n", a); // a
    printf("b = %x\n", b); // fffffff6

    // 无符号十六进制整数(不可以输出负数)
    printf("a = %X\n", a); // A
    printf("b = %X\n", b); // FFFFFFF6

    // 单、双精度浮点数(默认保留6位小数)
    printf("c = %f\n", c); // 6.600000
    printf("d = %lf\n", d); // 3.141593

    // 以指数形式输出单、双精度浮点数
    printf("e = %e\n", e); // 1.010000e+001
    printf("e = %E\n", e); // 1.010000E+001
    
    // 以最短输出宽度,输出单、双精度浮点数
    printf("e = %g\n", e); // 10.1
    printf("e = %G\n", e); // 10.1
    
    // 输出字符
    printf("f = %c\n", f); // a
}

  • 宽度
    • 格式: printf("a = %[宽度]类型", a);
    • 用十进制整数来指定输出的宽度, 如果实际位数多于指定宽度,则按照实际位数输出, 如果实际位数少于指定宽度则以空格补位
#include <stdio.h>
int main(){
    // 实际位数小于指定宽度
    int a = 1;
    printf("a =|%d|\n", a); // |1|
    printf("a =|%5d|\n", a); // |    1|
    // 实际位数大于指定宽度
    int b = 1234567;
    printf("b =|%d|\n", b); // |1234567|
    printf("b =|%5d|\n", b); // |1234567|
}

  • 标志
    • 格式: printf("a = %[标志][宽度]类型", a);
标志 含义
- 左对齐, 默认右对齐
+ 当输出值为正数时,在输出值前面加上一个+号, 默认不显示
0 右对齐时, 用0填充宽度.(默认用空格填充)
空格 输出值为正数时,在输出值前面加上空格, 为负数时加上负号
# 对c、s、d、u类型无影响
# 对o类型, 在输出时加前缀o
# 对x类型,在输出时加前缀0x
#include <stdio.h>
int main(){
    int a = 1;
    int b = -1;
    // -号标志
    printf("a =|%d|\n", a); // |1|
    printf("a =|%5d|\n", a); // |    1|
    printf("a =|%-5d|\n", a);// |1    |
    // +号标志
    printf("a =|%d|\n", a); // |1|
    printf("a =|%+d|\n", a);// |+1|
    printf("b =|%d|\n", b); // |-1|
    printf("b =|%+d|\n", b);// |-1|
    // 0标志
    printf("a =|%5d|\n", a); // |    1|
    printf("a =|%05d|\n", a); // |00001|
    // 空格标志
    printf("a =|% d|\n", a); // | 1|
    printf("b =|% d|\n", b); // |-1|
    // #号
    int c = 10;
    printf("c = %o\n", c); // 12
    printf("c = %#o\n", c); // 012
    printf("c = %x\n", c); // a
    printf("c = %#x\n", c); // 0xa
}

  • 精度
    • 格式: printf("a = %[精度]类型", a);
    • 精度格式符以"."开头, 后面跟上十进制整数, 用于指定需要输出多少位小数, 如果输出位数大于指定的精度, 则删除超出的部分
#include <stdio.h>
int main(){
    double a = 3.1415926;
    printf("a = %.2f\n", a); // 3.14
}
  • 动态指定保留小数位数
    • 格式: printf("a = %.*f", a);
#include <stdio.h>
int main(){
    double a = 3.1415926;
    printf("a = %.*f", 2, a); // 3.14
}
  • 实型(浮点类型)有效位数问题
    • 对于单精度数,使用%f格式符输出时,仅前6~7位是有效数字
    • 对于双精度数,使用%lf格式符输出时,前15~16位是有效数字
    • 有效位数和精度(保留多少位)不同, 有效位数是指从第一个非零数字开始,误差不超过本数位半个单位的、精确可信的数位
    • 有效位数包含小数点前的非零数位
#include <stdio.h>
int main(){
    //        1234.567871093750000
    float a = 1234.567890123456789;
    //         1234.567890123456900
    double b = 1234.567890123456789;
    printf("a = %.15f\n", a); // 前8位数字是准确的, 后面的都不准确
    printf("b = %.15f\n", b); // 前16位数字是准确的, 后面的都不准确
}

  • 长度
    • 格式: printf("a = %[长度]类型", a);
长度 修饰类型 含义
hh d、i、o、u、x 输出char
h d、i、o、u、x 输出 short int
l d、i、o、u、x 输出 long int
ll d、i、o、u、x 输出 long long int
#include <stdio.h>
int main(){
    char a = 'a';
    short int b = 123;
    int  c = 123;
    long int d = 123;
    long long int e = 123;
    printf("a = %hhd\n", a); // 97
    printf("b = %hd\n", b); // 123
    printf("c = %d\n", c); // 123
    printf("d = %ld\n", d); // 123
    printf("e = %lld\n", e); // 123
}
  • 转义字符
    • 格式: printf("%f%%", 3.1415);
    • %号在格式控制字符串中有特殊含义, 所以想输出%必须添加一个转移字符
#include <stdio.h>
int main(){
    printf("%f%%", 3.1415); // 输出结果3.1415%
}

Scanf函数

  • scanf函数用于接收键盘输入的内容, 是一个阻塞式函数,程序会停在scanf函数出现的地方, 直到接收到数据才会执行后面的代码
  • printf函数的调用格式为:
    • scanf("格式控制字符串", 地址列表);
    • 例如: scanf("%d", &num);

  • 基本用法
    • 地址列表项中只能传入变量地址, 变量地址可以通过&符号+变量名称的形式获取
#include <stdio.h>
int main(){
    int number;
    scanf("%d", &number); // 接收一个整数
    printf("number = %d\n", number); 
}
  • 接收非字符和字符串类型时, 空格、Tab和回车会被忽略
#include <stdio.h>
int main(){
    float num;
    // 例如:输入 Tab 空格 回车 回车 Tab 空格 3.14 , 得到的结果还是3.14
    scanf("%f", &num);
    printf("num = %f\n", num);
}
  • 非格式字符串原样输入, 格式控制字符串会赋值给地址项列表项中的变量
    • 不推荐这种写法
    <
  • 8518
    点赞
  • 53623
    收藏
    觉得还不错? 一键收藏
  • 560
    评论
Linux IO数据通道: 1.虚拟文件系统层:屏蔽下层具体文件系统操作的差异,为上层的操作提供一个统一的接口。因为有了这个层次,所以可以把设备抽象成文件,使得操作设备就像操作文件一样简单。 2.具体的文件系统层:不同的文件系统(例如 ext2 和 NTFS)具体的操作过程也是不同的。每种文件系统定义了自己的操作集合。 3.引入 cache 层的目的是为了提高 linux 操作系统对磁盘访问的性能。 Cache 层在内存中缓存了磁盘上的部分数据。当数据的请求到达时,如果在 cache 中存在该数据且是最新的,则直接将数据传递给用户程序,免除了对底层磁盘的操作,提高了性能。 4.通用块层:接收上层发出的磁盘请求,并最终发出 IO 请求。该层隐藏了底层硬件块设备的特性,为块设备提供了一个通用的抽象视图。 5. IO 调度层:接收通用块层发出的 IO 请求,缓存请求并试图合并相邻的请求(如果这两个请求的数据在磁盘上是相邻的)。并根据设置好的调度算法,回调驱动层提供的请求处理函数,以处理具体的 IO 请求。 6.驱动层:驱动程序对应具体的物理块设备,它从上层中取出 IO 请求,并根据该 IO 请求中指定的信息,通过向具体块设备的设备控制器发送命令的方式,来操纵设备传输数据。 7.设备层是具体的物理设备。定义了操作具体设备的规范。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值