typedef翻译,datatype 在C语言中怎么使用 后便可以跟什么数据类型 datetype elem 什么意思
typedef翻译,datatype 在C语言中怎么使用 后便可以跟什么数据类型 datetype elem 什么意思详细介绍
本文目录一览: c语言基础 翻译英语
auto 自动
break 中断
case 分支情况
char 字符
const 常量
continue 继续
default 缺省的
extern 外部的
for for循环
goto 直接跳转到
regisrer 寄存器
return 返回
short 短整型
signed 有符号的
sizeof 取所占字节长度
static 静态
struct 结构
switch 分情况开关
typedef 类型定义
union 联合
unsigned 无符号
void 无类型
while 当...循环
不需要死记硬背的,如果是为了过二级只需要知道循环体,指针,数组和字符串的关键字,他们的使用方法,格式才是重要的
分留给第一个人吧!
偶说说过二级要注意全面的能力,扎实的功底,过硬的心理,关键是"循环体,指针,数组和字符串的关键字",没错!
但是,谁能保证这部分就拿到高分!
[一家之言,仅供参考!]
datatype 在C语言中怎么使用 后便可以跟什么数据类型 datetype elem 什么意思
DataType这个是数据类型,应该是自定义类型,你可以定义成任何一种你需要的类型,可以直接在这改了,也可以在前面加上
teypedef 系统类型(如int) DataType;
这就是自定义类型
已知的数据类型有int,float,double,,等等。这里的datetype单独来说是没有含义的。
数据结构定义后。才具有意义。
例:typedef int datetype。这里的datetype就相当于数据类型int。
datetype a;就相当于int a;
你这里的
datetype *elem
就是定义datetype类型的指针变量。至于datetype是什么类型,就看你的定义了。
例1;
typedef struct datetype
{
int a;
datetype *next;
}
例2 :
typedef int datetype;
typedef float datetype;
typedef char datetype;等等
帮我翻译一下这程序意思 具体点哦
赚点分真不容易
这是模拟堆栈基本操作
#include
//引用stdio头文件
#include
//引用stdlib头文件
#define OK 1 //定义OK为1(状态码)
#define ERROR 0 //定义ERROR为0(状态码)
#define OVERFLOW -2 //同上(状态码)
#define LISTINCREMENT 10 //如果堆栈满了自增加的内存空间
#define INFEASIBLE -1 //下面没用到, 空定义
#define STACK_INIT_SIZE 100 //初始化时初始化多大内存空间
#define STACKINCREMENT 10 //如果堆栈满了自增加的内存空间
typedef int SElemType; //定义SelemType为int类型, 也就是和int一样用, 如int x = 6和SelemType x = 6一样
typedef int Status; //同上
typedef int ElemType; //同上
typedef struct SqStack //定义SqStack结构体(一个模拟堆栈)
{
SElemType *base; //结构成员, int指针
SElemType *top; //结构成员, int指针
int stacksize; //结构成员, int数据表示堆栈大小
}SqStack;
SqStack S; //声明S
Status InitStack(); //定义InitStack函数(作用:初始化S所需内存大小和S的成员), 返回int表示状态(成功或失败)的上面定义过的状态码
Status Push(SElemType e); //定义Push函数(作用: 压栈), 返回int状态码, 参数int(输入参数)
Status Pop(SElemType *e); //定义Pop函数(作用: 出栈), 返回int状态码, 参数int指针(输出参数)
Status StackEmpty(); //定义Status函数(作用: 检查是否是空的), 返回int状态码
void main() //主函数(入口)
{
char *b="0123456789ABCDEF"; //定义b(char指针)
int n,N,M,L,e; //变量声明
SqStack S; //结构声明
InitStack(); //初始化堆栈
printf("请输入要转换的数字:");//提示输入
scanf("%d",&n); //将用户输入的数据保存到n变量
N=M=L=n; //N,M,L都等于n值
while(N) //N不等于0时循环
{
Push(N % 8); //N除8的余数压栈
N = N / 8; //N递减
}
printf("转换为八进制数为:"); //提示
while(!StackEmpty()) //当堆栈不为空时循环
{
Pop(&e); //从堆栈弹出一个值, 保存到e内(相应的堆栈内的"东西"会减一)
printf("%d",e); //打印e
}
printf("\n"); //打印换行
while(M) //M不为0时循环
{
Push(M % 2); //压栈M除2的余数, 下面的同上面解释
M = M / 2;
}
printf("转换为二进制数为:");
while(!StackEmpty())
{
Pop(&e);
printf("%d",e);
}
printf("\n");
while(L)
{
Push(L % 16);
L = L / 16;
}
printf("转换为十六进制数为:");
while(!StackEmpty())
{
Pop(&e);
printf("%c", b[e]); //打印第'e'个b里面的字符, 上面定义过b是"0123456789ABCDEF"的指针, 比如e等于2, 那么打印2, e等于14, 那么打印'E'
}
printf("\n");
getch(); //让'DOS'黑窗不要关闭, 停在那.
}
Status InitStack() //函数主体(上面声明, 现在实现)
{
//为S结构体的base成员开辟新的内存空间(空间大小为STACK_INIT_SIZE * sizeof(int))
S.base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
//如果malloc返回了失败
if(!S.base)
exit(OVERFLOW); //则以OVERFLOW的状态码退出(是退出程序, 不是函数)
S.top = S.base; //首尾相连表示内部还没有数据
S.stacksize=STACK_INIT_SIZE; //更改成员的值(表示堆栈大小)
return OK; //返回OK状态码
}
Status Pop(SElemType *e) //实现函数
{
if(S.top == S.base) //如果首尾相连, 表示里面没值, 所以不能pop出数据
return ERROR; //以ERROR状态码退出
*e = *--S.top; //S.top指针递减(长度sizeof(int))并将该地址的值赋给e的地址
return OK; //返回成功状态
}
Status Push(SElemType e) //实现函数
{
if(S.top - S.base >= S.stacksize) //如果堆栈满了
{
//那么就重新分配空间(增加空间, 增加大小为定义的LISTINCREMENT)
S.base = (ElemType *)realloc(S.base,(S.stacksize + LISTINCREMENT) * sizeof(ElemType));
//如果分配失败
if(!S.base)
//以OVERFLOW退出程序
exit(OVERFLOW);
S.top = S.base + S.stacksize; //表示无数据
S.stacksize += STACKINCREMENT; //重新声明本堆栈的大小
}
*S.top++ = e; //然后赋值(因为新空间可用了)
return OK; //返回OK
}
Status StackEmpty() //实现函数
{
if(S.top == S.base) //如果堆栈是空的
return OK; //返回OK
else
return ERROR; //返回不是
}
希望可以帮到你.
什么是Hash函数
hash函数 Hash,一般翻译做"散列",也有直接音译为"哈希"的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。
简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。
HASH主要用于信息安全领域中加密算法,他把一些不同长度的信息转化成杂乱的128位的编码里,叫做HASH值. 也可以说,hash就是找到一种数据内容和数据存放地址之间的映射关系
了解了hash基本定义,就不能不提到一些著名的hash算法,MD5 和 SHA1 可以说是目前应用最广泛的Hash算法,而它们都是以 MD4 为基础设计的。那么他们都是什么意思呢?
这里简单说一下:
1) MD4
MD4(RFC 1320)是 MIT 的 Ronald L. Rivest 在 1990 年设计的,MD 是 Message Digest 的缩写。它适用在32位字长的处理器上用高速软件实现--它是基于 32 位操作数的位操作来实现的。
2) MD5
MD5(RFC 1321)是 Rivest 于1991年对MD4的改进版本。它对输入仍以512位分组,其输出是4个32位字的级联,与 MD4 相同。MD5比MD4来得复杂,并且速度较之要慢一点,但更安全,在抗分析和抗差分方面表现更好
3) SHA1 及其他
SHA1是由NIST NSA设计为同DSA一起使用的,它对长度小于264的输入,产生长度为160bit的散列值,因此抗穷举(brute-force)性更好。SHA-1 设计时基于和MD4相同原理,并且模仿了该算法。
那么这些Hash算法到底有什么用呢?
Hash算法在信息安全方面的应用主要体现在以下的3个方面:
1) 文件校验
我们比较熟悉的校验算法有奇偶校验和CRC校验,这2种校验并没有抗数据篡改的能力,它们一定程度上能检测并纠正数据传输中的信道误码,但却不能防止对数据的恶意破坏。
MD5 Hash算法的"数字指纹"特性,使它成为目前应用最广泛的一种文件完整性校验和(Checksum)算法,不少Unix系统有提供计算md5 checksum的命令。
2) 数字签名
Hash 算法也是现代密码体系中的一个重要组成部分。由于非对称算法的运算速度较慢,所以在数字签名协议中,单向散列函数扮演了一个重要的角色。 对 Hash 值,又称"数字摘要"进行数字签名,在统计上可以认为与对文件本身进行数字签名是等效的。而且这样的协议还有其他的优点。
3) 鉴权协议
如下的鉴权协议又被称作"挑战--认证模式:在传输信道是可被侦听,但不可被篡改的情况下,这是一种简单而安全的方法。
hash函数在程序设计中的实现
// 说明:Hash函数(即散列函数)在程序设计中的应用目标 ------ 把一个对象通过某种转换机制对应到一个
// size_t类型(即unsigned long)的整型值。
// 而应用Hash函数的领域主要是 hash表(应用非常广)、密码等领域。
// 实现说明:
// (1)、这里使用了函数对象以及泛型技术,使得对所有类型的对象(关键字)都适用。
// (2)、常用类型有对应的偏特化,比如string、char*、各种整形等。
// (3)、版本可扩展,如果你对某种类型有特殊的需要,可以在后面实现专门化。
// (4)、以下实现一般放在头文件中,任何包含它的都可使用hash函数对象。
//------------------------------------实现------------------------------------------------
#include
using std::string;
inline size_t hash_str( const char* s )
{
unsigned long res = 0;
for ( ; *s; ++s )
res = 5 * res + *s;
return size_t(res);
}
template
struct hash
{
size_t operator () ( const Key& k ) const;
};
// 一般的对象,比如:vector< queue
>的对象,需要强制转化
template < class Key >
size_t hash
::operator () ( const Key& k ) const
{
size_t res = 0;
size_t len = sizeof( Key );
const char* p = reinterpret_cast
( &k );
while ( len-- )
{
res = (res<<1)^*p++;
}
return res;
}
// 偏特化
template<>
size_t hash< string >::operator () ( const string& str ) const
{
return hash_str( str.c_str() );
}
typedef char* PChar;
template<>
size_t hash
::operator () ( const PChar& s ) const
{
return hash_str(s);
}
typedef const char* PCChar;
template<>
size_t hash
::operator () ( const PCChar& s ) const
{
return hash_str(s);
}
template<> size_t hash
::operator () ( const char& x ) const { return x; }
template<> size_t hash
::operator () ( const unsigned char& x ) const { return x; }
template<> size_t hash
::operator () ( const signed char& x ) const { return x; }
template<> size_t hash
::operator () ( const short& x ) const { return x; }
template<> size_t hash
::operator () ( const unsigned short& x ) const { return x; }
template<> size_t hash
::operator () ( const int& x ) const { return x; }
template<> size_t hash
::operator () ( const unsigned int& x ) const { return x; }
template<> size_t hash
::operator () ( const long& x ) const { return x; }
template<> size_t hash
::operator () ( const unsigned long& x ) const { return x; }
// 使用说明:
//
// (1)、使用时首先由于是泛型,所以要加上关键字类型。
//
// (2)、其次要有一个函数对象,可以临时、局部、全局的,只要在作用域就可以。
//
// (3)、应用函数对象作用于对应类型的对象。
//----------------------- hash函数使用举例 -------------------------
#include
#include
#include
using namespace std;
int main()
{
vector
vstr(2);
vstr[0] = "sjw";
vstr[1] = "suninf";
hash
strhash; // 局部函数对象
cout << " Hash value: " << strhash( vstr[0] ) << endl;
cout << " Hash value: " << strhash( vstr[1] ) << endl;
cout << " Hash value: " << hash< vector
>() ( vstr ) << endl;
cout << " Hash value: " << hash
() ( 100 ) << endl; // hash
() 临时函数对象
return 0;
}
Hash函数:
Hash,一般翻译做"散列",也有直接音译为"哈希"的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。
算法用途:
HASH主要用于信息安全领域中加密算法,它把一些不同长度的信息转化成杂乱的128位的编码里,叫做HASH值. 也可以说,hash就是找到一种数据内容和数据存放地址之间的映射关系。Hash算法在信息安全方面的应用主要体现在以下的3个方面:
1)文件校验
我们比较熟悉的校验算法有奇偶校验和CRC校验,这2种校验并没有抗数据篡改的能力,它们一定程度上能检测并纠正数据传输中的信道误码,但却不能防止对数据的恶意破坏。
MD5 Hash算法的"数字指纹"特性,使它成为目前应用最广泛的一种文件完整性校验和(Checksum)算法,不少Unix系统有提供计算md5 checksum的命令。
2)数字签名
Hash 算法也是现代密码体系中的一个重要组成部分。由于非对称算法的运算速度较慢,所以在数字签名协议中,单向散列函数扮演了一个重要的角色。对 Hash 值,又称"数字摘要"进行数字签名,在统计上可以认为与对文件本身进行数字签名是等效的。而且这样的协议还有其他的优点。
3)鉴权协议
如下的鉴权协议又被称作"挑战--认证模式:在传输信道是可被侦听,但不可被篡改的情况下,这是一种简单而安全的方法。
Hash函数是把任意长度的输入(又叫做预映射pre-image)通过散列算法变换成固定长度的输出,该输出就是散列值。
这种转换是一种压缩映射,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来确定唯一的输入值。
Hash函数可以将一个数据转换为一个标志,这个标志和源数据的每一个字节都有十分紧密的关系。Hash算法还具有一个特点,就是很难找到逆向规律。
扩展资料:
常用Hash函数有:
1、直接寻址法。取关键字或关键字的某个线性函数值为散列地址。即H(key)=key或H(key) = a·key + b,其中a和b为常数(这种散列函数叫做自身函数)
2、数字分析法。分析一组数据,比如一组员工的出生年月日,这时我们发现出生年月日的前几位数字大体相同。
3、平方取中法。取关键字平方后的中间几位作为散列地址。
4、 折叠法。将关键字分割成位数相同的几部分,最后一部分位数可以不同,然后取这几部分的叠加和(去除进位)作为散列地址。
参考资料来源:百度百科-hash函数
Q.front=Q.rear=(Queueptr)malloc(sizeof(QNode)) 请帮我每一个字都仔细翻译一下好么 十分感谢
#include
using namespace std;
#define OK 1
#define ERROR 0
#define OVERFLOW -1
typedef int QElemType;
typedef int status;
typedef struct QNode{
QElemType data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct{
QueuePtr front;
QueuePtr rear;
}LinkQueue;
status InitQueue(LinkQueue &Q)
{
Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));
if(!Q.front) exit(OVERFLOW);
Q.front->next=NULL;
return OK;
}
status DestroyQueue(LinkQueue &Q)
{
while(Q.front)
{
Q.rear=Q.front->next;
free(Q.front);
Q.front=Q.rear;
}
return OK;
}
status EnQueue(LinkQueue &Q,QElemType e)
{
QueuePtr p;
p=(QueuePtr)malloc(sizeof(QNode));
if(!p) return OVERFLOW;
p->data=e;
p->next=NULL;
Q.rear->next=p;
Q.rear=p;
return OK;
}
status DeQueue(LinkQueue &Q,QElemType &e)
{
QueuePtr p;
if(Q.front==Q.rear) return ERROR;
p=Q.front->next;
e=p->data;
Q.front->next=p->next;
if(Q.rear==p) Q.front==Q.rear;
free(p);
return OK;
}
status QueueLength(LinkQueue Q,QElemType &i)
{
QueuePtr p;
i=0;
if(Q.front==Q.rear) return ERROR;
p=Q.front->next;
while(p!=NULL)
{
i++;
p=p->next;
}
return OK;
}
status GetHead(LinkQueue Q,QElemType &e)
{
QueuePtr p;
if(Q.front==Q.rear) return ERROR;
p=Q.front->next;
e=p->data;
return OK;
}
void QueueTraverse(LinkQueue Q)
{
QueuePtr p;
int e;
p=Q.front->next;
while(p!=NULL)
{
e=p->data;
cout<
<e<<
我可以帮助你,你先设置我最佳答案后,我百度Hii教你。你的串号我已经记下,采纳后我会帮你制作
QueuePtr Q.front=new QNode;//问题所在
改为
Q.front=new QNode;
这是C吗
这段代码 Q是个结构体 指的是队列
front是队列前端 rear是队列末端
Queueptr 是 queue pointer 队列指针
malloc:memory allocate 内存分配
sizeof:尺寸
QNode:队列节点
这段代码是在初始化队列 但是不应该这么写
让队列Q的前段和末端指向同一个节点
并给这个节点申请一个单位节点的内存
</e<
auto break case char const continue default do double else enum extern float for goto if int long r
auto 这个是自动的,在C语言里面基本不用,属于默认的。
break 这个是中断循环的,用这个来结束循环。
case 情况,与switch并用
char 字符
const 恒定的,或者是常量,用来定义一个不能改变的量
continue 继续,不再执行后面的语句,重新开始下一次循环。
default 默认的
do 就是做,与while连用的
double 双浮点
else 其他,与if连用
enum 枚举
extern 外部的
float 浮点
for 一直,循环用的
goto 跳转到
if 如果
int 整形
long 长
redister 寄存器
return 返回
short 短
signed 有符号的
sizeof 变量的字结束
static 静态的
struct 结构体
switch 开关,也算作一种循环
typedef 定义新的类型名
union 联合
unsigned 无符号的
void 空的,或者是不定的
volatile 易变的
while 当……的时候
bool 布尔型(只有真:非零,假: 零两种值)
imaginary 虚数
restrict 约束
complex 复数
inline 内联
auto自动
break 中断
case 条件
char字符
const常量
continue继续
default默认
do做
double双精度
else否则
enum枚举
extern 外部
float 浮点
for 根据
goto 跳转到
if 如果
int整型
long 长整型
register 寄存器
return返回
short短整型
signed
sizeof大小
static静态
struct结构体
switch 开关
typedef 类型定义
union 联合体
unsigned无符号
void 无
volatile
while当
数据结构
何谓数据结构
?
数据结构是在整个计算机科学与技术领域上广泛被使用的术语。它用来反映一个数据的内部构成,即一个数据由那些成分数据构成,以什么方式构成,呈什么结构。数据结构有逻辑上的数据结构和物理上的数据结构之分。逻辑上的数据结构反映成分数据之间的逻辑关系,而物理上的数据结构反映成分数据在计算机内部的存储安排。数据结构是数据存在的形式。 数据结构是信息的一种组织方式,其目的是为了提高算法的效率,它通常与一组算法的集合相对应,通过这组算法集合可以对数据结构中的数据进行某种操作。
?
数据结构主要研究什么?
?
数据结构作为一门学科主要研究数据的各种逻辑结构和存储结构,以及对数据的各种操作。因此,主要有三个方面的内容:数据的逻辑结构;数据的物理存储结构;对数据的操作(或算法)。通常,算法的
?
设计取决于数据的逻辑结构,算法的实现取决于数据的物理存储结构。
?
什么是数据结构?什么是逻辑结构和物理结构?
?
数据是指由有限的符号(比如,"0"和"1",具有其自己的结构、操作、和相应的语义)组成的元素的集合。结构是元素之间的关系的集合。通常来说,一个数据结构DS 可以表示为一个二元组:
?
DS=(D,S), //i.e., data-structure=(data-part,logic-structure-part) 这里D是数据元素的集合(或者是“结点”,可能还含有“数据项”或“数据域”),S是定义在D(或其他集合)上的关系的集合,S = { R | R : D×D×...},称之为元素的逻辑结构。 逻辑结构有四种基本类型:集合结构、线性结构、树状结构和网络结构。表和树是最常用的两种高效数据结构,许多高效的算法可以用这两种数据结构来设计实现。表是线性结构的(全序关系),树(偏序或层次关系)和图(局部有序(weak/local orders))是非线性结构。
?
数据结构的物理结构是指逻辑结构的存储镜像(image)。数据结构 DS 的物理结构 P对应于从 DS 的数据元素到存储区M(维护着逻辑结构S)的一个映射:
?
(PD,S) -- > M 存储器模型:一个存储器 M 是一系列固定大小的存储单元,每个单元 U 有一个唯一的地址 A(U),该地址被连续地编码。每个单元 U 有一个唯一的后继单元 U'=succ(U)。 P 的四种基本映射模型:顺序(sequential)、链接(linked)、索引(indexed)和散列(hashing)映射。
?
因此,我们至少可以得到4×4种可能的物理数据结构:
?
sequential (sets)
linked lists
indexed trees
hash graphs
?
(并不是所有的可能组合都合理)
?
??? 数据结构DS上的操作:所有的定义在DS上的操作在改变数据元素(节点)或节点的域时必须保持DS的逻辑和物理结构。
?
DS上的基本操作:任何其他对DS的高级操作都可以用这些基本操作来实现。最好将DS和他的所有基本操作看作一个整体——称之为模块。我们可以进一步将该模块抽象为数据类型(其中DS的存储结构被表示为私有成员,基本操作被表示为公共方法),称之为ADT。作为ADT,堆栈和队列都是一种特殊的表,他们拥有表的操作的子集。 对于DATs的高级操作可以被设计为(不封装的)算法,利用基本操作对DS进行处理。
?
好的和坏的DS:如果一个DS可以通过某种“线性规则”被转化为线性的DS(例如线性表),则称它为好的DS。好的DS通常对应于好的(高效的)算法。这是由计算机的计算能力决定的,因为计算机本质上只能存取逻辑连续的内存单元,因此如何没有线性化的结构逻辑上是不可计算的。比如对一个图进行操作,要访问图的所有结点,则必须按照某种顺序来依次访问所有节点(要形成一个偏序),必须通过某种方式将图固有的非线性结构转化为线性结构才能对图进行操作。
?
树是好的DS——它有非常简单而高效的线性化规则,因此可以利用树设计出许多非常高效的算法。树的实现和使用都很简单,但可以解决大量特殊的复杂问题,因此树是实际编程中最重要和最有用的一种数据结构。树的结构本质上有递归的性质——每一个叶节点可以被一棵子树所替代,反之亦然。实际上,每一种递归的结构都可以被转化为(或等价于)树形结构。
?
从机器语言到高级语言的抽象
?
我们知道,算法被定义为一个运算序列。这个运算序列中的所有运算定义在一类特定的数据模型上,并以解决一类特定问题为目标。这个运算序列应该具备下列四个特征。 有限性,即序列的项数有限,且每一运算项都可在有限的时间内完成;确定性,即序列的每一项运算都有明确的定义,无二义性;可以没有输入运算项,但一定要有输出运算项;可行性,即对于任意给定的合法的输入都能得到相应的正确的输出。这些特征可以用来判别一个确定的运算序列是否称得上是一个算法。 但是,我们现在的问题不是要判别一个确定的运算序列是否称得上是一个算法,而是要对一个己经称得上是算法的运算序列,回顾我们曾经如何用程序设计语言去表达它。
?
算法的程序表达,归根到底是算法要素的程序表达,因为一旦算法的每一项要素都用程序清楚地表达,整个算法的程序表达也就不成问题。
?
作为运算序列的算法,有三个要素。 作为运算序列中各种运算的运算对象和运算结果的数据;运算序列中的各种运算;运算序列中的控制转移。这三种要素依序分别简称为数据、运算和控制。 由于算法层出不穷,变化万千,其中的运算所作用的对象数据和所得到的结果数据名目繁多,不胜枚举。最简单最基本的有布尔值数据、字符数据、整数和实数数据等;稍复杂的有向量、矩阵、记录等数据;更复杂的有集合、树和图,还有声音、图形、图像等数据。 同样由于算法层出不穷,变化万千,其中运算的种类五花八门、多姿多彩。最基本最初等的有赋值运算、算术运算、逻辑运算和关系运算等;稍复杂的有算术表达式和逻辑表达式等;更复杂的有函数值计算、向量运算、矩阵运算、集合运算,以及表、栈、队列、树和图上的运算等:此外,还可能有以上列举的运算的复合和嵌套。 关于控制转移,相对单纯。在串行计算中,它只有顺序、分支、循环、递归和无条件转移等几种。
?
我们来回顾一下,自从计算机问世以来,算法的上述三要素的程序表达,经历过一个怎样的过程。
?
最早的程序设计语言是机器语言,即具体的计算机上的一个指令集。当时,要在计算机上运行的所有算法都必须直接用机器语言来表达,计算机才能接受。算法的运算序列包括运算对象和运算结果都必须转换为指令序列。其中的每一条指令都以编码(指令码和地址码)的形式出现。与算法语言表达的算法,相差十万八千里。对于没受过程序设计专门训练的人来说,一份程序恰似一份"天书",让人看了不知所云,可读性
?
极差。
?
用机器语言表达算法的运算、数据和控制十分繁杂琐碎,因为机器语言所提供的指令太初等、原始。机器语言只接受算术运算、按位逻辑运算和数的大小比较运算等。对于稍复杂的运算,都必须一一分解,直到到达最初等的运算才能用相应的指令替代之。机器语言能直接表达的数据只有最原始的位、字节、和字三种。算法中即使是最简单的数据如布尔值、字符、整数、和实数,也必须一一地映射到位、字节和字
中,还得一一分配它们的存储单元。对于算法中有结构的数据的表达则要麻烦得多。机器语言所提供的控制转移指令也只有无条件转移、条件转移、进入子程序和从子程序返回等最基本的几种。用它们来构造循环、形成分支、调用函数和过程得事先做许多的准备,还得靠许多的技巧。 直接用机器语言表达算法有许多缺点。
?
大量繁杂琐碎的细节牵制着程序员,使他们不可能有更多的时间和精力去从事创造性的劳动,执行对他们来说更为重要的任务。如确保程序的正确性、高效性。程序员既要驾驭程序设计的全局又要深入每一个局部直到实现的细节,即使智力超群的程序员也常常会顾此失彼,屡出差错,因而所编出的程序可靠性差,且开发周期长。 由于用机器语言进行程序设计的思维和表达方式与人们的习惯大相径庭,只有经过
较长时间职业训练的程序员才能胜任,使得程序设计曲高和寡。因为它的书面形式全是"密"码,所以可读性差,不便于交流与合作。因为它严重地依赖于具体的计算机,所以可移植性差,重用性差。这些弊端造成当时的计算机应用未能迅速得到推广。
?
克服上述缺点的出路在于程序设计语言的抽象,让它尽可能地接近于算法语言。 为此,人们首先注意到的是可读性和可移植性,因为它们相对地容易通过抽象而得到改善。于是,很快就出现汇编语言。这种语言对机器语言的抽象,首先表现在将机器语言的每一条指令符号化:指令码代之以记忆符号,地址码代之以符号地址,使得其含义显现在符号上而不再隐藏在编码中,可让人望"文"生义。其次表现在这种语言摆脱了具体计算机的限制,可在不同指令集的计算机上运行,只要该计算机配上汇编语言的一个汇编程序。这无疑是机器语言朝算法语言靠拢迈出的一步。但是,它离算法语言还太远,以致程序员还不能从分解算法的数据、运算和控制到汇编才能直接表达的指令等繁杂琐碎的事务中解脱出来。 到了50年代中期,出现程序设计的高级语言如Fortran,Algol60,以及后来的PL/l, Pascal等,算法的程序表达才产生一次大的飞跃。
?
诚然,算法最终要表达为具体计算机上的机器语言才能在该计算机上运行,得到所需要的结果。但汇编语言的实践启发人们,表达成机器语言不必一步到位,可以分两步走或者可以筑桥过河。即先表达成一种中介语言,然后转成机器语言。汇编语言作为一种中介语言,并没有获得很大成功,原因是它离算法语
?
言还太远。这便指引人们去设计一种尽量接近算法语言的规范语言,即所谓的高级语言,让程序员可以用它方便地表达算法,然后借助于规范的高级语言到规范的机器语言的"翻译",最终将算法表达为机器语言。而且,由于高级语言和机器语言都具有规范性,这里的"翻译"完全可以机械化地由计算机来完成,就像汇编语言被翻译成机器语言一样,只要计算机配上一个编译程序。 上述两步,前一步由程序员去完成,后一步可以由编译程序去完成。在规定清楚它们各自该做什么之后,这两步是完全独立的。它们各自该如何做互不相干。前一步要做的只是用高级语言正确地表达给定的算法,产生一个高级语言程序;后一步要做的只是将第一步得到的高级语言程序翻译成机器语言程序。至于程序员如何用高级语言表达算法和编译程序如何将高级语言表达的算法翻译成机器语言表达的算法,显然毫不相干。
?
处理从算法语言最终表达成机器语言这一复杂过程的上述思想方法就是一种抽象。汇编语言和高级语言的出现都是这种抽象的范例。 与汇编语言相比,高级语言的巨大成功在于它在数据、运算和控制三方
?
面的表达中引入许多接近算法语言的概念和工具,大大地提高抽象地表达算法的能力。 在运算方面,高级语言如Pascal,除允许原封不动地运用算法语言的四则运算、逻辑运算、关系运算、算术表达式、逻辑表达式外,还引入强有力的函数与过程的工具,并让用户自定义。这一工具的重要性不仅在于它精简了重复的程序文本段,而且在于它反映出程序的两级抽象。
?
在函数与过程调用级,人们只关心它能做什么,不必关心它如何做。只是到函数与过程的定义时,人们才给出如何做的细节。用过高级语言的读者都知道,一旦函数与过程的名称、参数和功能被规定清楚,那么,在程序中调用它们便与在程序的头部说明它们完全分开。你可以修改甚至更换函数体与过程体,而不影响它们的被调用。如果把函数与过程名看成是运算名,把参数看成是运算的对象或运算的结果,那么
?
,函数与过程的调用和初等运算的引用没有两样。利用函数和过程以及它们的复合或嵌套可以很自然地表达算法语言中任何复杂的运算。
?
在数据方面,高级语言如Pascal引人了数据类型的概念,即把所有的数据加以分类。每一个数据(包括表达式)或每一个数据变量都属于其中确定的一类。称这一类数据为一个数据类型。 因此,数据类型是数据或数据变量类属的说明,它指示该数据或数据变量可能取的值的全体。对于无结构的数据,高级语言如Pascal,除提供标准的基本数据类型--布尔型、字符型、整型和实型外,还提供用户可自定义的枚举类、子界类型和指针类型。这些类型(除指针外),其使用方式都顺应人们在算法语言中使用的习惯。对于有结构的数据,高级语言如Pascal,提供了数组、记录、有限制的集合和文件等四种标准的结构数据类型。其中,数组是科学计算中的向量、矩阵的抽象;记录是商业和管理中的记录的抽象;有限制的集合是数学中足够小的集合的势集的抽象;文件是诸如磁盘等外存储数据的抽象。
?
人们可以利用所提供的基本数据类型(包括标准的和自定义的),按数组、记录、有限制的集合和文件的构造规则构造有结构的数据。 此外,还允许用户利用标准的结构数据类型,通过复合或嵌套构造更复杂更高层的结构数据。这使得高级语言中的数据类型呈明显的分层。 高级语言中数据类型的分层是没有穷尽的,因而用它们可以表达算法语言中任何复杂层次的数据。 在控制方面,高级语言如Pascal,提供了表达算法控制转移的六种方式。
?
(1)缺省的顺序控制";"。
?
(2)条件(分支)控制:"if表达式(为真)then S1 else S2;" 。
?
(3)选择(情况)控制:
?
"Case 表达式 of
?
值1: S1
值2: S2
...
值n: Sn
end"
?
(4)循环控制:
?
"while 表达式(为真) do S;" 或
"repeat S until 表达式(为真);" 或
"for变量名:=初值 to/downto 终值do S;"
?
(5)函数和过程的调用,包括递归函数和递归过程的调用。
?
(6)无条件转移goto。
这六种表达方式不仅覆盖了算法语言中所有控制表达的要求,而且不再像机器语言或汇编语言那样原始、那样繁琐、那样隐晦,而是如上面所看到的,与自然语言的表达相差无几。 程序设计语言从机器语言到高级语言的抽象,带来的主要好处是: 高级语言接近算法语言,易学、易掌握,一般工程技术人员只要几周时间的培训就可以胜任程序员的工作;高级语言为程序员提供了结构化程序设计的环境和工具,使得设计出来的程序可读性好,可维护性强,可靠性高;高级语言远离机器语言,与具体的计算机硬件关系不大,因而所写出来的程序可移植性好,重用率高; 由于把繁杂琐碎的事务交给了编译程序去做,所以自动化程度高,开发周期短,且程、序员得到解脱,可以集中时间和精力去从事对于他们来说更为重要的创造性劳动,以提高、程序的质量。
?
数据结构、数据类型和抽象数据类型
?
数据结构、数据类型和抽象数据类型,这三个术语在字面上既不同又相近,反映出它们在含义上既有区别又有联系。
?
数据结构是在整个计算机科学与技术领域上广泛被使用的术语。它用来反映一个数据的内部构成,即一个数据由哪些成分数据构成,以什么方式构成,呈什么结构。数据结构有逻辑上的数据结构和物理上的数据结构之分。逻辑上的数据结构反映成分数据之间的逻辑关系,物理上的数据结构反映成分数据在计算机内的存储安排。数据结构是数据存在的形式。
?
数据是按照数据结构分类的,具有相同数据结构的数据属同一类。同一类数据的全体称为一个数据类型。在程序设计高级语言中,数据类型用来说明一个数据在数据分类中的归属。它是数据的一种属性。这个属性限定了该数据的变化范围。为了解题的需要,根据数据结构的种类,高级语言定义了一系列的数据类型。不同的高级语言所定义的数据类型不尽相同。Pascal语言所定义的数据类型的种类。
?
其中,简单数据类型对应于简单的数据结构;构造数据类型对应于复杂的数据结构;在复杂的数据结构里,允许成分数据本身具有复杂的数据结构,因而,构造数据类型允许复合嵌套;指针类型对应于数据结构中成分数据之间的关系,表面上属简单数据类型,实际上都指向复杂的成分数据即构造数据类型中的数据,因此这里没有把它划入简单数据类型,也没有划入构造数据类型,而单独划出一类。
?
数据结构反映数据内部的构成方式,它常常用一个结构图来描述:数据中的每一项成分数据被看作一个结点,并用方框或圆圈表示,成分数据之间的关系用相应的结点之间带箭号的连线表示。如果成分数据本身又有它自身的结构,则结构出现嵌套。这里嵌套还允许是递归的嵌套。
?
由于指针数据的引入,使构造各种复杂的数据结构成为可能。按数据结构中的成分数据之间的关系,数据结构有线性与非线性之分。在非线性数据结构中又有层次与网状之分。 由于数据类型是按照数据结构划分的,因此,一类数据结构对应着一种数据类型。数据类型按照该类型中的数据所呈现的结构也有线性与非线性之分,层次与网状之分。一个数据变量,在高级语言中的类型说明必须是读变量所具有的数据结构所对应的数据类型。最常用的数据结构是数组结构和记录结构。数组结构的特点是:
?
成分数据的个数固定,它们之间的逻辑关系由成分数据的序号(或叫数组的下标)来体现。这些成分数据按照序号的先后顺序一个挨一个地排列起来。每一个成分数据具有相同的结构(可以是简单结构,也可以是复杂结构),因而属于同一个数据类型(相应地是简单数据类型或构造数据类型)。这种同一的数据类型称为基类型。所有的成分数据被依序安排在一片连续的存储单元中。 概括起来,数组结构是一个线性的、均匀的、其成分数据可随机访问的结构。
?
由于这、种结构有这些良好的特性,所以最常被人们所采用。在高级语言中,与数组结构相对应的、数据类型是数组类型,即数组结构的数据变量必须说明为array [i] of T0 ,其中i是数组、结构的下标类型,而T0是数组结构的基类型。 记录结构是另一种常用的数据结构。它的特点是:与数组结构一样,成分数据的个数固定。但成分数据之间没有自然序,它们处于平等地位。每一个成分数据被称为一个域并赋予域名。不同的域有不同的域名。不同的域允许有不同的结构,因而允许属于不同的数据类型。与数组结构一样,它们可以随机访问,但访问的途径靠的是域名。在高级语言中记录结构对应的数据类型是记录类型。记录结构的数据的变量必须说明为记录类型。
?
抽象数据类型的含义在上一段已作了专门叙述。它可理解为数据类型的进一步抽象。即把数据类型和数据类型上的运算捆在一起,进行封装。引入抽象数据类型的目的是把数据类型的表示和数据类型上运算的实现与这些数据类型和运算在程序中的引用隔开,使它们相互独立。对于抽象数据类型的描述,除了必须描述它的数据结构外,还必须描述定义在它上面的运算(过程或函数)。抽象数据类型上定义的过程和函
数以该抽象数据类型的数据所应具有的数据结构为基础。
?
泛型设计和数据结构与算法
?
下面我想再说说关于泛型程序设计模型对于数据结构和算法方面的最新推动,泛型思想已经把数据结
?
构和算法方面的基本思想抽象到了一个前所未有的高度,现在有多种程序设计语言支持泛型设计,比如
ADA,C++,而且据说在JAVA的下一版本和C#中也将对泛型设计进行全面的支持。
?
先说说泛型设计的基本思想:泛型编程(generic programming,以下直接以GP称呼)是一种全新的程序设计思想,和OO,OB,PO这些为人所熟知的程序设计想法不同的是GP抽象度更高,基于GP设计的组件之间偶合度底,没有继承关系,所以其组件间的互交性和扩展性都非常高。我们都知道,任何算法都是作用在一种特定的数据结构上的,最简单的例子就是快速排序算法最根本的实现条件就是所排序的对象是存
贮在数组里面,因为快速排序就是因为要用到数组的随机存储特性,即可以在单位时间内交换远距离的对象,而不只是相临的两个对象,而如果用联表去存储对象,由于在联表中取得对象的时间是线性的既O[n],这样将使快速排序失去其快速的特点。也就是说,我们在设计一种算法的时候,我们总是先要考虑其应用的数据结构,比如数组查找,联表查找,树查找,图查找其核心都是查找,但因为作用的数据结构不同
?
将有多种不同的表现形式。数据结构和算法之间这样密切的关系一直是我们以前的认识。泛型设计的根本思想就是想把算法和其作用的数据结构分离,也就是说,我们设计算法的时候并不去考虑我们设计的算法将作用于何种数据结构之上。泛型设计的理想状态是一个查找算法将可以作用于数组,联表,树,图等各种数据结构之上,变成一个通用的,泛型的算法。这样的理想是不是很诱惑人?
?
泛型编程带来的是前所未有的弹性以及不会损失效率的抽象性,GP和OO不同,它不要求你通过额外的间接层来调用函数:它让你撰写完全一般化并可重复使用的算法,其效率与针对特定数据结构而设计的算法旗鼓相当。我们大家都知道数据结构在C++中可以用用户定义类型来表示,而C++中的模板技术就是以类型作为参数,那么我可以想象利用模板技术可以实现我们开始的GP思想,即一个模板函数可以对于各种传递进来的类型起作用,而这些类型就可以是我们定义的各种数据结构。
?
泛型算法抽离于特定类型和特定数据结构之外,使得其适应与尽可能的一般化类型,算法本身只是为了实现算法其需要表达的逻辑本质而不去被为各种数据结构的实现细节所干扰。这意味着一个泛型算法实际具有两部分。1,用来描叙算法本质逻辑的实际指令;2,正确指定其参数类型必须满足的性质的一组需求条件。到此,相信有不少人已经开始糊涂了,呵呵,不要紧。毕竟GP是一种抽象度非常高的程序设计思想,里面的核心就是抽象条件成为成为程序设计过程中的核心,从而取代了类型这在OO里面的核心地位,正是因为类型不在是我们考虑的重点,类型成为了抽象条件的外衣,所以我们称这样的程序思想为泛型思想------把类型泛化。
满意请采纳。
如何把这个C语言文件转化为hex文件?
可以配置他是否显示头文件,工程目录树是怎么组织的等等信息
10 bak就是对工程文件的备份.LST 列表文件,被定位到单片机哪个地址里了,例如你有哪些代码段,显示程序汇编后的汇编代码等等,显示符号表.OBJ 这个是编译器编译后的最终文件:
1 test1 无后缀文件,没有调用哪个函数,里面都是连接器的连接信息,没啥说的
呀.hex 这个文件可以直接下载到单片机里,然后提取变成HEX
6 DBK PWI 是test1,共同说明这你工程里有哪些文件,不用说了吧
12 lnp算是连接日志,用来给连接器连接和定位,工程代码总大小,都是多大,就是给你一个后悔修改的机会
11 asm 就是汇编文件了,用来和KEIL联合仿真
4 test1我把我能认识的说说,在你工程选项里,不能打开
2 test1、数据段,他就是从无后缀文件test1里提取的,可以打开
5 test1,可以用文本编辑器打开看看,去掉了调试信息,可以打开
3 test1,比如覆盖分析,这个文件很重要.DSN,这个是另外一个软件PROTUES软件的工程文件,这个是最终生成的文件,告诉你连接器连接了哪些OBJ等,没啥说的,出了大问题必须打开它,文件有没有被编译过,混合编程时查看函数段名等,这就属于PROTUES软件了,内存使用总大小等
9 uvopt和uvproj都是keil工程文件,只要有这个文件KEIL就可以软件仿真.DSN的附带文件,可以打开,不在详述
7 plg keil 的编译日志文件,里面是电路图,哪个函数调用了哪个函数.M51文件,可以打开看看
8 test1,连接器对OBJ连接后就变成了无后缀文件,这个文件是某个C文件编译后的文件,我好像马马虎虎勉强都认识啦
说的不够详细
解决方案2:
全部翻译就是:
生成(或构建)目标 ‘目标1’
正在汇编main.asm...
正在连接...
程序大小:内部直接寻址data存储区使用了8字节,外部xdata存储区使用0字节,代码大小15字节
正在从“test”创建hex格式的文件...
工程“test” - 0 个错误,0个警告
51单片机RAM区有4种:data、bdata、idata和xdata
51单片机ROM区一种:code
ROM就是 read only memory ,只读存储器,用来存程序的,掉电不会丢失数据
RAM就是 random access memory 随机访问存储器,是内存,掉电后数据全部丢失
typedef在c#中如何实现
enumTerminalType myTerminalType = (enumTerminalType)Enum.Parse(typeof(enumTerminalType),"类型1",true);
像这样,就是将字符串"类型1"转成对应的枚举
如下
C# code
using MyInt = System.Int32;//为Int32定义别名
C# 中使用 struct 结构 来实现上述的功能
这句话不用翻译吧 ,typedef 只是把前面复杂的模板定义变得简单点,书写时方便易读,你只要在以后的代码里把CDArray 改换成CArray<>,写自己的C#代码就行了