本笔记记录自 Coursera课程 《计算机程式设计》 台湾大学 刘邦锋老师

Week4 Functions

4-1 System Function

函数主要分为两大类系统定义函数使用者定义函数,例如printf和main。

例子:(sys-function.c)呼叫系统定义函数

#include <stdio.h> /* for printf and scanf */
#include <stdlib.h> /* for abs */
#include <math> /* for sin */
main()
{
int i, j;
double x, y;
scanf("%d", &i);
j = abs(i);
printf("%d\n", j);
scanf("%lf", &x);
y = sin(x);
printf("%f\n", y);
}

需要使用的系统定义函数,可以在网络上查找到它存在于哪个库中,方便调用。比如说课程中提到的这个网址

  • 函数名称,参数,及返回值合称为函数的原型
  • 函数的原型就好像是函数的使用说明书,详细记载函数应该如何使用。
  • 系统函数的原型都是定义在对应的标头档(类似python的库)内。

3 4-2 System Function Return Value

例子:(scanf-count.c)借由scanf的返回值掌握资料个数

#include <stdio.h>

int main()
{
int sum = 0;
int count = 0;
int i; while (scanf("%d", &i) != EOF){
sum += i;
count++;
}
printf("%d\n", sum / count);
return 0;
}

4-3 User Function Definition

如果定义一个接受一个整数参数i,并返回一个整数的函数myfuntion:

  • 先写返回值的类别int,再写函数的名称myfunction,最后用小括号( )将参数的类别int,及名称i括起来。
  • 此时不只描述函数的原型,也要定义函数如何操作,所以不能像函数原型直接用分号结束,而是要用一对{ }将操作的部分包起来,就像写main主程式一样。
  • 因为我们要返回一个整数,所以我们申明一个整数变量value,并根据参数i计算value,最后使用return命令将value返回。
int myfunction(int i)
{
int value;
...
compute value according to i;
...
return value;
}

例子:返回一个整数的main

#include <stdio.h>
int main(void)
{
return 0;
}
  • main主程式是一个没有参数,担忧一个整数返回值的函数。而且通常我们将返回值设为0.
  • 由于main不需要任何参数,所以main后面的( )中以void来表示。
  • void表示的是没有

例子:(leap-year-function.c)定义一个函数决定闰年

#include <stdio.h>
int leap_year(int y)
{
int is_leap;
is_leap = (y % 400 == 0) || ((y % 4 == 0) && !(y % 100 == 0));
return is_leap;
}
int main(void)
{
int year;
int k;
scanf("%d", &year);
k = leap_year(year);
printf("%d\n", k);
return 0;
}

可以重复使用写好的函数。重复的代码不仅会让程序冗长难以理解,而且很容易在重复撰写时出错。如果使用已经过验证的函数,则可以避免这些麻烦。

4-4 User Function With Return Value

定义一个接受一个整数参数i,但不返回任何值的函数foo:

  • 使用void表示foo并没有任何返回值。void不可省略,否则编译器会假设返回值类别为int。
void foo(int i)
{
...
process according to i;
...
return;
}

例子:(print-digits.c)印出一个数的各位数

#include <stdio.h>
void print_digits(int i)
{
int index = 0;
int digits[20];
if (i < 0)
return;
while (i != 0){
digits[index] = (i % 10);
i /= 10;
index++;
}
for (i = index - 1; i >= 0; i --)
printf("%d\n", digits[i]);
return;
}
int main(void)
{
int i;
scanf("%d", &i);
print_digits(i);
return 0;
}

4-5 Use Function to Simplify Program

其实就是把重复的代码整合在函数里,可以简化代码。

4-6 Printf Scanf for Multiple Variables and Extra Message

函数原型:printf-scanf

int printf(char *format, ...);
int scanf(char *format, ...);
  • 第二个参数非常奇特,是...,意思是参数个数是不固定的。
  • 之前printf及scanf都一次处理一个变量,但是"..."不固定参数个数能让我们同时对多个变量作输出入。

例子:对多个变量作输出输入

printf("%d %p %f %f\n", int, addr, float, double);
scanf("%d%f%lf", &int, &float, &double)

例子:(multi-io-message.c)输出夹杂其他字元

#include <stdio.h>
int main(void)
{
int i;
float f;
double df;
scanf("%d%f%lf", &i, &f ,&df);
printf("int %d adr %p flt %f dbl %f\n",i &i, f, df);
return 0;
}

则如输入

-1 3.2 4.6

输出为

int -1 adr 0x7fff98a1f330 flt 3.200000 dbl 4.600000

4-7 Scanf with Nonspace Char in Format String

就是说scanf也可以夹杂其他字元,但是输入形式一定要与其相对应,不然会读不全。

4-8 Function Parameter Passing

  • 形式参数(formal parameter)就是写在被呼叫方函数的申明部分,所以一定是一个变量的类别。例如j就是test的形式参数。

    void test(int j)
  • 实际参数(actual parameter)是呼叫方实际用以呼叫被呼叫函数的参数。实际参数可以是一个算式,并不一定是一个变量。

    test(i);
    test(3 + 7);

4-9 Funtion Array Parameter Passing

例子:使用函数处理一个数组中的元素

void process_array(int array[], int n)
{
int i;
for (i = 0; i < n; i++)
process element array[i];
return;
}
int main(void)
{
int a[10];
process_array(a,10);
return 0;
}

这里注意形式参数array申明要写成array[]。

4-10 Function Array Parameter Passing with Modification

例子:(partial-inc.c)增加部分阵列元素的值

#include <stdio.h>
void print_array(int array[], int n)
{
int i;
for (i = 0; i < n; i++)
printf("a[%d] = %d\n", i, array[i]);
return;
}
void inc_array(int array[], int n)
{
int i;
printf("inc_array: array = %p\n", array);
for (i = 0; i < n; i++)
array[i]++;
return;
}
int main(void)
{
int i;
int a[5];
for (i = 0; i < 5; i++)
scanf("%d", &(a[i]));
printf("before inc_array\n");
print_array(a, 5);
inc_array(a, 5);
printf("after first inc_array\n");
print_array(a, 5);
inc_array(&(a[1]), 2);
printf("after second inc_array\n");
print_array(a, 5);
inc_array(&(a[2]), 2);
printf("after third inc_array\n");
print_array(a, 5);
return 0;
}
  • 第一次实际参数是(a, 5),所以inc_array中的形式参数array会拿到数组a的起始位址,并将整个数组加1。
  • 第二次实际参数是(&(a[1]), 2),所以inc_array中的形式参数array会拿到元素a[1]的位址,并将a[1]及a[2]加1。
  • 第三次实际参数是(&(a[2]), 2),所以inc_array中的形式参数array会拿到元素a[2]的位址,并将a[2]及a[3]加1。

4-11 Function Multi-dimension Array Parameter Passing

例子:(multi-dim-array-parameter.c)传递多维数组参数

#include <stdio.h>
void print_matrix(int a[4][3], int i, int j)
{
printf("a[%d][%d] = %d\n", i, j, a[i][j]);
return;
}
int main(void)
{
int i, j;
int array[3][4];
for (i = 0; i < 3; i++)
for (j = 0; j < 4; j++)
scanf("%d", &(array[i][j]));
printf("array[2][1] = %d\n", array[2][1]);
print_matrix(array, 2, 1);
printf("array[0][2] = %d\n", array[0][2]);
print_matrix(array, 0, 2);
return 0;
}

注意,我们在main函数中申明的array是3,4,而print_matrix函数中申明的形式参数array是4,3。

输入

0 1 2 3
4 5 6 7
8 9 10 11

输出

array[2][1] = 9
a[2][1] = 7
array[0][2] = 2
a[0][2] = 2

why??因为

测验代码

因为不会算长方体可以分割多少个大小相等的正方体,凭感觉乱写了一个4/5的测验代码,与老师的相差那么一丢丢吧。

我的代码

#include <stdio.h>
int value(int type, int width, int height, int length)
{
if ((type != 79) && (type != 47) && (type != 29) && (type != 82) && (type != 26) && (type != 22))
return -1;
if ((width <= 0) || (height <= 0) || (length <= 0))
return -2;
int value;
// 找到最小的边长
int t;
if (width > height)
t = height;
else
t = width;
if (t > length)
t = length;
// 求正方体的边长和个数
int v1, n, a, v;
v1 = width * height * length;
for (a = t; a > 0; a--){
v = a * a * a;
if ( v1 % v == 0){
n = v1 / v;
break;
}
}
switch(type){
case 79:
value = v * v * n * 30;
break;
case 47:
value = v * v * n * 10;
break;
case 29:
value = v * v * n * 4;
break;
case 82:
value = v * v * n * 5;
break;
case 26:
value = v * v * n * 3;
break;
case 22:
value = v * v * n * 9;
break;
default:
value = 0;
}
return value;
}
int main ()
{
int type, width, height, length;
scanf ( "%d%d%d%d", &type, &width, &height, &length );
printf ( "%d", value ( type, width, height, length ) );
return 0;
}

老师的代码

#include <stdio.h>

int gcd ( int a, int b )
{
if ( a < b ) return gcd ( b, a ); if ( b == 0 )
return a;
else
return gcd ( b, a % b );
} int value ( int type, int width, int height, int length )
{
int u_val; switch ( type ) {
case 79:
u_val = 30;
break;
case 47:
u_val = 10;
break;
case 29:
u_val = 4;
break;
case 82:
u_val = 5;
break;
case 26:
u_val = 3;
break;
case 22:
u_val = 9;
break;
default :
return -1;
} if ( width <= 0 || height <= 0 || length <= 0 )
return -2; int s = gcd ( gcd ( width, height ), gcd ( height, length ) );
int v = s * s * s;
int count = ( width / s ) * ( height / s ) * ( length / s ); return v * v * count * u_val;
}

《计算机程式设计》Week4 课堂笔记的更多相关文章

  1. 【C语言】Coursera课程《计算机程式设计》台湾大学刘邦锋——Week6 String课堂笔记

    Coursera课程 <计算机程式设计>台湾大学 刘邦锋 Week6 String 6-1 Character and ASCII 字符变量的声明 char c; C语言使用一个位元组来储 ...

  2. 《计算机程式设计》Week5 课堂笔记

    本笔记记录自 Coursera课程 <计算机程式设计> 台湾大学 刘邦锋老师 Week5 Pointer 5-1 Pointer Definition and Declaration 指针 ...

  3. 《计算机程式设计》Week3 课堂笔记

    本笔记记录自 Coursera课程 <计算机程式设计> 台湾大学 刘邦锋老师 Week3 Array 3-1 Array Usage 例子:使用数组一次申明10个整数变量 int a[10 ...

  4. 《计算机程式设计》Week2 课堂笔记

    本笔记记录自 Coursera课程 <计算机程式设计> 台湾大学 刘邦锋老师 Week2 Control Structure 2-1 If-then-else if then 判断 if ...

  5. 九章算法系列(#3 Binary Tree & Divide Conquer)-课堂笔记

    前言 第一天的算法都还没有缓过来,直接就进入了第二天的算法学习.前一天一直在整理Binary Search的笔记,也没有提前预习一下,好在Binary Tree算是自己最熟的地方了吧(LeetCode ...

  6. 九章算法系列(#5 Linked List)-课堂笔记

    前言 又是很长时间才回来发一篇博客,前一个月确实因为杂七杂八的事情影响了很多,现在还是到了大火燃眉毛的时候了,也应该开始继续整理一下算法的思路了.Linked List大家应该是特别熟悉不过的了,因为 ...

  7. 九章算法系列(#4 Dynamic Programming)-课堂笔记

    前言 时隔这么久才发了这篇早在三周前就应该发出来的课堂笔记,由于懒癌犯了,加上各种原因,实在是应该反思.好多课堂上老师说的重要的东西可能细节上有一些急记不住了,但是幸好做了一些笔记,还能够让自己回想起 ...

  8. 九章算法系列(#2 Binary Search)-课堂笔记

    前言 先说一些题外的东西吧.受到春跃大神的影响和启发,推荐了这个算法公开课给我,晚上睡觉前点开一看发现课还有两天要开始,本着要好好系统地学习一下算法,于是就爬起来拉上两个小伙伴组团报名了.今天听了第一 ...

  9. ocp11g培训内部教材_052课堂笔记(042)_体系架构

    OCP 052 课堂笔记 目录 第一部分: Oracle体系架构... 4 第一章:实例与数据库... 4 1.Oracle 网络架构及应用环境... 4 2.Oracle 体系结构... 4 3. ...

随机推荐

  1. oracle数据库中的游标

    oracle中的游标,游标的概念与作用,游标的分类,游标的使用. 一,游标的概念与作用 摘自百度百科:游标(Cursor)是处理数据的一种方法,为了查看或者处理结果集中的数据,游标提供了在结果集中一次 ...

  2. Prometheus快速入门

    Prometheus是一个开源的,基于metrics(度量)的一个开源监控系统,它有一个简单而强大的数据模型和查询语言,让我们分析应用程序.Prometheus诞生于2012年主要是使用go语言编写的 ...

  3. 看CLRS 对B树的浅显理解

    定义及特点: 每个结点有n个关键字和n+1个指向子结点的指针,即有n+1个孩子结点. n个关键字按非递减的顺序存储. 最小度数t>=2,除了根结点的所有内部结点(非叶结点)的孩子数>=t且 ...

  4. Maven 添加其他Maven组件配置问题

    在父工程的pom文件里,添加如下配置 <project> <!--其它配置--> <modules> <module>A项目文件夹</module ...

  5. springboot easyexcel

    pom..xml <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel&l ...

  6. 1.使用kubeadm安装kubernetes

    一.环境准备 所有规划主机(一台master,两台node)均需操作 1.关闭防火墙,selinux [root@node1 ~]# systemctl stop firewalld [root@no ...

  7. [原创]Laravel 基于redis队列的解析

    目录 参考链接 本文环境 为什么使用队列 Laravel 中的队列 分发任务 任务队列 Worker Last-Modified: 2019年5月10日11:44:18 参考链接 使用 Laravel ...

  8. Dynamic len

    题目 有n个数编号从0→n-1,两种操作: Q L R:询问编号为L→R-1的数中共有多少种不同的数 M X Y:将编号为X的数改为Y 共有m个操作 分析 既然是单点修改,查询,我们考虑一下分块. 首 ...

  9. Kohana Minion cli 学习

    1.E:\html\tproject\framebota\platform\bootstrap.php Kohana::modules(array( 'auth' => MODPATH.'aut ...

  10. Linux内核源码分析

    Linux源码下载: https://www.kernel.org/ https://git.kernel.org/ Linux内核源码阅读以及工具(转): https://blog.csdn.net ...