当前位置: 首页 > article >正文

c语言简单编程练习9

1、输入一个整数,判断它是否为回文数

例:输入:12321       输出:该数是回文数      输入:12323         输出:该数不是回文数

#include <stdio.h>
int huiwenshu(int num)
{
    int a[100];
    int i, n, j, k;
    i = 0;
    n = 0;
    while(num)   //将整数存入数组 1234 -> a[100]={4,3,2,1};
    {
        n = num%10;
        a[i] = n;
        num /= 10;
        n = 0;
        i++;
    }
    k = i-1;  //找到最后一个数的下标
    for(j=0;j<(i-1)/2;j++)  //第一个与最后一个比较,从两边向中间依次比较
    {
        if(a[j]==a[k])
            k--;
        else
            return 0;
    }
    return 1;
}
int main(int argc, char *argv[])
{
    int n, m;
    printf("请输入一个整数:");
    scanf("%d",&n);
    m = huiwenshu(n);
    if(m==1)
    {
        printf("该数是回文数\n");
    }
    else
        printf("该数不是回文数\n");
    return 0;
}

解析: 在之前我们判断的是回文字符串,字符串我们是可以通过指针指向这个字符串,然后直接把最后一个字符与第一个字符比较,依次比较即可;但是这里需要判断的是回文数,这是一个整数我们并不能直接使用指针来比较它,所以我先使用了一个数组将整数的每一位数都存入了数组,然后通过调用数组里的值进行比较判断;

这里存整数是通过除以十取余数的方式来存储,将整数除以十,得到的余数存入数组第一个元素的位置,然后得到这个数除以十后的商,用商再除以十取余得到整数十位上的数,存入数组第二个元素的位置,依次存储,最后在数组中得到的就是整数反过来读的一组数字,例如1234,在数组中就是4321;虽然是倒过来的但是并不影响我们判断它是否为回文数;

得到数组后我们直接使用一个循环来进行比较,循环的条件跟整数的位数相关,也就是跟数组中的元素个数相关,j=0;j<(i-1)/2;j++;j从0开始,到小于元素个数的一半即可,这样就能保证比较完;在这里我把判断回文数写为了一个函数,当比较到数字不相同就返回0(表示输入的整数不是回文数),要是循环能完成就返回1;这样通过判断函数的返回值就能知道输入的整数是不是回文数。

 2、函数的多文件封装

多文件封装的优点:

  1. 模块化
    • 将代码拆分成多个文件,每个文件负责特定的功能或模块,可以使代码结构更加清晰和易于管理。
    • 模块化有助于减少代码之间的依赖,使得代码更易于维护和扩展。
  2. 可读性
    • 将函数和类分散到多个文件中,每个文件专注于一个特定的任务或功能,可以提高代码的可读性。
    • 开发者可以更容易地找到和理解所需的代码部分,而不必在大量代码中搜索。
  3. 可重用性
    • 通过将常用功能封装到独立的文件中,可以更容易地在多个项目或模块中重用这些功能。
    • 这有助于减少代码重复,提高开发效率。
  4. 代码维护
    • 当需要修改或更新代码时,模块化结构使得修改更加局部化,减少了引入错误的风险。
    • 独立的文件也更便于版本控制和代码审查。
  5. 编译和加载效率
    • 在一些编程语言中,如C或C++,将代码拆分成多个文件可以优化编译过程,因为编译器可以只重新编译那些发生变化的文件。
    • 对于大型项目,这可以显著减少编译时间。
    • 在一些动态语言(如Python)中,将代码拆分成多个模块也可以提高模块的加载效率,因为模块只会在需要时被加载。
  6. 团队协作
    • 模块化结构使得多个开发者可以并行工作在不同的模块上,减少了代码冲突和合并问题的可能性。
    • 这有助于加快开发进度,提高团队协作效率。
  7. 命名空间管理
    • 将函数和类封装到不同的文件中,可以避免命名冲突,特别是当使用全局变量或函数时。
    • 通过命名空间(如Python中的模块、Java中的包)来组织代码,可以提高代码的安全性和可维护性。
  8. 代码封装和隐藏实现细节
    • 将实现细节封装在单独的文件中,并通过公共接口(如API)暴露必要的功能,可以隐藏内部实现细节,提高代码的封装性和安全性。
    • 这有助于减少外部代码对内部实现的依赖,使得内部实现更容易进行更改和优化。

函数的多文件封装通常分为三个文件:自定义头文件、功能函数文件、测试文件(主函数文件)

自定义头文件里面放的是库头文件(用<>引用)和我们自定义的头文件(用双引号引用)

< >和" "的区别:

尖括号< >

  • 用途:主要用于引用标准库头文件或安装在系统级别的第三方库头文件。
  • 查找路径:编译器会直接在它的默认包含目录中查找头文件。这些目录通常由编译器预定义或通过编译选项

双引号"

  • 用途:主要用于引用项目特定或自定义的头文件,例如你自己写的头文件或者与项目紧密相关的第三方库头文件。
  • 查找路径:编译器会首先在源文件所在的目录进行查找,然后才会去编译器默认的包含目录中查找。这种方式允许开发者更灵活地管理文件位置,特别是在项目结构复杂时。

下面我将题1的代码来做多文件封装,便于宝子们对照

自定义头文件:

#ifndef _HUIWEN_H
#define _HUIWEN_H

#include <stdio.h>
int huiwenshu(int num);

#endif

头文件的格式就是头两行为 #ifndef _HUIWEN_H(如果没有定义huiwen.h这个头文件)和#define _HUIWEN_H(定义huiwen.h这个头文件),最后加一行#endif;中间要写的就是所需要头文件的引用和我们自己功能函数的声明

功能函数文件:

#include "huiwen.h"
int huiwenshu(int num)
{
    int a[100];
    int i, n, j, k;
    i = 0;
    n = 0;
    while(num)   //将整数存入数组 1234 -> a[100]={4,3,2,1};
    {
        n = num%10;
        a[i] = n;
        num /= 10;
        n = 0;
        i++;
    }
    k = i-1;  //找到最后一个数的下标
    for(j=0;j<(i-1)/2;j++)  //第一个与最后一个比较,从两边向中间依次比较
    {
        if(a[j]==a[k])
            k--;
        else
            return 0;
    }
    return 1;
}

在功能函数文件里面我们首先需要引用我们自定义的头文件 #include "huiwen.h",之后就是需要实现功能的函数,这里面可以放多个功能函数,同时就需要在我们自定义的头文件里面声明所有的功能函数。

测试文件(主函数文件):

#include "huiwen.h"
int main(int argc, char *argv[])
{ 
    int n, m;
    printf("请输入一个整数:");
    scanf("%d",&n);
    m = huiwenshu(n);
    if(m==1)
    {
        printf("该数是回文数\n");
    }
    else
        printf("该数不是回文数\n");
    return 0;
} 

在测试文件里面我们也需要先引用我们自定义的头文件,之后就是通过调用函数来实现相应的功能。

注意:除了我们的测试文件(主函数文件) 之外,其他两个文件都不能有主函数int main()。

3、 静态存储(static)

作用:

  1. 在函数体内定义静态变量

    • 记忆功能:被声明为static的局部变量在这一函数被调用的过程中其值维持不变,即函数返回后,该变量的值不会丢失,下次该函数被调用时,该变量将保持上次函数执行结束时的值。
    • 存储位置:静态局部变量存储在全局数据区(静态区),而非栈区。
    • 生命周期:静态局部变量的生命周期贯穿整个程序运行期间,但其作用域仍然是局部的,即只能在定义它的函数内部访问。
  2. 在模块内(函数体外)定义静态变量

    • 作用域限制:静态全局变量只能被本模块内的函数访问,而不能被模块外的其他函数访问。它相当于一个本地的全局变量。
    • 存储位置:同样存储在全局数据区。
    • 初始化:静态全局变量只初始化一次,防止在其他文件单元中被引用。
  3. 定义静态函数

    • 作用域限制:静态函数只能在本源文件中使用,不能被其他源文件调用。这有助于实现信息隐藏和模块化编程。

记忆功能,我也把它称为延长生命周期(不是延长作用域!!!),下面我用一个例子来说明:

#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
p:{
    int a;
    a = 10;
    a++;
    printf("%d\n",a);
    sleep(2);
    goto p;
  }
    return 0;
}

在代码中我使用goto做了一个循环,相信宝子们都知道上面代码会每2秒打印a的值,但是由于每次goto都回到了a定义前,因此每次打印a的值都为11,如下图:

                        

但是我如果使用static去修饰变量a,那么goto回去之后并不会将它初始化,a任然会保持上次执行的值不变,在上次值的基础上++,执行结果如上面右图,代码如下:

#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
p:{
    static int a =10;
    a++;
    printf("%d\n",a);
    sleep(2);
    goto p;
  }
    return 0;
}

4、printf的缓冲行为

printf将数据输出到标准输出时,这些数据的缓冲行为遵循标准输出的缓冲机制。

缓冲的一些关键点:

  1. 行缓冲:当输出流是交互式设备(如终端或控制台)时,标准输出通常是行缓冲的。这意味着输出会存储在缓冲区中,直到遇到换行符(\n)或缓冲区满时,缓冲区的内容才会被刷新到输出设备。

  2. 全缓冲:当输出流是文件时,标准输出通常是全缓冲的。这意味着输出会存储在缓冲区中,直到缓冲区满或显式调用fflush函数时,缓冲区的内容才会被写入文件。

  3. 无缓冲:标准错误(stderr)通常是无缓冲的,意味着每次调用如fprintf(stderr, ...)都会立即将输出刷新到设备,而不会存储在缓冲区中。

#include <stdio.h>
int main(int argc, char *argv[])
{ 
    printf("1111");
    while(1)
    {
        //printf("2222");
        //usleep(10000);
    }

    return 0;
} 

当printf没有加换行符‘\n’时,代码会全部执行完才会将1111打印出来,我在下面加了一个死循环之后,光标会在终端一直闪烁,并不会输出1111,运行结果如下:

 

把上述代码被注释掉的两行加入,就能得到当缓冲区被放满后,缓冲区的内容被刷新输出到终端的结果,如下图:

 

 


http://www.kler.cn/a/381896.html

相关文章:

  • ReentrantLock底层原理、源码解析
  • JAVA开发入门学习七- 数组
  • C/C++基础错题归纳
  • cudnn版本gpu架构
  • PyTorch 神经网络回归(Regression)任务:关系拟合与优化过程
  • 前端开发 之 12个鼠标交互特效上【附完整源码】
  • 剧本杀小程序,市场发展下的新机遇
  • 鸿蒙HarmonyOS NEXT应用层架构
  • SpringBoot源码解析(一):SpringApplication构造方法
  • npm入门教程5:package.json
  • 静态库、动态库、framework、xcframework、use_frameworks!的作用、关联核心SDK工程和测试(主)工程、设备CPU架构
  • 分布式光伏发电的投融资计算
  • OTFS基带通信系统(脉冲导频,信道估计,MP解调算法)
  • 零基础快速入门MATLAB
  • Nat Med病理AI系列|哈佛大学团队发表研究,探讨深度学习在病理诊断中的公平性问题及解决方案|顶刊精析·24-11-02
  • Webserver(3.2)锁
  • 基于CentOS 7.9上安装WebLogic
  • 【STL_list 模拟】——打造属于自己的高效链表容器
  • EasyExcel 学习之 导出 “文件编码问题”
  • 苍穹外卖 商家取消、派送、完成订单
  • HTB:PermX[WriteUP]
  • 附件商户,用户签到,uv统计功能(geo,bitmap,hyperloglog结构的使用)
  • 如何使用RabbitMQ和Python实现广播消息
  • 深度学习基础知识-Batch Normalization(BN)超详细解析
  • 第二节 管道符、重定向与环境变量
  • 手写一个axios方法