摘 要
《数据结构》课程是计算机专业中的一门专业基础必修课,但凡设置计算机专业的学校都开设此课程。该课程主要介绍和研究数据在计算机中的存储和处理方法,旨在培养学生分析数据、组织数据的能力,告诉学生如何编写效率高、结构好的程序。数据结构的研究不仅涉及到计算机硬件(特别是编码理论、存储装置和存取方法等)的研究范围,而且和计算机软件的研究有着更密切的关系,无论是编译程序还是操作系统,都涉及到数据元素在存储器中的分配问题。在研究信息检索时也必须考虑如何组织数据,以便查找和存取数据元素更为方便。因此,可以认为《数据结构》是介于数学、计算机硬件和计算机软件三者之间的一门核心课程,在计算机科学中,数据结构不仅是一般程序设计(特别是非数值计算的程序设计)的基础,而且是设计和实现编译程序、操作系统、数据系统及其他系统程序和大型应用程序的重要基础。《数据结构》课程的前导课程有:计算机基础、高等数学、一门程序设计语言(如C语言、PASCAL语言、C++语言、JAVA语言等)、微型计算机原理等,后续课程有操作系统、计算机网络技术、组网工程、JAVA程序设计、单片机原理与应用等。
通过对文本串进行加密与解密的研究,可以对这一门课程有了更深一步的认识,对一些细节语法有了更新、更深刻的理解。
关键词:文本串 加密 解密 C++
第一章 绪 论
内容:一个文本串可用事先给定的字母映射表进行加密。例如:设字母映射
表为:
abcdefghIjklmnopqrstuvwxyz
ngzqtcobmuhelkpdawxfyIvrsj
则字符串“encrypt”被加密为“tkzwsdf”。编写一个程序,将输入的文本
串加密后输出,然后进行解密并输出。
1.2.1
cin是C++编程语言中的标准输入流对象,即istream类的对象。cin主要用于从标准输入读取数据,这里的标准输入,指的是终端的键盘。cin读取数据是
从缓冲区中获取数据,缓冲区为空时,cin的成员函数会阻塞等待数据的到来,一旦缓冲区中有数据,就触发cin的成员函数去读取数据。cin的常用读取方法:
使用cin从标准输入读取数据时,通常用到的方法有cin>>, cin.get, cin.getline。其中cin>>的用法是cin可以连续从键盘读取想要的数据,以空格、tab或换行作为分隔符。
1.2.2
cout<<i<<endI就是输出i后换行,cout<<endl表示输出换行的意思。cout用于在计算机屏幕上显示信息,是C++中iostream类型的对象,C++的输出是用“流"(stream)的方式实现的,流运算符的定义等信息是存放在C++的输入输出流库中的,因此如果在程序中使用cout和流运算符,就必须使用预处理命令把头文件stream包含到本文件中。即< iostream>库,该库定义的名字都在命名空间std中,所以cout全称是std::cout。cout语句的一般格式为:cout<<表达式1<<表达式.....<<表达式n;在定义流对象时,系统会在内存中开辟一-段缓冲区,用来暂存输入输出流的数据。在执行cout语句时,先把插入的数据顺序存放在输出缓冲区中,直到输出缓冲区满或遇到cout语句中的endl(或\n' ,ends,flush)为止,此时将缓冲区中已有的数据一-起输出,并清空缓冲区。输出流中的数据在系统默认的设备(一般为显示器)输出。
1.2.3
计算机上的非数值处理的对象大部分是字符串数据,字符串一 般简称为串。串是一种特殊的线性表,其特殊性体现在数据元素是一一个字符, 也就是说,串是一种内容受限的线性表。由于现今使用的计算机硬件结构是面向数值计算的需要而设计的,在处理字符串数据时比处理整数和浮点数要复杂得多。而且,在不同类型的应用中,所处理的字符串具有不同的特点,要有效地实现字符串的处理,就必须根据具体情况使用合适的存储结构。
类似于线性表的顺序在储结构。用一组地址连续的在储单 元存储串值的字符序列。按照预定义的大小,为每个定义的串变量分配一个固定长度的存储区, 这种定义方式是静态的,在编译时刻就确定了串空间的大小。
1.2.4
if语句是指编程语言(包括c语言、C++、C#、java、VB、汇编语言等)中用来判定所给定的条件是否满足,根据判定的结果(真或假)决定执行给出的两种操作之一。if的返回值为真或假,可以用bool型变量进行存储,占用一字节。
while是计算机的一种基本循环模式。当满足条件时进入循环,进入循环后,当条件不满足时,跳出循环。while语句的一般表达式为:while(表达式){循环体}。
for语句是C语言所提供的功能更强, 使用更广泛的一种循环语句。其般形式为:for(表达式1;表达式2;表达3)语句:表达式1通常用来给循环变 量赋初值,一般是赋值表达式。 也允许在for语句外给循坏变量赋初值,此时可以省略该表达式。表达式2通常是循环条件,一 般为关系表达式或逻辑表达式。表达式3通常可用来修改循环变量的值,一 般 是赋值语句。
这三个表达式都可以是逗号表达式,即每个表达式都可由多个表达式组成。三个表达式都是任选项,都可以省略。一般形式中的“语句”即为循环体语句。for语句的语义是:
1.首先计算表达式1的值。
2.再计算表达式2的值,若值为真非0)则执行循环体一次,否则跳出循环。
3.然后再计算表达式3的值,转回第2步重复执行。在整个for循环过程中,表达式1只计算一次,表达式2和表达式,3则可能计算多次。循环体可能多次执行,也可能一次都不执行。
第二章 课设实现过程
加密:改变原有信息数据。
解密:得到原有的信息数据。
Microsoft Visual C++,(简称Visual C++、MSVC、VC++或VC)是Microsoft公司推出的以C++语言为基础的开发Windows环境程序,面向对象的可视化集成编程系统。它不但具有程序框架自动生成、灵活方便的类管理、代码编写和界面设计集成交互操作、可开发多种程序等优点,而且通过的设置就可使其生成的程序框架支持数据库接口、OLE2.0,WinSock网络。
Microsoft Visual C++ 6.0,简称VC6.0,是微软于1998年推出的一款C++编译器,集成了MFC 6.0,包含标准版(Standard Edition)、专业版(Professional Edition)与企业版(Enterprise Edition)。如今仍用于维护旧的项目。(但是,这个版本在Windows XP下运行会出现问题,尤其是在调试模式的情况下(例如:静态变量的值并不会显示)。这个调试问题可以通过打一个叫“Visual C++ 6.0 Processor Pack”的补丁来解决。)
Microsoft Visual C++ 6.0对windows7和windows8的兼容性较差。在Windows7使用VC6.0只需要忽略兼容性提示即可正常使用,但是在Windows8(含Windows8.1)使用VC6.0则需要改原MSDEV.EXE文件名并改兼容性才能正常使用。在Windows10的第一个版本也可以正常使用VC6.0,但Windows10系统升级更新后中文版VC6.0无法正常使用,提示“0xc0000142”的错误,需要将原MSDEV.EXE文件替换为英文版或者汉化版才能正常使用(该版本在Windows8(含Windows8.1)照样需要改原MSDEV.EXE文件名并改兼容性才能正常使用。)。
2.2.3 算法
生成串:将一个字符串常量cstr(以'\0'字符标识结尾)赋给顺序串s,即生成一个其值等于cstr的串,算法如下:
void StrAssign(SqString &s,char cstr[]) //s为引用型参数
{
int i;
for (i=0;cstr[i]!='\0';i++)
s.data[i]=cstr[i];
s.length=i;
}
2.2.1 概要设计
2.2.2 详要设计
方法一
1.首先运用串的存储结构相关知识,给文本串w和k分配一个固定长度为100的存储区
#include<iostream>
#include<string>
using namespace std;
char w[100] = "abcdefghijklmnopqrstuvwxyz";//定义一个字符数组w
char k[100] = "ngzqtcobmuhelkpdawxfyivrsj";
- 程序运行后,要先输入要进行操作的串,这时面临两种操作,输入1加密,输入2解密。我们用if语句来实现操作。
当输入的1时,我们要先调用String类的方法输出串的长度,然后用串s中的字符与串w中的字符匹配,当相等时,输出串w字符的位置j,然后输出串k[j]的字符,重复操作直到得到的串长度为n,这时完成加密操作,我们用for语句实现这种循环操作。
当输入的是2时,我们要先调用String类的方法输出串的长度,然后用串s中的字符与串k中的字符匹配,当相等时,输出串k字符的位置j,然后输出串w[j]的字符,重复操作直到得到的串长度为n,这时完成解密操作,我们用for语句实现这种循环操作。
int main()
{
while (1)
{
string s;
cout<<"输入字符串"<<endl;
cin>>s;
int m;
cout<<"输入1加密,输入2为解密"<<endl;
cin>>m;
if(m==1)
{
cout<<"加密串为"<<endl;
int n=s.length();//调用String类的方法输出字符串的长度
for(int i=0;i<n;i++)
{
for(int j=0;j<26;j++)
{
if(s[i]==w[j])
{
cout<<k[j];
}
}
}
cout<<endl;
}
if(m==2)
{
cout<<"解密串为"<<endl;
int n=s.length();
for(int i=0;i<n;i++)
{
for(int j=0;j<26;j++)
{
if(s[i]==k[j])
{
cout<<w[j];
}
}
}
cout<<endl;
}
}
return 0;
}
方法二
1.为串分配一个最大长度为100的存储区
#include <stdio.h>
#include <String>
#define MaxSize 100
typedef struct
{
char data[MaxSize] ;
int length;
}SqString;
2.输入与输出串
void StrAssign(SqString &s,char cstr[]) //s为引用型参数
{
int i;
for (i=0;cstr[i]!='\0';i++)
s.data[i]=cstr[i];
s.length=i;
}
void DispStr(SqString s)
{
int i;
if (s.length>0)
{
for(i=0;i<s.length;i++)
printf("%c",s.data[i]);
printf("\n");
}
}
3.在A中找p.data[i],返回位置j ,将B[j]中的数据赋值给串q,我们用if语句与for循环语句实现操作,然后输出q,即得到要求的加密串。.在B中找q.data[i],返回位置j ,将A[j]中的数据赋值给串p,同时用if语句与for循环语句实现操作,然后输出p,即得到要求的解密串。
SqString EnCrypt(SqString p,SqString A,SqString B) //加密,p是需要加密的串,A是初始串,B是映射串
{
int i=0,j;
SqString q; //加密后的串
while(i<p.length)
{
for(j=0;p.data[i]!=A.data[j]&& j < A.length;j++); //在A中找p.data[i],返回位置j
if(j>=A.length) //A串中未找到p.data[i]
q.data[i] = p.data[i];
else //A串中找到p.data[i]
q.data[i] = B.data[j];
i++;
}
q.length = p.length;
return q;
}
SqString UnEnCrypt(SqString q,SqString A,SqString B) //解密,q是已经加密的串,A是初始串,B是映射串
{
int i=0,j;
SqString p; //解密后的串
while(i<q.length)
{
for(j=0;q.data[i]!=B.data[j]&& j < B.length;j++); //在B中找p.data[i],返回位置j
if(j>=B.length) //B串中未找到q.data[i]
p.data[i] = q.data[i];
else //B串中找到q.data[i]
p.data[i] = A.data[j];
i++;
}
p.length = q.length;
return p;
}
4.将要求的加密与解密串呈现出来
int main(int argc, char** argv) {
char strA[] = "abcdefghijklmnopqrstuvwxyz";
char strB[] = "ngzqtcobmuhelkpdawxfyivrsj";
SqString A;
SqString B;
StrAssign(A,strA);
StrAssign(B,strB);
SqString p,q;
char str[100];
printf("输入原文串:");
gets(str);
StrAssign(p,str);
printf("加密解密如下:\n");
printf(" 原文串:");
DispStr(p);
q=EnCrypt(p,A,B);
printf(" 加密串:");
DispStr(q);
p=UnEnCrypt(q,A,B);
printf(" 解密串:");
DispStr(p);
return 0;
}
完整代码
#include<iostream>
#include<string>
using namespace std;
char w[100] = "abcdefghijklmnopqrstuvwxyz";
char k[100] = "ngzqtcobmuhelkpdawxfyivrsj";
int main()
{
while (1)
{
string s;
cout<<"输入字符串"<<endl;
cin>>s;
int m;
cout<<"输入1加密,输入2为解密"<<endl;
cin>>m;
if(m==1)
{
cout<<"加密串为"<<endl;
int n=s.length();
for(int i=0;i<n;i++)
{
for(int j=0;j<26;j++)
{
if(s[i]==w[j])
{
cout<<k[j];
}
}
}
cout<<endl;
}
if(m==2)
{
cout<<"解密串为"<<endl;
int n=s.length();
for(int i=0;i<n;i++)
{
for(int j=0;j<26;j++)
{
if(s[i]==k[j])
{
cout<<w[j];
}
}
}
cout<<endl;
}
}
return 0;
}
完整代码
#include <stdio.h>
#include <String>
#define MaxSize 100
typedef struct
{
char data[MaxSize] ;
int length;
}SqString;
void StrAssign(SqString &s,char cstr[]) //s为引用型参数
{
int i;
for (i=0;cstr[i]!='\0';i++)
s.data[i]=cstr[i];
s.length=i;
}
void DispStr(SqString s)
{
int i;
if (s.length>0)
{
for(i=0;i<s.length;i++)
printf("%c",s.data[i]);
printf("\n");
}
}
SqString EnCrypt(SqString p,SqString A,SqString B) //加密,p是需要加密的串,A是初始串,B是映射串
{
int i=0,j;
SqString q; //加密后的串
while(i<p.length)
{
for(j=0;p.data[i]!=A.data[j]&& j < A.length;j++); //在A中找p.data[i],返回位置j
if(j>=A.length) //A串中未找到p.data[i]
q.data[i] = p.data[i];
else //A串中找到p.data[i]
q.data[i] = B.data[j];
i++;
}
q.length = p.length;
return q;
}
SqString UnEnCrypt(SqString q,SqString A,SqString B) //解密,q是已经加密的串,A是初始串,B是映射串
{
int i=0,j;
SqString p; //解密后的串
while(i<q.length)
{
for(j=0;q.data[i]!=B.data[j]&& j < B.length;j++); //在B中找p.data[i],返回位置j
if(j>=B.length) //B串中未找到q.data[i]
p.data[i] = q.data[i];
else //B串中找到q.data[i]
p.data[i] = A.data[j];
i++;
}
p.length = q.length;
return p;
}
int main(int argc, char** argv) {
char strA[] = "abcdefghijklmnopqrstuvwxyz";
char strB[] = "ngzqtcobmuhelkpdawxfyivrsj";
SqString A;
SqString B;
StrAssign(A,strA);//生成一个其值等于strA的串A
StrAssign(B,strB);//生成一个其值等于strB的串B
SqString p,q;
char str[100];//存储串的一维数组
printf("输入原文串:");
gets(str);
StrAssign(p,str);
printf("加密解密如下:\n");
printf(" 原文串:");
DispStr(p);
q=EnCrypt(p,A,B);
printf(" 加密串:");
DispStr(q);
p=UnEnCrypt(q,A,B);
printf(" 解密串:");
DispStr(p);
return 0;
}