作者: Wenbo

  • 实验 1:程序编写与调试

    一、C程序的编写过程

    (一)开发环境

    需借助编译环境将C语言(高级语言)翻译为机器语言,常用工具包括:

    • Visual C++
    • Vs2010
    • Code::Blocks

    (二)核心步骤(编辑→编译→连接→执行)

    步骤 核心操作 输出文件 文件后缀 关键说明
    编辑程序 用编辑器编写代码,保存为源文件 源程序 .c 源文件是存放汇编或高级语言代码的文件,需遵循C语言基础语法框架
    编译程序 编译器检查语法错误,将源程序翻译为机器指令 目标程序 .obj 若语法错误(如缺少分号、关键字错误),编译会失败并提示错误位置
    连接程序 将目标文件与标准库函数(如printf所在库)打包组装 可执行程序 .exe 连接成功后生成计算机可直接运行的文件,连接失败可能因库函数引用错误
    执行程序 运行可执行文件 运行结果 查看程序是否实现预期功能,若结果异常需排查逻辑或运行时错误

    (三)示例任务

    编写程序在屏幕输出两行内容:

    1. “我是中国人,我爱中国!”
    2. “I am Chinese. I love China!”

    二、Hello World类程序编写(基础输出程序)

    (一)核心代码框架

    #include <stdio.h>  // 引用标准输入输出库,用于printf函数
    int main(void)      // 主函数,程序入口
    {
        // 输出指定内容,\n表示换行
        printf("我是中国人,我爱中国!\n");
        printf("I am Chinese. I love China!\n");
        return 0;       // 主函数返回0,标识程序正常结束
    }
    

    (二)提交要求

    • 主观题形式,需将编写的程序拍照上传,确保代码清晰、无语法错误

    三、C程序的错误类型

    (一)语法错误(编译阶段报错)

    • 定义:违反C语言语法规则,如缺少分号、括号不匹配、变量未声明等。
    • 示例代码
      #include <stdio.h>
      int main(void)
      {
          int a,b,sum; 
          a=123; 
          b=456 sum=a+b;  // 错误:b=456后缺少分号
          printf(sum);    // 错误:printf格式错误,缺少引号和格式符
          return 0;
      }
      
    • 特征:编译时会提示具体错误位置(如“error C2146: 语法错误: 缺少‘;’”),程序无法生成目标文件。

    (二)逻辑错误(编译通过,结果异常)

    • 定义:语法无错,程序能正常执行,但结果不符合预期,多因算法或逻辑设计错误。
    • 示例代码
      #include <stdio.h>
      int main(void)
      {
          int a,b,c;
          scanf("%d%d",a,&b);  // 错误:scanf第一个参数应为&a(取地址)
          c=a/b;
          printf("sum is %d\n",c);  // 错误:变量c是除法结果,却标注为sum
          return 0;
      }
      
    • 特征:无报错信息,需通过对比预期结果与实际结果排查(如输入6和3,正确结果应为2,若因逻辑错误输出其他值)。

    (三)运行时错误(编译通过,运行崩溃/异常)

    • 定义:语法和逻辑无明显错误,但运行时因资源问题或非法操作(如未初始化变量、数组越界)无法正常执行。
    • 示例代码
      #include <stdio.h>
      int main(void)
      {
          int a,b,c;
          a=3;
          c=b;  // 错误:变量b未初始化,值为随机数
          return 0;
      }
      
    • 特征:运行时弹出错误提示(如“Run-Time Check Failure #3: 变量b未初始化”),程序可能中止或闪退。

    四、C语言调试工具

    (一)基于断点的调试(传统调试方式)

    1. 核心流程

    1. 设置断点:在代码关键位置(如分支、循环处)标记,使程序运行到此处中断,方便观察状态。
      • 示例:在if(x==y+z)行设置断点,查看x与y+z的比较逻辑。
    2. 运行程序:启动调试模式,程序执行到断点处暂停。
    3. 观察变量:通过调试工具查看变量实时值(如局部变量x、y、z的当前数值),判断是否符合预期。
    4. 修改代码:若发现错误(如将x=y+z(赋值)误写为x==y+z(判断)),暂停调试并修正代码,重新运行验证。

    2. 常用操作

    • 单步执行:逐行运行代码,观察每一步变量变化,定位错误位置。
    • 查看内存:复杂程序可查看内存地址中的数据,排查指针或数组相关错误。

    (二)基于大模型的调试(辅助调试方式)

    1. 工具示例

    • 讯飞星火大模型(https://xinghuo.xfyun.cn/botweb/2081730)
    • 功能定位:智能识别代码错误(如语法错误、逻辑漏洞),提供修正建议和解释。

    2. 调试示例

    • 原错误代码(缺少分号):
      #include <stdio.h>
      int main(void)
      {
          int a,b,sum;
          a=123;
          b=456 sum=a+b;  // 缺少分号
          printf("sum is ");
          return 0;
      }
      
    • 大模型修正后代码:
      #include <stdio.h>
      int main(void)
      {
          int a,b,sum;
          a=123;
          b=456;  // 补充分号
          sum=a+b;
          printf("sum is %d\n",sum);  // 补充格式符%d,输出sum值
          return 0;
      }
      

    五、思考题

    1. 程序中的标识符有什么用?(提示:标识变量、函数、数组等的名称,需遵循命名规则,如首字符为字母或下划线)
    2. 整型与浮点型运算后的结果是什么数据类型?由什么决定?(提示:结果为浮点型,由C语言的“隐式类型转换”规则决定,低精度类型向高精度类型转换)
  • 第 2 讲:让计算机学会运算

    一、变量与常量

    (一)变量

    1. 定义:存储数值可改变的量,需指定数据类型,占用固定内存空间(如int型占4字节)。
      • 一般形式:数据类型 变量名称1, 变量名称2, ..., 变量名称n;
      • 示例:int count;(定义存储常服数量的整型变量count)
    2. 初始化:定义时为变量赋予初始值,避免使用未初始化变量(会导致运行错误)。
      • 一般形式:数据类型 变量名称 = 初始值;
      • 示例:
        • float cj = 90;(定义浮点型变量cj,初始值90.0)
        • int x = 1, y, z;(x初始值1,y、z未初始化,值为随机数)

    (二)常量

    1. 分类及定义
      类型 说明 示例 注意事项
      整型常量 整数,默认int型存储 sum = sum + 357 可指定类型/进制:<br>- 92LL(long long型)、92U(无符号整型)<br>- 07(八进制)、0X1F(十六进制)
      浮点型常量 小数或指数形式,默认double型 十进制小数:0.123123.0<br>指数形式:1.2e-27E0 可指定类型:<br>- 3.14F(float型)、3.14L(long double型)<br>- 十进制小数必须含小数点,指数形式e前后需有数
      字符常量 单撇号括起的1个字符,值为ASCII码 普通字符:'a'(97)、'0'(48)<br>转义字符:'\n'(换行,10)、'\x62'(‘b’) 不可用'ab'表示2个字符,需分开写'a''b'
      字符串常量 双撇号括起的字符序列,末尾自动加'\0'作为结束标志 "China"(内存存储:C h i n a \0)、"中国" 与字符常量区别:'a'占1字节,"a"占2字节(含'\0'
      符号常量 用标识符表示常量,需用#define定义 #define PI 3.14(PI代表3.14) 定义后不可修改,通常大写,增强代码可读性

    二、指针变量

    (一)核心概念

    指针变量存储的是其他变量的内存地址,通过地址可间接访问目标变量,类比“通过房间号找房间内物品”。

    (二)定义与初始化

    1. 定义:需指定基类型(与目标变量类型一致),*表示指针类型。
      • 一般形式:数据类型 *变量名称;
      • 示例:
        • float *p3;(定义指向float型变量的指针p3)
        • double *p4, *p5;(定义2个指向double型变量的指针)
        • 注意:double *p1, p2;中p2是普通double变量,非指针
    2. 初始化:初始值为已定义变量的地址(&取地址运算符)或空指针(0)。
      • 一般形式:数据类型 *变量名称 = 初始值;
      • 示例:
        • char a, *p1 = &a;(p1存储变量a的地址,指向a)
        • int *p2 = 0;(p2为空指针,不指向任何变量)

    (三)变量访问方式

    访问方式 说明 示例
    直接访问 通过变量名访问 short cj = 92;(直接给cj赋值92)
    间接访问 通过指针变量访问(*指针运算符,表“指向的变量”) *p1 = 90;(通过p1修改其指向的变量a的值为90)

    三、运算符和表达式

    (一)运算符分类及规则

    1. 核心运算符汇总

      类别 运算符 含义 优先级 结合性 示例 结果
      算术运算符 +(单目) 正号 右结合 +5 5
      -(单目) 负号 右结合 -5 -5
      ++ 自增 右结合 i=5; ++i 6
      -- 自减 右结合 i=5; --i 4
      * 乘法 左结合 5*3 15
      / 除法 左结合 5/3(整型)、5/3.0(浮点型) 1、1.666…
      % 取余 左结合 5%3 2
      +(双目) 加法 中低 左结合 5+3 8
      -(双目) 减法 中低 左结合 5-3 2
      关系运算符 <<=>>= 比较大小 左结合 5>2 1(真)
      == 等于 左结合 5==2 0(假)
      != 不等于 左结合 5!=2 1(真)
      逻辑运算符 ! 逻辑非 右结合 !0 1(真)
      && 逻辑与 左结合 1&&0 0(假)
      ` ` 逻辑或 左结合
      赋值运算符 = 赋值 最低 右结合 a = 5 将5赋给a
    2. 表达式计算规则

      • 先按优先级执行(如先乘除后加减,先逻辑非后逻辑与/或);
      • 优先级相同时,按结合性执行(如算术运算符左结合,单目运算符右结合);
      • 不可省略乘号(如a*b不可写ab),可加小括号强制改变顺序(如(a+b)*c)。

    (二)特殊情形

    1. 短路运算:逻辑表达式确定最终值后,后续分量不再计算。
      • 示例:a=0, b=10时,c=(a>=1 && (b=5))中,a>=1为假,直接确定结果为假,b=5不执行,最终b=10
    2. 数据类型转换
      • 自动转换:赋值时低精度→高精度(如char→short→int→long long),可能丢失数据(如char a=127; a=a+1;后a=-128,溢出);
      • 强制转换:用(目标类型)强制转换,优先级最高。
      • 示例:(char)12.5(将12.5转为char型12)、(int)x + y(先转x为int型,再与y相加)。

    四、处理简单问题(程序编写)

    (一)基本步骤

    1. 编写main()函数(程序入口);
    2. 定义与初始化变量;
    3. 输入数据(如scanf);
    4. 编写算法语句(核心逻辑);
    5. 输出结果(如printf)。

    (二)示例

    1. 华氏温度转摄氏温度
      • 公式:c = 5.0/9 * (f - 32)(用5.0避免整型除法);
      • 代码:
      #include <stdio.h>
      int main() {
          float c, f = 64;  // 初始化华氏温度f=64
          c = 5.0/9 * (f - 32);  // 计算摄氏温度
          printf("摄氏温度: %.1f\n", c);  // 输出结果(如17.8)
          return 0;
      }
      
    2. 三角形面积计算(海伦公式)
      • 公式:p=(a+b+c)/2s=sqrt(p*(p-a)*(p-b)*(p-c))(需包含math.h);
      • 代码:
      #include <stdio.h>
      #include <math.h>  // 调用sqrt函数需包含
      int main() {
          float a=6, b=7, c=8, p, s;  // 初始化三边长
          p = (a + b + c) / 2;  // 计算半周长
          s = sqrt(p * (p - a) * (p - b) * (p - c));  // 计算面积
          printf("三角形面积: %.2f\n", s);  // 输出结果(如20.33)
          return 0;
      }
      
    3. 大写字母转小写字母
      • 原理:小写字母ASCII码 = 大写字母ASCII码 + 32;
      • 代码:
      #include <stdio.h>
      int main() {
          char u_l = 'B';  // 定义大写字母变量
          u_l = u_l + 32;  // 转为小写('B'+32='b')
          printf("小写字母: %c\n", u_l);  // 输出'b'
          return 0;
      }
      

    五、重点与难点

    1. 重点
      • 变量的定义、初始化与使用;
      • 常量(尤其是符号常量、转义字符)的定义与使用;
      • 算术、关系、逻辑运算符的优先级与表达式计算。
    2. 难点
      • 指针变量的定义、初始化及间接访问;
      • 数据类型自动转换的溢出问题与强制转换的正确使用。

    六、思考题

    1. 符号常量与其他常量(整型、浮点型等)的区别:符号常量用标识符表示,无类型;其他常量有明确类型。符号常量与变量的区别:符号常量定义后不可修改,变量值可改变。
    2. 程序运行结果错误的排查方法:检查变量是否初始化、数据类型是否匹配、运算符优先级是否正确、公式逻辑是否有误、是否存在数据溢出等。
  • 第 1 讲:程序设计基本概念

    一、人类的助手:计算机核心概念

    1. 程序与指令

    • 指令:计算机可直接执行、不可再分割的命令,是计算机操作的最小单位。
    • 程序:一组计算机能够识别和执行的指令集合,用于完成特定任务。
    • 程序设计(编程):将人类解决问题的思路转化为程序,进而转换为计算机可执行指令的过程。

    二、与计算机对话:计算机语言体系

    计算机语言按抽象程度分为三级,核心作用是实现“人类意图→计算机执行”的转换。

    1. 机器语言(最低级)

    • 本质:二进制代码(0和1)组成的机器指令集合,是计算机唯一能直接理解和执行的语言。
    • 结构:每条指令包含“操作码”(指定操作类型,如存储、加法)和“操作数”(指定操作对象,如寄存器地址、数值)。
    • 示例
      • 存储指令:1 001 10(将数据存入地址为10的寄存器)
      • 加法指令:2 002 10 00000010(将十进制2与寄存器10中的数相加并存储)
    • 缺点:可读性极差,难以记忆和编写,依赖具体硬件。

    2. 汇编语言(低级)

    • 本质:用符号(如MOV、ADD)替代二进制指令的“符号语言”,仍依赖特定硬件架构。

    • 优势:相比机器语言更易理解,降低编程复杂度。

    • 示例:“1+2”的汇编实现

      指令序号 操作码 操作数1 操作数2 指令含义
      1 MOV A 将十进制“1”存入寄存器A
      2 ADD A 2 十进制“2”与寄存器A中的数相加,结果存回A
    • 局限性:仍需了解硬件细节,未完全脱离机器依赖。

    3. 高级语言(最高级)

    • 核心特点:独立于特定计算机系统,语法接近人类自然语言,可读性和通用性强。
    • 执行流程:需通过“编译器”将高级语言编写的源程序(如.c文件)转换为目标程序(如.obj文件),再经“链接程序”生成可执行程序(如.exe文件)。
    • 主流语言:根据IEEE Spectrum 2023排行榜,热门语言包括Python、C++、C、Java等。

    4. 重点:C语言

    • 发展背景:20世纪70年代由美国贝尔实验室的D.M.Ritchie设计,用于开发UNIX系统。

    • 语言结构:类比人类语言的层级关系,形成清晰的语法体系

      类别 结构
      人类语言 字 → 词 → 句子 → 段落 → 文章
      C语言 标识符 → 表达式 → 语句 → 函数 → 程序
    • 基础示例:输出“I love China!”的C程序

      #include <stdio.h>  // 引入标准输入输出库
      int main() {         // 主函数,程序入口(C程序必须有且仅有一个main函数)
          printf("I love China!");  // 输出语句
          return 0;        // 主函数返回值,标识程序正常结束
      }
      

    (1)C语言核心组成单元

    • 标识符:用于命名变量、函数等的符号,规则如下:

      • 由英文字母(A-Z、a-z)、数字(0-9)、下划线(_)组成;
      • 不能以数字开头;
      • 区分大小写(如Word3word3是不同标识符);
      • 不能与“关键字”重名。
    • 关键字:C语言预定义的特殊标识符,具有固定含义,不可自定义

      常用关键字 功能说明
      int、char、double 数据类型声明
      if、else、while、for 流程控制
      return、break、continue 程序跳转
      void、static、const 存储类型/修饰符
    • 表达式:用运算符连接运算对象的式子,用于计算或判断

      运算符类型 符号示例 功能说明
      算术运算符 +、-、*、/、%、++ 加减乘除、取余、自增
      关系运算符 >、<、==、!=、>=、<= 比较大小关系
      逻辑运算符 !(非)、&&(与)、
      赋值运算符 =、+=、-=、*= 变量赋值及扩展赋值
      其他 sizeof(求字节数)、(类型)(强制转换) 数据操作辅助
    • 语句:C语言的基本执行单位,一条语句对应一个或多个机器指令,如:

      • 赋值语句:sum = 1 + 2;
      • 输出语句:printf("Hello");
      • 分支语句:if (sunny == 1) fly_kite = 1; else stay_home = 1;
    • 函数:C程序的基本功能单位,实现代码模块化,示例:两数交换函数

      #include <stdio.h>
      // 自定义函数swap:通过指针交换两个整数的值
      void swap(int *a, int *b) {
          int temp = *a;  // 临时变量存储*a的值
          *a = *b;        // 将*b的值赋给*a
          *b = temp;      // 将临时变量的值赋给*b
      }
      int main() {
          int num1 = 2, num2 = 3;
          swap(&num1, &num2);  // 调用swap函数,传入变量地址
          printf("交换后的两个数: %d %d", num1, num2);  // 输出结果:3 2
          return 0;
      }
      

    三、从问题到程序:程序设计完整流程

    程序设计需遵循标准化步骤,确保逻辑清晰、可维护性强。

    1. 核心步骤

    1. 分析问题:明确问题需求(如“计算1到100的和”“找出三个数中的最大值”),确定输入、输出和处理逻辑。

    2. 设计算法

      • 算法定义:解决问题的具体方法和步骤,需满足“有穷性”“确定性”“可行性”。
      • 表示方法
        • 自然语言:如“计算1+2+…+100”的步骤:
          1. 令sum=0(累加结果)、augend=1(累加项);
          2. sum = sum + augend;
          3. augend = augend + 1;
          4. 若augend ≤ 100,跳转至步骤2;否则执行步骤5;
          5. 输出sum的值。
        • 流程图:用图形符号表示算法,常用符号包括
          • 开始/结束框(椭圆形)、执行框(矩形)、选择框(菱形)、输入输出框(平行四边形)、流程线(箭头)。
      • 经典结构:顺序结构(按步骤执行)、选择结构(if-else,根据条件分支)、循环结构(while/for,重复执行)。
    3. 编写程序

      • 按算法逻辑,用选定的高级语言(如C语言)编写源程序;
      • 注意语法规范(如语句结尾加;、括号配对)。
    4. 测试程序

      • 编译:检查语法错误,生成目标程序;
      • 运行:测试功能正确性(如输入边界值、异常值),修复逻辑错误。
    5. 编写文档:记录程序关键信息,便于维护和使用,文档内容示例

      文档明细 具体内容 备注
      程序文件名称 FindTallestMan.c 源文件
      程序功能描述 找出三个数中最大的数及位置
      输入数据格式 小数,小数,小数 示例:1.9,1.8,1.7
      输出数据格式 身高最高的是第X人,他的身高是Y米 X、Y由程序计算输出

    四、让计算机认识世界:数据表示方式

    计算机仅能识别数字,需将各类信息(整数、小数、字符)转换为二进制形式存储。

    1. 整数表示

    • 存储单位:字节(1字节=8位二进制),字节有唯一地址(内存地址)。

    • 表示方法

      • 无符号整数:仅表示非负数,1字节范围为0~255(2⁸-1)。
      • 有符号整数:用最高位(符号位)表示正负(0为正,1为负),采用补码存储(解决“+0”与“-0”重复问题):
        • 正整数:补码=原码(二进制本身);
        • 负整数:补码=原码(除符号位外)按位取反 + 1。
    • C语言整数类型

      数据类型 字节数 是否有符号 取值范围
      unsigned short 2 0~65535(2¹⁶-1)
      signed short 2 -32768~32767(-2¹⁵~2¹⁵-1)
      unsigned int/long 4 0~4294967295(2³²-1)
      signed int/long 4 -2147483648~2147483647(-2³¹~2³¹-1)
      unsigned long long 8 0~18446744073709551615(2⁶⁴-1)
      signed long long 8 -9223372036854775808~9223372036854775807(-2⁶³~2⁶³-1)

    2. 小数表示(浮点数)

    • 特点:位数不固定,采用“指数形式”存储(类似科学计数法),如十进制19.625=二进制10011.101=1.0011101×2⁴。

    • 存储结构(以4字节float为例):1位符号位 + 8位指数位 + 23位尾数位。

    • C语言浮点类型

      数据类型 字节数 有效数位 数值范围(绝对值)
      float 4 6~7位 0 及 1.2×10⁻³⁸~3.4×10³⁸
      double 8 15~16位 0 及 2.3×10⁻³⁰⁸~1.7×10³⁰⁸
      long double 16 18~19位 0 及 3.4×10⁻⁴⁹³²~1.1×10⁴⁹³²
    • 注意:浮点数存在精度误差(如0.1无法用二进制精确表示),需避免直接用“==”比较。

    3. 字符表示

    • 编码标准

      • 英文字符/数字:采用ASCII码(1字节),如’A’=65(十进制)=1000001(二进制),‘a’=97,‘0’=48。
      • 中文字符:采用GB2312编码(2字节),解决ASCII码无法表示中文的问题。
    • C语言字符类型

      类型 字节数 取值范围 说明
      char(有符号) 1 -128~127 存储ASCII码或窄字符
      unsigned char(无符号) 1 0~255 存储扩展ASCII码
    • 表示方式:字符常量需用单引号包裹,如'A'(字符)与A(标识符)、"A"(字符串)区分。

    五、思考题

    • 如何区分十进制数与八进制(以0开头,如012=10十进制)、十六进制数(以0x开头,如0xA=10十进制)?
    • 为什么字符需要用单引号引起来?(区分字符常量与标识符、字符串)