【重拾C语言】五、模块化程序设计——函数(定义、调用、参数传递、结果返回、函数原型;典例:打印字符图形、验证哥德巴赫猜想)

目录

前言

五、模块化程序设计——函数

5.1 计算三角形的重心

5.2 函数

5.2.1 函数定义

5.2.2 函数调用

a. 函数调用的形式和过程

b. 参数传递

值传递

指针传递

c. 函数结果返回

5.2.3 函数原型(先调用后定义)

5.3 程序设计实例

5.3.1 打印字符图形

5.3.2 哥德巴赫猜想

5.4  程序调试


        

前言

        本文介绍了模块化程序设计——函数,其中包括如何定义函数、函数的调用形式和过程、参数传递(值传递和指针传递)、函数结果的返回以及函数原型的使用。具体的程序设计实例有打印字符图形和验证哥德巴赫猜想。

五、模块化程序设计——函数

        在C语言中,我们可以使用函数实现模块化程序设计,将一些独立功能的部分写成单独的函数,使得程序更加结构化和清晰。

5.1 计算三角形的重心

        我们可以根据给定的三角形顶点坐标(x1, y1)、(x2, y2)和(x3, y3)来计算三角形的重心。重心G的坐标计算公式如下:

G_{x} = (x_{1} + x_{2} + x_{3} ) / 3

G_{y} = (y_{1} + y_{2} + y_{3} ) / 3

        以下是使用C语言实现的函数:

#include <stdio.h>void centroid(float x1, float y1, float x2, float y2, float x3, float y3, float *Gx, float *Gy) {*Gx = (x1 + x2 + x3) / 3;*Gy = (y1 + y2 + y3) / 3;
}int main() {float x1, y1, x2, y2, x3, y3, Gx, Gy;scanf("%f%f%f%f%f%f", &x1, &y1, &x2, &y2, &x3, &y3);centroid(x1, y1, x2, y2, x3, y3, &Gx, &Gy);printf("Centroid of the triangle is: (%.2f, %.2f)\n", Gx, Gy);return 0;
}

        (关于指针的使用详见本系列后文)

5.2 函数

5.2.1 函数定义

        函数定义包括返回值类型、函数名、参数列表以及函数体。

类型符 函数名(形式参数表) {函数体
}

        其中,返回类型符指定了函数返回的数据类型,可以是基本数据类型(如int、char、float等)或自定义的数据类型。函数名是函数的标识符,用于在程序中调用该函数。参数列表是一组用逗号分隔的参数,可以包含零个或多个参数,每个参数包括参数类型和参数名。函数体是函数的具体实现代码,包括一系列语句和操作。以上面 centroid 函数为例:

        函数的目的是计算一个三角形的质心坐标。它接受6个输入参数,分别是三角形的3个顶点的x和y坐标(x1, y1, x2, y2, x3, y3),以及两个指针变量(float *Gxfloat *Gy),用于存储计算得到的质心的x和y坐标。

        在函数体中,通过将三个顶点的x坐标相加并除以3,将结果存储在*Gx指向的内存位置中,表示质心的x坐标。同样,将三个顶点的y坐标相加并除以3,将结果存储在*Gy指向的内存位置中,表示质心的y坐标。

        请注意,在C语言中,函数的声明和定义可以分开进行,即可以在程序的开头声明函数的原型(函数名、参数列表和返回类型),然后在后面的位置实现函数的定义。这种分离的方式可以提供更好的代码组织和模块化。

(详见5.2.3 函数原型)

5.2.2 函数调用

函数名(实际参数表)

        函数调用是在主函数或其他函数中使用已定义的函数。通过函数名和实际参数列表来调用函数。例如,在 main 函数中,我们调用了 centroid 函数并传入了6个实际参数和2个用于存储结果的指针。

  • 定义一个函数后,就可以在程序中调用这个函数:
    • 标准库函数:在程序的最前面用#include命令包含相应的头文件。
    • 自定义函数:程序中必须有相对应的函数定义。
a. 函数调用的形式和过程

        在C语言中,函数调用通过函数名和实际参数列表的形式进行。函数调用的一般形式是:

函数名(参数1, 参数2, ...);

        其中,函数名是要调用的函数的名称,参数是传递给函数的输入值。

函数调用的过程如下:

  • 程序执行到函数调用的位置时,会跳转到被调用函数的起始位置。
  • 在被调用函数中,执行函数体中的语句,处理传递进来的参数。
  • 如果函数有返回值,计算并返回结果。
  • 执行完函数体中的语句后,返回到函数调用的下一条语句,继续执行。

b. 参数传递

        在C语言中,函数参数可以通过值传递(传递参数的副本)或指针传递(传递参数的地址)的方式进行传递。

  • 值传递
    • 当使用值传递方式传递参数时,函数内部对参数的修改不会影响到函数外部的变量。即函数内部操作的是参数的副本。
  • 指针传递
    • 当使用指针传递方式传递参数时,函数内部可以通过指针来访问和修改函数外部的变量。通过传递变量的地址,函数可以直接对原始变量进行操作。

c. 函数结果返回
  • 函数可以有返回值,也可以没有返回值。函数的返回值通过 return 语句来指定。
  • 函数的返回值可以是任意基本类型(如整数、浮点数等),也可以是指针类型或结构体类型。
  • 在函数中使用 return 语句将结果返回给调用函数。返回值可以直接返回,也可以存储在变量中后再返回。

例如,以下是一个函数的示例,它计算两个整数的和并返回结果:

int add(int a, int b) {int sum = a + b;return sum;
}

在调用该函数时,可以将返回值赋给一个变量:

int result = add(3, 5);

        在这个例子中,函数 add 接收两个整数参数 a 和 b,计算它们的和并将结果返回。函数调用 add(3, 5) 的结果为 8,然后将返回值 8 赋给变量 result

5.2.3 函数原型(先调用后定义)

        函数原型是函数定义的简化形式,用于告诉编译器函数的信息,包括函数的返回值类型、函数名和参数列表(包括参数类型和参数名)。函数原型的目的是在函数调用之前提供函数的声明,让编译器知道函数的存在及其参数和返回值的类型

        在C语言中,函数原型的语法形式为:

返回值类型 函数名(参数列表);

        例如,对于之前提到的 centroid 函数,可以编写函数原型如下:

void centroid(float x1, float y1, float x2, float y2, float x3, float y3, float *Gx, float *Gy);

        通过提供函数原型,我们可以在主函数之前声明函数,使得编译器能够正确地解析函数调用,并检查函数调用的参数类型和返回值类型的匹配性。这提高了程序的可读性和可维护性。在本例5.1中,函数原型可以省略,因为我们把 centroid 函数放在 main 函数的前面

        在程序的开头声明函数的原型:

#include <stdio.h>void centroid(float x1, float y1, float x2, float y2, float x3, float y3, float *Gx, float *Gy);int main() {float x1, y1, x2, y2, x3, y3, Gx, Gy;scanf("%f%f%f%f%f%f", &x1, &y1, &x2, &y2, &x3, &y3);centroid(x1, y1, x2, y2, x3, y3, &Gx, &Gy);printf("Centroid of the triangle is: (%.2f, %.2f)\n", Gx, Gy);return 0;
}void centroid(float x1, float y1, float x2, float y2, float x3, float y3, float *Gx, float *Gy) {*Gx = (x1 + x2 + x3) / 3;*Gy = (y1 + y2 + y3) / 3;
}

5.3 程序设计实例

5.3.1 打印字符图形

#include <stdio.h>void printCharacterPattern(int n) {int i, j, space;// 打印上半部分for (i = 1; i <= n; i++) {// 打印空格for (space = 1; space <= n - i; space++) {printf("  ");}// 打印字母for (j = 1; j <= (2 * i) - 1; j++) {printf("%c ", 'A' + i - 1);}printf("\n");}// 打印下半部分for (i = n - 1; i >= 1; i--) {// 打印空格for (space = 1; space <= n - i; space++) {printf("  ");}// 打印字母for (j = 1; j <= (2 * i) - 1; j++) {printf("%c ", 'A' + i - 1);}printf("\n");}
}int main() {int n;printf("Enter the number of lines: ");scanf("%d", &n);printf("\n");printCharacterPattern(n);return 0;
}

5.3.2 哥德巴赫猜想

        哥德巴赫猜想:任意一个大于2的偶数都可以表示成两个素数之和。我们可以编写一个函数,找到两个素数,使它们的和等于一个给定的偶数。

#include <stdio.h>int isPrime(int number) {int i;if (number <= 1) {return 0;}for (i = 2; i <= number / 2; i++) {if (number % i == 0) {return 0;}}return 1;
}void verifyGoldbachConjecture(int n) {int i, flag = 0;if (n % 2 != 0 || n <= 2) {printf("Invalid input! Please enter an even number greater than 2.\n");return;}for (i = 2; i <= n / 2; i++) {if (isPrime(i) && isPrime(n - i)) {printf("%d = %d + %d\n", n, i, n - i);flag = 1;}}if (flag == 0) {printf("The Goldbach conjecture is not verified for the number %d.\n", n);}
}int main() {int n;printf("Enter an even number greater than 2: ");scanf("%d", &n);verifyGoldbachConjecture(n);return 0;
}
  • 在上面的代码中,定义了两个函数:isPrimeverifyGoldbachConjecture
    • isPrime函数用于检查一个数是否是素数;
    • verifyGoldbachConjecture函数用于验证哥德巴赫猜想。
      • 首先检查输入是否为一个大于2的偶数,然后通过遍历所有可能的素数对来验证猜想。如果找到满足猜想的素数对,则打印出相应的表示;如果找不到满足猜想的素数对,则输出相应的提示信息。

5.4  程序调试

ChatGPT:

        程序调试是指对程序进行测试和排除错误的过程。在程序开发过程中,经常会出现各种错误,比如语法错误、逻辑错误、运行时错误等。调试的目标是找出程序中存在的错误并修复它们,确保程序能够按照预期的方式运行。

下面是一些常见的程序调试技术和方法:

  1. 打印调试信息:通过在关键位置插入打印语句,输出变量的值或程序执行到达的位置,以便观察程序的执行过程和状态,从而找出问题所在。

  2. 使用调试器:调试器是一种工具,可以用来逐步执行程序、观察变量的值、检查内存和寄存器的状态,以及跟踪程序的执行流程。通过调试器,可以更深入地分析程序的运行情况和定位错误。

  3. 单元测试:编写针对程序中单个函数或模块的测试用例,验证其是否按照预期工作。通过逐个测试函数,可以逐步排查错误并验证程序的正确性。

  4. 边界值测试:针对程序处理数据的边界情况进行测试,包括最大值、最小值、边界条件等。边界值测试可以揭示一些潜在的问题,如数组越界、整数溢出等。

  5. 追踪错误:对于运行时错误,可以使用追踪技术来定位错误发生的位置。可以通过观察错误信息、栈跟踪和日志等来追踪错误的来源,进而修复问题。

  6. 代码审查:请同事或其他开发人员对代码进行审查,有时候他们能够发现你忽略的问题或提出改进的建议。

        在进行程序调试时,建议采用自底向上的方法,逐步调试和测试程序的不同部分,确保每个部分的正确性,最后再整体进行测试。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/95200.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C/S架构学习之TCP的三次握手和四次挥手

TCP的三次握手&#xff1a;一定由客户端主动发起的&#xff0c;发生在建立连接的过程中。此过程发生在客户端的connect()函数和服务器的accept()函数之间。第一次握手&#xff1a;客户端向服务器发送一个带有SYN标志的数据包&#xff0c;表示客户端请求建立连接。并且客户端会选…

3D孪生场景搭建:模型区域摆放

前面介绍完了NSDT场景编辑器的线性绘制和阵列绘制&#xff0c;本章将讲述下编辑器的另一种绘制方式&#xff1a;区域绘制。 1、区域绘制功能简介 在场景中绘制资产时&#xff0c;除使用上述两个的方式外&#xff0c;NSDT 编辑器还支持使用区域绘制的方式进行绘制。先选取需要…

python修改unittestreport中的用例条数

背景: 自动化框架中使用yaml文件作为数据配置&#xff0c;使用ddt作为数据驱动来运行测试用例&#xff0c;由于测试用例都是基于场景去编写&#xff0c;目前都是一个测试类算是一条测试用例&#xff0c;但基于测试报告里面一个类运行的测试方法有多个&#xff0c;因此统计的测试…

计算机毕业设计 基于SpringBoot的图书馆管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

香蕉叶病害数据集

1.数据集 第一个文件夹为数据增强&#xff08;旋转平移裁剪等操作&#xff09;后的数据集 第二个文件夹为原始数据集 2.原始数据集 Cordana文件夹&#xff08;162张照片&#xff09; healthy文件夹&#xff08;129张&#xff09; Pestalotiopsis文件夹&#xff08;173张照片&…

【Java 进阶篇】JDBC 数据库连接池 C3P0 详解

数据库连接池是数据库编程中常用的一种技术&#xff0c;它可以有效地管理数据库连接&#xff0c;提高数据库访问的性能和效率。在 Java 编程中&#xff0c;有多种数据库连接池可供选择&#xff0c;其中之一就是 C3P0。本文将详细介绍 C3P0 数据库连接池的使用&#xff0c;包括原…

Linux CentOS7 vim重复行

在用vim编辑处理文件时&#xff0c;会有重复行。有的是情境需要&#xff0c;有的可能是误操作而形成。对于正常形成的重复行&#xff0c;我们不作讨论&#xff0c;我们仅讨论什么情况下会出现重复行&#xff0c;如何避免&#xff0c;如何处理。 在文件中的单行或多个连续空白行…

【Unity】3D贪吃蛇游戏制作/WebGL本地测试及项目部署

本文是Unity3D贪吃蛇游戏从制作到部署的相关细节 项目开源代码&#xff1a;https://github.com/zstar1003/3D_Snake 试玩链接&#xff1a;http://xdxsb.top/Snake_Game_3D 效果预览&#xff1a; 试玩链接中的内容会和该效果图略有不同&#xff0c;后面会详细说明。 游戏规则 …

【C语言】内存函数的详细教学和模拟实现

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是gugugu。希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f194;本文由 gugugu 原创 CSDN首发&#x1f412; 如需转载还请通知⚠…

互联网Java工程师面试题·Dubbo篇·第一弹

目录 1、为什么要用 Dubbo&#xff1f; 2、Dubbo 的整体架构设计有哪些分层? 3、默认使用的是什么通信框架&#xff0c;还有别的选择吗? 4、服务调用是阻塞的吗&#xff1f; 5、一般使用什么注册中心&#xff1f;还有别的选择吗&#xff1f; 6、默认使用什么序列化框架&…

学习记忆——宫殿篇——记忆宫殿——记忆桩——卧室——莫兰勋爵在地铁走失的案子

《神探夏洛克》第三季第一集中提到“思维殿堂”&#xff0c;其实指的就是记忆宫殿。讲述了一个名叫莫兰勋爵在地铁走失的案子&#xff0c;这里简单给大家罗列以下破案信息&#xff1a; 订阅报纸的男人、伦敦养狗的女人、穿着黑色运动的非裔女人、松木、云杉、雪松、新樟脑球、碳…

AtCoder Beginner Contest 232(A-G)

A - QQ solver (atcoder.jp)直接按题意模拟即可。 B - Caesar Cipher (atcoder.jp)按题意模拟即可 C - Graph Isomorphism (atcoder.jp)按题意模拟即可 D - Weak Takahashi (atcoder.jp) 一个非常套路的网格dp E - Rook Path (atcoder.jp) &#xff08;1&#xff09;题意 有…

探秘前后端开发世界:猫头虎带你穿梭编程的繁忙街区,解锁全栈之路

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

【Java】接口 interface

目录 概述 示例代码&#xff1a; 接口成员访问特点 示例代码&#xff1a; 概述 什么是接口 接口就是一种公共的规范标准&#xff0c;只要符合规范标准&#xff0c;大家都可以调用。 Java 中的接口更多的体现在对行为的抽象&#xff01; 1. 接口 用关键字 interface 修饰 pub…

从零手搓一个【消息队列】创建核心类, 数据库设计与实现

文章目录 一、创建核心类1, 交换机2, 交换机类型3, 队列4, 绑定5, 交换机转发 & 绑定规则6, 消息7, 消息属性 二、数据库设计1, 使用 SQLite2, 使用 MyBatis2.1, 创建 Interface2.2, 创建 xml 文件 三、硬盘管理 -- 数据库1, 创建 DataBaseManager 类2, init() 初始化数据库…

算法题系列10·最长公共前缀

目录 题目描述 思路 实现 题目描述 编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀&#xff0c;返回空字符串 ""。示例 1&#xff1a; 输入&#xff1a;strs ["flower","flow","flight"] 输出&#xff1a;&qu…

LabVIEW开发教学实验室自动化INL和DNL测试系统

LabVIEW开发教学实验室自动化INL和DNL测试系统 如今&#xff0c;几乎所有的测量仪器都是基于微处理器的设备。模拟输入量在进行数字处理之前被转换为数字量。对于参加电气和电子测量课程的学生来说&#xff0c;了解ADC以及如何欣赏其性能至关重要。ADC的不确定性可以根据其传输…

蓝桥杯每日一题2023.10.5

3420. 括号序列 - AcWing题库 题目描述 题目分析 对于这一我们需要有前缀知识完全背包 完全背包的朴素写法&#xff1a; #include<bits/stdc.h> using namespace std; const int N 1010; int n, m, v[N], w[N], f[N][N]; int main() {cin >> n >> m;fo…

PyTorch实例:简单线性回归的训练和反向传播解析

文章目录 &#x1f966;引言&#x1f966;什么是反向传播&#xff1f;&#x1f966;反向传播的实现&#xff08;代码&#xff09;&#x1f966;反向传播在深度学习中的应用&#x1f966;链式求导法则&#x1f966;总结 &#x1f966;引言 在神经网络中&#xff0c;反向传播算法…

华为OD七日集训第6期 十一特辑 - 按算法分类,由易到难,循序渐进,玩转OD

目录 专栏导读华为OD机试算法题太多了&#xff0c;知识点繁杂&#xff0c;如何刷题更有效率呢&#xff1f; 一、逻辑分析二、数据结构1、线性表① 数组② 双指针 2、map与list3、优先队列4、滑动窗口5、二叉树6、并查集7、栈 三、算法1、基础算法① 贪心算法② 二分查找③ 分治…