1705 字
9 分钟
C语言答疑-01

C 语言答疑-01#

​ By Von Brank | 2020/10/28

目录:#

  • IDE 的推荐与使用
  • 在线评测系统的推荐与使用
  • 近期所学知识梳理
  • 常见错误
  • 几道例题
  • 答疑

IDE 的推荐与使用#

  • Dev-Cpp

  • Visual Studio Code

在线评测系统的推荐与使用#

知识点梳理#

函数#


函数的基本应用#

解决代码重复率高,质量低下的问题

如:

int i, sum;
for(i=1, sum=0; i<=10; i++) //计算1~10的和
{
    sum += i;
}
printf("%d\n", sum);

for(i=11, sum=0; i<=20; i++) //计算11~20的和
{
    sum += i;
}
printf("%d\n", sum);

for(i=21, sum=0; i<=30; i++) //计算21~30的和
{
    sum += i;
}
printf("%d\n", sum);

写成函数形式

void sum(int a, int b)
{
    int ans = 0, i;
    for(i=a; i<=b; i++)
    {
        ans += i;
    }
    printf("%d\n", ans);
}

函数的定义#

<函数头> <函数名>(参数表)
{
    函数体
}

void sum(int a, int b)
{
    int ans = 0, i;
    for(i=a; i<=b; i++)
    {
        ans += i;
    }
    printf("%d\n", ans);
}

函数的调用#

#include <stdio.h>
void hello()
{
    printf("Hello World!!!");
}
int main()
{
    hello; -> 错误写法
    hello(); //没有参数也要()
    return 0;
}
#include <stdio.h>
void sum(int a, int b)
{
    int ans = 0, i;
    for(i=a; i<=b; i++)
    {
        ans += i;
    }
    printf("%d\n", ans);
}
int main()
{
    sum(1, 10);
    sum(11, 20);
    sum(21, 30);
    return 0;
}

函数的返回值#

返回类型写法
void function();
intint function();
doubledouble function();
#include <stdio.h>
int sum(int a, int b)
{
    int ans = 0, i;
    for(i=a; i<=b; i++)
    {
        ans += i;
    }
    return ans;  //注意:非void类型函数结尾必须写return语句
}
int main()
{
    printf("%d\n", sum(1, 10));
    return 0;
}
  • return是函数的出口
  • return <变量>;是非void函数的出口,并返回一个值
  • void函数中的return;仅作为函数的出口

函数原型(声名)#

  • main 函数之前声名,在main函数后定义一定程度上可以避免头重脚轻,但通常不会这么写
  • C/C++/Java 语言对于声名,定义等概念有严格要求
#include <stdio.h>
int sum(int a, int b); //告诉编译器这个函数的样子
int main()
{
    printf("%d\n", sum(1, 10));
    return 0;
}
int sum(int a, int b)
{
    int ans = 0, i;
    for(i=a; i<=b; i++)
    {
        ans += i;
    }
    return ans;
}

参数的传递#

本质上是用传入的参数初始化函数参数表的变量

注意:

  • 传递的参数要与参数表对应类型相匹配
  • 传递参数的个数要与对应函数参数表的变量个数相匹配
#include <stdio.h>
void sum(int a, int b)
{
    int ans = 0, i;
    for(i=a; i<=b; i++)
    {
        ans += i;
    }
    printf("%d\n", ans);
}
int main()
{
    sum(1.1, 9.9); //不匹配的参数类型会被强制类型转换,然后以其结果初始化参数
    sum(11, 20, 30); //传入的参数个数不匹配会导致编译错误
    sum(21, 30);
    return 0;
}

参数在函数内是本地变量#

  • 变量的值作为参数初始化参数表的变量时,参变量值的改变不会改变被传入参数的值
#include <stdio.h>
void sum(int a, int b)
{
    n = 1;
    int ans = 0, i;
    for(i=a; i<=b; i++)
    {
        ans += i;
    }
    printf("%d\n", ans);
}
int main()
{
    int m = 1, n = 10;
    sum(m, n);
    return 0;
}
  • 与全局变量同名的参数表变量会将该全局变量屏蔽
#include <stdio.h>
int a, b;
void sum(int a, int b)
{
    int ans = 0, i;
    for(i=a; i<=b; i++)
    {
        ans += i;
    }
    printf("%d\n", ans);
}
int main()
{
    sum(1, 10);
    return 0;
}
  • 不与参变量同名的全局非常量变量可以在函数内直接被修改
#include <stdio.h>
int n;
void sum(int a, int b)
{
    n = 1;
    int ans = 0, i;
    for(i=a; i<=b; i++)
    {
        ans += i;
    }
    printf("%d\n", ans);
}
int main()
{
    sum(1, 10);
    return 0;
}
  • 代码块内部的变量也是本地变量,与函数内的本地变量类似
#include <stdio.h>
int main()
{
    int a, b;
    a = 1;
    b = 2;
    printf("%d %d\n", a, b);
    {
        int a;
        a = 3;
        printf("%d %d\n", a, b);
    }
    return 0;
}

关于函数的一些细节#

  • void function(void);以及void function();表示参数未知,并不表示没有参数,

如:

#include <stdio.h>
void f();
int main()
{
	int a = 1, b = 2;
    f(a, b);
    return 0;
}
void f(double a, double b)
{
    printf("%d %d", a, b);
}

这类写法是编译器的作者没想到的,因此在编写函数原型时一定要写全参数,在没有参数时可写void

  • 逗号预算符,在参数传递中可能导致的错误
#include <stdio.h>
int a, b;
void sum(int a, int b)
{
    int ans = 0, i;
    for(i=a; i<=b; i++)
    {
        ans += i;
    }
    printf("%d\n", ans);
}
int main()
{
    int a = 1, b = 10;
    sum(a, b);
    sum((a, b));  //比较这两行的区别
    return 0;
}
  • C/C++语言不允许函数内嵌套函数

  • 几种鬼畜的写法

    如:

    int i, j, sum(int a, int b);
    
    return (ans);

    以上写法可以通过编译,但不推荐使用

main()是什么#

  • int main()也是一个函数
  • 可以写成int main(void)但通常不这么写
  • main函数结尾的return 0;是有意义的

递归#

  • 递归是程序运行过程中函数调用自身的行为

  • 阶乘斐波那契数列是经典的递归案例,但是学完数组之后你很可能不会再用递归来实现它们

    int Fib(int n)
    {
        if(n == 1 || n == 2) return 1;
        else return Fib(n - 1) + Fib(n - 2);
    }
    
    int Fac(int n)
    {
        if(n == 0) return 1;
        else return n * Fac(n - 1);
    }
  • C 语言中递归的本质——

几道题#

洛谷 P5735 【深基 7.例 1】距离函数#

给出平面坐标上不在一条直线上三个点坐标(x1,y1),(x2,y2),(x3,y3)(x_1,y_1),(x_2,y_2),(x_3,y_3),坐标值是实数,且的绝对值不超过 100.00100.00,求围成的三角形周长。保留两位小数。

对于平面上的两个点 (x1,y1),(x2,y2)(x_1,y_1),(x_2,y_2),则这两个点之间的距离 dis=(x2x1)2+(y2y1)2dis=\sqrt{(x_2-x_1)^2+(y_2-y_1)^2}

洛谷 P5737 【深基 7.例 3】闰年展示#

输入 x,y(1582x<y3000)x,y(1582\le x < y \le 3000),输出[x,y][x,y]区间中闰年个数,并在下一行输出所有闰年年份数字,使用空格隔开。

洛谷 P1255 数楼梯#

楼梯有NN阶,上楼可以一步上一阶,也可以一步上二阶。

编一个程序,计算共有多少种不同的走法。

洛谷 P1464 Function#

对于一个递归函数w(a,b,c)w(a,b,c)

  • 如果a0orb0orc0a \le 0\quad or\quad b \le 0 \quad or\quad c \le 0就返回值1111
  • 如果a>20orb>20orc>20a>20\quad or\quad b>20\quad or\quad c>20\quad就返回w(20,20,20)w(20,20,20)
  • 如果a<ba<b并且b<cb<c就返回w(a,b,c1)+w(a,b1,c1)w(a,b1,c)w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c)
  • 其它的情况就返回w(a1,b,c)+w(a1,b1,c)+w(a1,b,c1)w(a1,b1,c1)w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1)

这是个简单的递归函数,但实现起来可能会有些问题。当a,b,ca,b,c均为1515时,调用的次数将非常的多。你要想个办法才行.

对于一些特殊情况,比如 w(30,1,0)w(30,-1,0)既满足条件11又满足条件22,这种时候我们就按最上面的条件来算,所以答案为11

洛谷 P1029 最大公约数和最小公倍数问题#

输入两个正整数 x0,y0x_0, y_0,求出满足下列条件的 P,QP, Q 的个数:

  1. P,QP,Q 是正整数。
  2. 要求 P,QP, Qx0x_0 为最大公约数,以 y0y_0 为最小公倍数。

试求:满足条件的所有可能的 P,QP, Q 的个数。

C语言答疑-01
https://blog.vonbrank.com/posts/hit-cs31106-explanation-01/
作者
Von Brank
发布于
2020-10-28
许可协议
CC BY-NC-SA 4.0