C语言实验(九):数组(中值滤波、两个不超过 200 位的非负整数的和)


实验一:编程实现中值滤波

中值滤波是对一个滑动窗口内的诸像素灰度值排序,用其中值代替窗口中心象素的原来灰度值,它是一种非线性的图像平滑法,它对脉冲干扰级椒盐噪声的抑制效果好,在抑制随机噪声的同时能有效保护边缘少受模糊。中值滤波可以过滤尖峰脉冲。目的在于我们对于滤波后的数据更感兴趣。滤波后的数据保留的原图像的变化趋势,同时去除了尖峰脉冲对分析造成的影响。
以一维信号的中值滤波举例。对灰度序列80、120、90、200、100、110、70,如果按大小顺序排列,其结果为70、80、90、100、110、120、200,其中间位置上的灰度值为100,则该灰度序列的中值即为100。一维信号中值滤波实际上就是用中值代替规定位置(一般指原始信号序列中心位置)的信号值。对前面所举的序列而言,中值滤波的结果是用中值100替代序列80、120、90、200、100、110、70中的信号序列中心位置值200,得到的滤波序列就是80、120、90、100、100、110、70。如果在此序列中200是一个噪声信号,则用此方法即可去除这个噪声点。
上面的例子所使用的滤波窗口大小为7,如果窗口大小为3,则中值滤波的结果为80、90、120、100、110、100、70
题目:使用窗口大小3,实现下面数据的中值滤波。
128 100 89 81 99 191 85 119 255 200 198 23 21 32 10 49 98 23 123 234 190 99 190 88 68 97 105 64 25 156

实验内容

1、要实现一组数据求中值滤波,要用数组储存、处理数据。思路:从数据中依次取出N个数据进行排序;用排序后的中值代替要处理的数据。

2、先实现排序,并找到中值。使用冒泡排序法进行排序,返回中值。其中数组名作为函数参数时,传入的是一个地址。

3、排序找到中值之后,新建一个长度为3的数组用于暂时存放窗口数据,不断更新。再新建一个数组,将原数据的头尾先固定到该数组。新的数组存放滤波后的数据,每次都将中值存入该数组。

4、完成函数封装之后,编写主函数。将原数据放到数组中,调用窗口为3 的中值滤波函数。发现程序可以通过编译并运行,但结果只有4个数。

5、输出数组长度查看,发现结果为4. 原因是:在C语言中,数组名作为参数传递给函数时,退化为指针,sizeof对指针操作结果应该是4。所以函数中如果需要数组的大小时,需要我们一个参数传数组名,另一个传数组大小。

6、修改函数参数设置,一个参数传数组名,另一个传数组大小。编译通过,并正常运行。运行结果如下。

实验代码
#include <stdio.h>
#include <stdlib.h>
void MediamFilter_3(int sn[],int n); //窗口为3中值滤波
float MediumNum(int s[],int n); //求数组长度为n的中值

int main()
{
    int sn[30]={128,100,89,81,99,191,85,119,255,200,198,23,21,32,10,49,98,23,123,234,190,99,190,88,68,97,105,64,25,156};
    MediamFilter_3(sn,30);
    return 0;
}

void MediamFilter_3(int sn[],int n)
{
    int i,j,k;
    int s[3]={0},t[100]={0};
    t[0] = sn[0];
    t[29] = sn[29];
    j=1;
    for(i=0;i<28;i++)
    {
        s[0] = sn[i];
        s[1] = sn[i+1];
        s[2] = sn[i+2];

        t[j] = MediumNum(s,3); //每个窗口确定一个值
        j++;
    }

    for(i=0;i<n;i++)
        printf("%4d",t[i]);//将滤波结果输出
    printf("\n");
}


float MediumNum(int s[],int n)
{
    int i,j,t;

    for(i=0;i<n-1;i++) //冒泡排序法
    {
        for(j=0;j<n-i-1;j++)
        {
            if(s[j]>s[j+1])
            {
                t=s[j];
                s[j]=s[j+1];
                s[j+1]=t;
            }
        }
    }

    if(n/2==0)//数组长度为奇数偶数返回值计算不同
        return (s[n/2]+s[n/2-1])/2;
    else
        return s[(n-1)/2];
}
运行结果

在这里插入图片描述


实验二:编程求两个不超过 200 位的非负整数的和。

输入数据
有两行,每行是一个不超过 200 位的非负整数,没有多余的前导 0。
输出要求
一行,即相加后的结果。结果里不能有多余的前导 0,即如果结果是 342,那么就不能 输出为 0342。
输入样例
22222222222222222222
33333333333333333333
输出样例
Output Sample:
55555555555555555555

实验内容

1、两个大整数相加,首先要考虑大整数的储存问题。C语言中没有可以储存200位数的数据类型,考虑到字符串其实就是一个字符数组,可以通过数组的方式储存大整数。

2、整数的相加用最简单的原理:从个位数开始逐个相加,其中涉及到一个问题就是进位。所以为了方便计算并且进位,我们先把大整数翻转过来,从各位开始计算。

3、逐位相加并存入另一个字符串中(相加过程中要检查是否有进位),最后将得到的字符串逆置就可以得到结果。其中最重要的是进位问题,所以通过一个变量t,在求实际和和加数维数不同每一个的时候都要判断是否进位,并设置进位值。

实验代码
#include <stdio.h>
#include <stdlib.h>
void sum(char str1[],char str2[],char res[]);
void reverse(char str[]); //字符串倒置函数

int main()
{
    char str1[200] = {0};
    char str2[200] = {0};
    char res[201];

    gets(str1);
    gets(str2);
    sum(str1,str2,res);
    printf("%s",res);
    return 0;
}

void sum(char str1[],char str2[],char res[])
{
    reverse(str1);//倒置
    reverse(str2);//倒置

    int len1,len2,i;
    int t=0,temp;
    len1 = strlen(str1);
    len2 = strlen(str2);

    for(i=0;i<len1&&i<len2;i++)
    {
        temp = (str1[i]-'0'+str2[i]-'0')%10; //每一位相加
        res[i] = temp + t +'0';
        if(str1[i]-'0' + str2[i]-'0'>= 10)//判断是否需要进位
            t=1;
        else
            t=0;
    }

    if(i < len1)
    {
        for(;i<len1;i++)
        {
            temp = (str1[i] - '0')%10;
            res[i] =  temp + t +'0';

            if(str1[i]-'0' >= 10)//判断结果第一位是否进位
                t = 1;
            else
                t = 0;
        }
    }

    if(i < len2)
    {
        for(;i<len2;i++)
        {
            temp = (str2[i] - '0')%10;
            res[i] = temp + t + '0';

            if(str2[i]-'0' >= 10)//判断结果第一位是否进位
                t = 1;
            else
                t = 0;
        }
    }

    if(t == 1)//如果进位要加1
        res[i++] = '1';
    res[i] = '\0';
    reverse(res); //翻转过来就是结果
}

void reverse(char str[]) //字符串倒置函数
{
    int len;
    int i;
    char temp;
    len = strlen(str);
    for(i=0;i<len/2;i++)
    {
        temp = str[i];
        str[i] = str[len-i-1];
        str[len-i-1] = temp;
    }
}

运行结果

在这里插入图片描述

实验总结

中值滤波的实验主要是练习了数组的用法。新建空数组用于存放结果,新建数组用于暂时存放窗口数据。以及学到一个重要的知识点:数组作为函数参数传入时是一个指针,不能用sizeof函数得到数组的长度。如果要使用这个数组的长度,要同时把数组长度传入函数。
大整数相加的实验参考了一些代码都看不下去,最后还是自己根据算法思路编写代码。其中进位问题很让人困扰,结合网上的思路解决了如何判断进位的问题,后来发现漏掉不同位数相加的情况。从这个实验可以看出字符串是一个字符数组,可以按照数组的方法进行处理。同样新建了一个空数组用于存放结果。
在画流程图的时候画得比较乱,没有细致地自主分析算法流程,实现代码的时候效率低下。之前的学习过程中还是有知识漏洞。导致代码写出来之后花了不少时间检查漏洞。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值