这回在上回实现功能的基础之上,修改了一些命名上的不规范,并且让文件操作更加优雅
一、引言
1.相关检测技术是信号检测领域里一种重要工具,常用于从噪声背景中检测出有用的确定性信号。它利用确定性信号在不同时刻的取值一般都具有较强相关性,而干扰噪声因为随机性较强,不同时刻取值相关性较差的特性,把确定性信号和干扰噪声区分开来。
-
假设确定信号序列为x[m],具有噪声背景的实际信号序列为y[n],m<n,通过滑动相关计算,找出滑动相关计算序列z[k]的最大的值,则可以求出具有噪声背景的实际信号序列y中所包含的确定信号序列x的位置。
-
滑动相关计算公式为:
二、系统设计要求
总体要求:在12个候选小区中确认是否有适合接入的小区?若有,请找到终端最适合接入的小区。
要求输出中间过程的打印信息:
1、打印各小区强度以及排序的结果(小区ID即文件名);
2、打印与3组PSS相关后所获得的各自序列的最大值;
3、打印设置的强度门限以及相关门限;
4、体现流程分支走向(无适合接入小区,驻留失败/当前小区无法接入,寻找下一小区/当前小区满足接入条件,流程结束);
三、设计思路与方案
3.1 程序流程图设计
3.2 变量设计
#define data_N 12//数据组数
#define PSS_N 3//PSS文件数
#define MAX_data 30000 //data中存放信号强度的实部和虚部Q和I共30000个数据
#define MAX_PSS 4096 //PSS 存放数据4096行
struct Cell//小区结构体
{
char ID[15];//小区名称——文件名称
double avg_strength;//小区信号平均强度
double strength[MAX_data/2];//小区信号强度
double max_colleration[PSS_N];//相关性序列最大值
};
struct PSS //确定信号序列结构体
{
char ID[15];
double strength[MAX_PSS/2];//确定的信号强度
} ;
struct Cell cell[data_N];//小区结构体数组
struct PSS pss[PSS_N];//确定的信号序列结构体数组
void ID_init()//初始化小区名称
{
int i;
for(i=0;i<data_N;i++)
{
sprintf(cell[i].ID,"data%d.txt",i+24);//ID幅值data24~data35
}
for(i=0;i<PSS_N;i++)
{
sprintf(pss[i].ID,"PSS%d.txt",i);//ID幅值PSS0~PSS2
}
}
3.3 文件读取以及数据处理
完成读取data文件,计算信号强度模值和平均信号强度并存入cell结构体;读取PSS文件并计算信号强度模值存入PSS数组
void fileop_data()//读取data文件,计算信号强度模值和平均信号强度并存入cell结构体
{
FILE* fp;
int i,j;
double sum = 0;
double Q,I;//定义双精度浮点数存放信号强度的实部和虚部
for(i=0;i<data_N;i++)
{
if((fp = fopen(cell[i].ID,"r")) == NULL)
{
printf("打开文件错误");
}
else
{
for(j=0;j<MAX_data/2;j++)//
{
fscanf(fp,"%lf %lf",&Q,&I);//读取文件,并将数值存储到Q和I中
sum = sum + sqrt(Q * Q + I * I);
cell[i].strength[j] = sqrt(Q * Q + I * I);//求信号强度模值并存入结构体
}
if(j == MAX_data/2)//当执行到MAX/2次时执行以下代码
{
cell[i].avg_strength = sum / (MAX_data/2);//求平均信号强度并存入结构体
sum = 0;//总和清零
j = 0;//次数清零
}
}
fclose(fp);
}
}
void fileop_pss()//读取PSS文件并计算信号强度模值存入PSS数组
{
FILE* fp;
double Q, I;
for (int i=0; i <PSS_N; i++)
{
if ((fp = fopen(pss[i].ID, "r")) == NULL)
{
printf("打开PSS文件错误");
}
for (int j=0; j<MAX_PSS/2; j++)
{
fscanf(fp, "%lf %lf", &Q, &I);
pss[i].strength[j] = sqrt(Q * Q + I * I);//计算信号强度模值并存入结构体
}
fclose(fp);
}
}
3.4 冒泡排序
对小区平均信号强度从大到小进行冒泡排序。
void sort()//冒泡算法排序
{
struct Cell temp;
for (int i=0; i<=data_N-1; i++)
{
for (int j=0; j<=data_N-1-i; j++)
{
if (cell[j].avg_strength < cell[j+1].avg_strength)
{
temp = cell[j] ;
cell[j] = cell[j+1];
cell[j+1] = temp;
}
}
}
}
3.5滑动相关检测
根据公式:
可设计算法如下:
double slide(struct Cell *cell, struct PSS *pss)//滑动相关检测
{
int i,j;
double max=0;//用于放置最大相关序列
double temp;//用于暂存当前序列
for(i=0; i<MAX_data/2 - MAX_PSS/2 + 1; i++)//根据公式i∈[0,n-m]
{
temp = 0;
for(j=0;j<MAX_PSS/2;j++)
{
temp = temp + pss->strength[j] * cell->strength[i+j];
}
if(temp>max)
{
max = temp;
}
return max;
}
return 0;
}
3.6 判断是否能接入
由于排序后的结构体数据根据平均强度由强到弱的顺序存放,故先判断小区信号平均强度的最大值是否满足设定平均强度门限,若不满足则输出“无适合接入小区,驻留失败”;若满足则用flag标记出满足条件的最小位;再判断满足条平均强度的小区中,最大相关序列是否满足设定的相关门限;若满足则输出“当前小区满足接入条件,流程结束”;若当前小区不满足则继续判断下一个小区是否满足条件。
void IfConnect()//根据输入门限判断能否连接
{
int i;
int flag;//用于标记满足平均强度门限的小区
double strength_threshold;//定义平均强度门限
double correlation_threshold;//定义相关后最大强度门限
printf("\n请输入强度门限:\n");
scanf("%lf",&strength_threshold);
//判断是否满足平均强度门限
if(cell[0].avg_strength<strength_threshold)//最大值也低于门限
{
printf("\n无适合接入小区,驻留失败");
return;
}
printf("\n满足平均强度门限条件的小区有:\n");
for (i=0; i<data_N; i++)
{
if(cell[i].avg_strength>=strength_threshold)//如果满足门限条件打印相关信息
{
printf("ID:%s\b\b\b\b 信号平均强度:%lf\n", cell[i].ID, cell[i].avg_strength);
flag=i;
}
}
printf("\n请输入相关门限:\n");
scanf("%lf",&correlation_threshold);
//判断是否满足最大相关门限
for(i=0;i<=flag;i++)
{
if(cell[i].max_colleration[0]>correlation_threshold&&
cell[i].max_colleration[1]>correlation_threshold&&
cell[i].max_colleration[2]>correlation_threshold)
printf("ID:%s\b\b\b\b 当前小区满足接入条件,流程结束\n",cell[i].ID);
else
printf("ID:%s\b\b\b\b 当前小区无法接入,寻找下一小区\n",cell[i].ID);
}
}
3.7 主函数
int main()
{
int i,j;
ID_init();//初始化小区名称
printf("文件读取中...\n");
fileop_pss();
fileop_data();
sort();
printf("\n排序结果为:\n");
for(int i=0; i<data_N; i++)
{
printf("ID;%s\b\b\b\b信号平均强度为:%lf\n",cell[i].ID,cell[i].avg_strength);
}
printf("\nPSS与小区匹配结果:\n");
for(i=0;i<data_N;i++)//求实际信号与确定信号相关性序列最大值
{
for(j=0;j<PSS_N;j++)
{
cell[i].max_colleration[j] = slide(&cell[i],&pss[j]);//将滑动相关后的相关性序列最大值给小区结构体
printf("ID:%s\b\b\b\b 与 PSS%d 相关性序列最大值:%lf\n", cell[i].ID, j, cell[i].max_colleration[j]);
}
}
IfConnect();
}
3.8 整体代码
#include <stdio.h>
#include <string.h>
#include <math.h>
#define data_N 12//数据组数
#define PSS_N 3//PSS文件数
#define MAX_data 30000 //data中存放信号强度的实部和虚部Q和I共30000个数据
#define MAX_PSS 4096 //PSS 存放数据4096行
struct Cell//小区结构体
{
char ID[15];//小区名称——文件名称
double avg_strength;//小区信号平均强度
double strength[MAX_data/2];//小区信号强度
double max_colleration[PSS_N];//相关性序列最大值
};
struct PSS //确定信号序列结构体
{
char ID[15];
double strength[MAX_PSS/2];//确定的信号强度
} ;
struct Cell cell[data_N];//小区结构体数组
struct PSS pss[PSS_N];//确定的信号序列结构体数组
void ID_init()//初始化小区名称
{
int i;
for(i=0;i<data_N;i++)
{
sprintf(cell[i].ID,"data%d.txt",i+24);
}
for(i=0;i<PSS_N;i++)
{
sprintf(pss[i].ID,"PSS%d.txt",i);
}
}
void fileop_data()//读取data文件,计算信号强度模值和平均信号强度并存入cell结构体
{
FILE* fp;
int i,j;
double sum = 0;
double Q,I;//定义双精度浮点数存放信号强度的实部和虚部
for(i=0;i<data_N;i++)
{
if((fp = fopen(cell[i].ID,"r")) == NULL)
{
printf("打开文件错误");
}
else
{
for(j=0;j<MAX_data/2;j++)//
{
fscanf(fp,"%lf %lf",&Q,&I);//读取文件,并将数值存储到Q和I中
sum = sum + sqrt(Q * Q + I * I);
cell[i].strength[j] = sqrt(Q * Q + I * I);//求信号强度模值并存入结构体
}
if(j == MAX_data/2)//当执行到MAX/2次时执行以下代码
{
cell[i].avg_strength = sum / (MAX_data/2);//求平均信号强度并存入结构体
sum = 0;//总和清零
j = 0;//次数清零
}
}
fclose(fp);
}
}
void fileop_pss()//读取PSS文件并计算信号强度模值存入PSS数组
{
FILE* fp;
double Q, I;
for (int i=0; i <PSS_N; i++)
{
if ((fp = fopen(pss[i].ID, "r")) == NULL)
{
printf("打开PSS文件错误");
}
for (int j=0; j<MAX_PSS/2; j++)
{
fscanf(fp, "%lf %lf", &Q, &I);
pss[i].strength[j] = sqrt(Q * Q + I * I);//计算信号强度模值并存入结构体
}
fclose(fp);
}
}
void sort()//冒泡算法排序
{
struct Cell temp;
for (int i=0; i<=data_N-1; i++)
{
for (int j=0; j<=data_N-1-i; j++)
{
if (cell[j].avg_strength < cell[j+1].avg_strength)
{
temp = cell[j] ;
cell[j] = cell[j+1];
cell[j+1] = temp;
}
}
}
}
double slide(struct Cell *cell, struct PSS *pss)//滑动相关检测
{
int i,j;
double max=0;//用于放置最大相关序列
double temp;//用于暂存当前序列
for(i=0; i<MAX_data/2 - MAX_PSS/2 + 1; i++)//i∈[0,n-m]
{
temp = 0;
for(j=0;j<MAX_PSS/2;j++)
{
temp = temp + pss->strength[j] * cell->strength[i+j];
}
if(temp>max)
{
max = temp;
}
return max;
}
return 0;
}
void IfConnect()//根据输入门限判断能否连接
{
int i;
int flag;//用于标记满足平均强度门限的小区
double strength_threshold;//定义平均强度门限
double correlation_threshold;//定义相关后最大强度门限
printf("\n请输入强度门限:\n");
scanf("%lf",&strength_threshold);
//判断是否满足平均强度门限
if(cell[0].avg_strength<strength_threshold)//最大值也低于门限
{
printf("\n无适合接入小区,驻留失败");
return;
}
printf("\n满足平均强度门限条件的小区有:\n");
for (i=0; i<data_N; i++)
{
if(cell[i].avg_strength>=strength_threshold)//如果满足门限条件打印相关信息
{
printf("ID:%s\b\b\b\b 信号平均强度:%lf\n", cell[i].ID, cell[i].avg_strength);
flag=i;
}
}
printf("\n请输入相关门限:\n");
scanf("%lf",&correlation_threshold);
//判断是否满足最大相关门限
for(i=0;i<=flag;i++)
{
if(cell[i].max_colleration[0]>correlation_threshold&&
cell[i].max_colleration[1]>correlation_threshold&&
cell[i].max_colleration[2]>correlation_threshold)
printf("ID:%s\b\b\b\b 当前小区满足接入条件,流程结束\n",cell[i].ID);
else
printf("ID:%s\b\b\b\b 当前小区无法接入,寻找下一小区\n",cell[i].ID);
}
}
int main()
{
int i,j;
ID_init();//初始化小区名称
printf("文件读取中...\n");
fileop_pss();
fileop_data();
sort();
printf("\n排序结果为:\n");
for(int i=0; i<data_N; i++)
{
printf("ID;%s\b\b\b\b信号平均强度为:%lf\n",cell[i].ID,cell[i].avg_strength);
}
printf("\nPSS与小区匹配结果:\n");
for(i=0;i<data_N;i++)//求实际信号与确定信号相关性序列最大值
{
for(j=0;j<PSS_N;j++)
{
cell[i].max_colleration[j] = slide(&cell[i],&pss[j]);//将滑动相关后的相关性最大值赋予小区结构体
printf("ID:%s\b\b\b\b 与 PSS%d 相关性序列最大值:%lf\n", cell[i].ID, j, cell[i].max_colleration[j]);
}
}
IfConnect();
}
四、调试
五、心得体会
六、 意见
七、附录
运行结果
第一个即为最合适接入的小区,只需对Ifconnect()函数中代码稍作修改即可实现找到最优解立马退出程序,这里为了便于直观理解,就将所有情况都打印出来