目录

一、问题分析

二、总体设计

三、详细设计

1.数据结构:

2.功能实现:

3.算法及思路:

四、个性功能介绍

1.Beep报警功能:

2.用户交互菜单:

3.输入处理:

五、实现部分

1.字符串赋值(StrAssign)

2.计算nextval数组(NextVal)

3.KMP字符串匹配(KMP)

4.报警函数(Beep)

5.DNA检测函数(DNA)

6.主函数(main)

六、程序运行结果

七、课程设计小结

八、附录:课设源码


一、问题分析

      本课题的内容是关于病毒感染检测即DNA序列匹配的问题,具体是通过实现KMP(Knuth-Morris-Pratt)算法来检测一个人的DNA序列中是否包含某种病毒的DNA序列。从需求上来说,最终需要完成的功能是:输入一个人的DNA序列和一种病毒的DNA序列,通过KMP字符串匹配算法判断人的DNA序列中是否包含病毒的DNA序列,并给出相应的提示信息。如果包含,则提示用户已感染病毒;如果不包含,则提示用户未感染病毒并提醒注意防护。

二、总体设计

1.输入模块:负责接收用户输入的人DNA序列和病毒DNA序列。

2.处理模块:使用KMP算法进行字符串匹配。

3.输出模块:根据匹配结果输出相应的信息,并在匹配成功时触发报警。

4.功能设计:

用户界面:提供一个简单的菜单,允许用户选择开始运行、再次运行或退出程序。

字符串处理:实现字符串的赋值、KMP算法以及用于KMP算法的nextval表计算。

报警功能:在检测到病毒感染时,通过蜂鸣器声音提示用户

5.流程图:

三、详细设计

1.数据结构:

SString:用于存储字符串及其长度,包含一个字符数组str和一个整数length。

2.功能实现:

StrAssign:将输入的字符数组赋值给SString结构体的字符数组,并计算长度。

NextVal:计算KMP算法中需要的nextval表,用于优化匹配过程。

KMP:实现KMP字符串匹配算法,返回匹配成功的位置或0(匹配失败)。

Beep:实现报警功能,通过蜂鸣器声音提示用户。

3.算法及思路:

KMP算法:通过预处理模式串(病毒DNA序列)生成nextval表,在匹配过程中利用nextval表跳过不必要的比较,从而提高匹配效率。

报警功能:使用Windows API函数Beep和Sleep实现蜂鸣器声音,并通过_kbhit和_getch函数检测用户是否按下了回车键以停止报警。

四、个性功能介绍

1.Beep报警功能:

       当检测到病毒DNA时,系统会发出报警声,并提示用户按回车键停止报警。这一功能通过Beep函数实现,使用了Windows API中的Beep函数和Sleep函数来控制报警声的频率和持续时间。

2.用户交互菜单:

       系统提供了一个简单的用户交互菜单,用户可以通过输入数字来选择是否运行检测或退出程序。这一功能通过main函数中的循环和条件判断实现,提高了系统的灵活性和易用性。

3.输入处理:

       在读取用户输入的DNA序列时,系统使用了fgets函数来替代gets函数,以避免潜在的缓冲区溢出问题。同时,系统还通过strcspn函数去除了输入字符串中的换行符,确保字符串的正确处理。

五、实现部分

1.字符串赋值(StrAssign)

功能:将C风格的字符串(const char* chars)赋值给自定义的字符串结构(SString)。

实现:遍历输入的字符串,将其字符逐个复制到SString的str数组中,并设置字符串长度length。

2.计算nextval数组(NextVal)

功能:为KMP算法生成必要的nextval数组,用于在匹配失败时快速跳过不必要的比较。

实现:基于KMP算法的原理,通过迭代计算每个位置的nextval值,这些值表示在匹配失败时应该回退到的位置。

3.KMP字符串匹配(KMP)

功能:使用KMP算法在文本字符串(S)中搜索模式字符串(T)。

实现:利用nextval数组,在匹配失败时快速回退到正确的位置,继续匹配过程。如果找到匹配,返回匹配起始位置;否则返回0。

4.报警函数(Beep)

功能:在检测到病毒感染时发出报警声,直到用户按下回车键停止。

实现:使用Windows API的Beep函数发出声音,使用Sleep函数控制声音间隔,使用_kbhit和_getch函数检测用户输入。

5.DNA检测函数(DNA)

功能:获取用户输入的人DNA序列和病毒DNA序列,使用KMP算法进行匹配,并根据匹配结果输出相应信息。

实现:使用fgets函数获取用户输入,注意处理换行符。调用StrAssign函数将输入转换为SString结构,然后调用KMP函数进行匹配。根据匹配结果,输出未感染或感染的信息,并在感染时调用Beep函数发出报警。

6.主函数(main)

功能:提供用户交互界面,允许用户选择开始运行、再次运行或退出程序。

实现:使用while循环不断获取用户输入,根据输入调用DNA函数或退出程序。注意使用getchar函数清除输入缓冲区中的换行符,以避免影响后续输入。

六、程序运行结果

开始运行:

输入:1

输入人的DNA序列:123456789

输入病毒的DNA序列:456

此时显示

“你已感染病毒,病毒DNA在主DNA的位置为:4”

同时电脑开始发出报警的蜂鸣声

点击回车键停止报警

再次返回主菜单

输入2继续运行

输入人的DNA序列:asdfghjkl

输入病毒的DNA序列:abc

显示

“恭喜你,你没有感染病毒!请注意防护。”

并再次返回主菜单

输入:0

退出程序

七、课程设计小结

       本次课程设计是一次非常宝贵的学习和实践机会。在整个过程中,我深刻体会到了理论与实践相结合的重要性,也收获了许多宝贵的经验和知识。

       在课程设计的初期,我首先对所学知识进行了系统的回顾和整理,明确了设计的目标和要求。通过查阅相关资料和文献,我对设计内容有了更深入的了解,为后续的设计工作打下了坚实的基础。

       在设计过程中,我遇到了不少挑战和困难。但通过不断尝试和修改,我不仅掌握了更多的设计技巧和方法,还培养了解决问题的能力。

       在本次课设中,我深入学习到了深入理解字符串处理,通过实现串的赋值(StrAssign函数)和字符串匹配算法(KMP算法),加深了对字符串处理和数据结构(如结构体SString的使用)的理解。

       同时掌握了KMP算法,成功实现了KMP算法,包括计算nextval数组和进行字符串匹配。这一过程中,不仅理解了KMP算法的原理,还学会了如何在实际编程中应用该算法。

       还增强编程实践能力,通过编写完整的程序,包括用户输入处理、函数调用和结果输出等,增强了编程实践能力和代码组织能力。

       了解错误处理和用户交互,在程序中加入了错误处理和用户交互功能,如处理无效输入和提示用户输入等,提高了程序的健壮性和用户体验。

       总的来说,这次课程设计不仅提升了我的专业技能和实践能力,还让我更加清晰地认识到了自己的优势和不足。我相信在未来的学习和工作中,我会继续努力,不断进步,为实现自己的目标和梦想而奋斗。同时,我非常感谢老师的指导和帮助,让我能够顺利完成这次课程设计。

八、附录:课设源码

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <iostream>

#include <windows.h>

#include <conio.h>



using namespace std;



#define ERROR 0

#define OK 1

#define OVERFLOW -2

#define MAX 50



typedef int Status;



typedef struct

{

    char str[MAX + 1];

    int length;

} SString;



Status StrAssign(SString& S, const char* chars)

{

    int l = strlen(chars);

    for (int i = 0; i < l; i++)

        S.str[i] = chars[i];

    S.str[l] = '\0';

    S.length = l;

    return OK;

}



// 计算KMP算法中需要的nextval数组

void NextVal(const SString& T, int nextval[])

{

    int m = T.length;

    int k = -1;

    nextval[0] = -1;  //nextval[0]赋值为-1

    for (int j = 1; j < m; ++j)  // j为数组上标从1开始

    {

        while (k >= 0 && T.str[k + 1] != T.str[j])

            k = nextval[k];

        if (T.str[k + 1] == T.str[j])

            ++k;

        nextval[j] = (T.str[k + 1] == T.str[j] ? nextval[j] : k);

    }

}



// 实现KMP字符串匹配算法

int KMP(const SString& S, const SString& T)

{

    int nextval[MAX];

    NextVal(T, nextval);



    int i = 0, j = 0;

    while (i < S.length)

    {

        if (j == -1 || S.str[i] == T.str[j])

        {

            ++i;

            ++j;

        }

        else

        {

            j = nextval[j];

        }

        if (j == T.length)

        {

            return i - j + 1; // 匹配成功,返回起始位置(从1开始计数)

        }

    }

    return 0; // 匹配失败

}



// 防止有人感染后瞒报,设置报警器,字符串匹配成功后自动报警

int Beep() {

    int Beeping = 3;

    printf("按回车键停止报警:\n ");

    while (Beeping)

    {

        Beep(750, 300);

        Sleep(1000);

        // 检查是否有键盘输入(不阻塞)

        if (_kbhit())

        {

            char ch = _getch();

            if (ch == '\r')  // 检查是否是回车键(ASCII码为13,即\r)

            {

                Beeping = 0;

            }

        }

    }

    printf("报警已关闭!\n");

    return 0;

}



void DNA(void)

{

    SString S, T;

    char chars[MAX + 2];

    printf("\n请输入人的DNA序列: ");

    fgets(chars, MAX + 2, stdin);  // 使用fgets代替gets_s,注意处理换行符

    chars[strcspn(chars, "\n")] = 0;  // 去除换行符

    StrAssign(S, chars);

    printf("请输入病毒的DNA序列: ");

    fgets(chars, MAX + 2, stdin);

    chars[strcspn(chars, "\n")] = 0;

    StrAssign(T, chars);



    int position = KMP(S, T);

    if (position == 0)

    {

        printf("恭喜你,你没有感染病毒!请注意防护。\n");

    }

    else

    {

        printf("你已感染病毒,病毒DNA在主DNA中的位置为: %d\n", position);

        printf("你已感染病毒,请配合工作人员进行隔离和治疗!\n");

        Beep();

    }

}



int main()

{

    int choice;

    printf("————————病毒感染检测————————\n");

    printf("输入1开始运行\n");

    printf("输入2再次运行\n");

    printf("输入0退出运行\n");

    printf("请输入:");



    while (1)

    {

        scanf_s("%d", &choice);

        getchar(); // 清除输入缓冲区中的换行符



        if (choice == 0)

        {

            printf("程序退出。\n");

            break;

        }

        else if (choice == 1 || choice == 2)

        {

            DNA();

        }

        else

        {

            printf("无效输入,请重新输入。\n");

        }



        printf("\n————————病毒感染检测————————\n");

        printf("输入1开始运行\n");

        printf("输入2再次运行\n");

        printf("输入0退出运行\n");

        printf("请输入:");

    }

    return 0;

}

更多推荐