|||
//---------------------------------------------------------------------------- |
// 标题: 曼彻斯特和差分曼彻斯特编码的实现 |
// 分析:曼彻斯特编码是将每个码元的中央实现跳变,具体的码字表示为: |
// 1->10,0->01. |
// 差分曼彻斯特编码每个码元依前一码元而定,遇1跳变,遇0保持 |
// 若前为:01,则1->10 0->01 |
// 若前为:10,则1->01 0->10 |
// 实现:定义两个数组,一个用来放置输入要编码的序列,另一个用来放编码后的序列 |
// |
// |
//----------------------------------------------------------------------------
/**/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 头文件
#include <stdio.h>
#include <assert.h>
#include<string.h>
/**/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 全局变量
#define M 10
int j; //指向编码后序列的数组下标
int i; //输入码字的数组下标
int length; //求值输入数组的长度
/**/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 参数表
int Direct_code(char str0[]) //直接编码
...{
char dirct_code[2*M];
memset(dirct_code,0,2*M);
dirct_code[0]='0';
dirct_code[1]='1';
j=2;
extern length;
for(i=0;i<length;i++)
...{
// 循环入口数据
printf("current character is: %c ",str0);
// 循环处理,0 ->01 1 ->10
if(str0=='0') ...{dirct_code[j++]='0';dirct_code[j++]='0';}
else if(str0=='1') ...{dirct_code[j++]='1';dirct_code[j++]='1';}
else ...{printf("input error,exit........ "); return 1;} // 输入出错
// 循环处理后数据
printf("-----");
printf("after process: %c%c ",dirct_code[j-2],dirct_code[j-1]);
}
// 结果字符串加上终结符
dirct_code[j]=0;
// 输出结果
printf("------------------------------------------- ");
printf("Direct_code coding is:%s ",dirct_code);
return 0;
}
int Manchester(char str0[]) //曼彻斯特编码
...{
char Manchester[2*M];
memset(Manchester,0,2*M);
Manchester[0]='0';
Manchester[1]='1';
j=2;
extern length;
for(i=0;i<length;i++)
...{
// 循环入口数据
printf("current character is: %c ",str0);
// 循环处理,0 ->01 1 ->10
if(str0=='0') ...{Manchester[j++]='0';Manchester[j++]='1';}
else if(str0=='1') ...{Manchester[j++]='1';Manchester[j++]='0';}
else ...{printf("input error,exit........ "); return 1;} // 输入出错
// 循环处理后数据
printf("-----");
printf("after process: %c%c ",Manchester[j-2],Manchester[j-1]);
}
// 结果字符串加上终结符
Manchester[j]=0;
// 输出结果
printf("------------------------------------------- ");
printf("Manchester coding is :%s ",Manchester);
return 0;
}
int Dif_Manchester(char str0[]) //差分曼彻斯特编码
...{
char Dif_Manch[2*M];
memset(Dif_Manch,0,2*M); //初始化数组
Dif_Manch[0]='0';
Dif_Manch[1]='1';
j=2;
extern length;
for(i=0;i<length;i++)
...{
// 循环入口数据
printf("current character is: %c ",str0);
// 循环处理,0 ->01 1 ->10
if(str0=='0')
...{
Dif_Manch[j++]=Dif_Manch[j-3];
Dif_Manch[j++]=Dif_Manch[j-2];
}
else if(str0=='1')
...{
Dif_Manch[j++]=Dif_Manch[j-2];
Dif_Manch[j++]=Dif_Manch[j-3];
}
else ...{printf("input error,exit........ "); return 1;} // 输入出错
// 循环处理后数据
printf("-----");
printf("after process: %c%c ",Dif_Manch[j-2],Dif_Manch[j-1]);
}
// 结果字符串加上终结符
Dif_Manch[j]=0;
// 输出结果
printf("------------------------------------------- ");
printf("Dif_Manchester coding is :%s ",Dif_Manch);
return 0;
}
/**/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// 入口点
int main(int argc, char* argv[])
...{
char str0[M];
// 获取输入数据
printf("please input the number string u want(it must less than 10): ");
scanf("%s",str0);
// 验证输入数据是否正确,可以用assert之类
printf("what u input is------:: %s ",str0);
length=strlen(str0);
assert(length <M ); //设置断言,数组越界检查
// 输出数据区置0
//memset(str1,0,2*M);
Direct_code(str0);
Manchester(str0);
Dif_Manchester(str0);
return 0;
}
/**///////////////////////////////////////////////////////////////////////////////
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
/**/////////////////////////////////////////这是刚刚开始自己写的程序////////////////////////////////////////////////////////////////////////
#define M 10
#include<stdio.h>
void main()
...{
int i=0;
int str0[M];
int str1[2*M];
printf("please input the number string u want: ");
scanf("%s",str0);
do
...{
if(str0==0) ...{str1=0;str1[i+1]=1;}
else if(str0==1) ...{str1=1;str1[i+1]=0;}
i++;
}while(str0!='
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
总结几点:
A:字符串和数字是不同的,例如‘1’,‘0’表示的是字符,而1,0表示的数字(但是有个问题还是不太明白,数 组中存放数字有什么错误吗?为何要用字符呢?哈哈,别骂我....)。一个字符用‘’表示时,它传递给计算机的是它的ASCII码值
B:编写程序时候每一段代码做了什么都应该清晰明了,设定一定的提示输出,显示程序所做的事情,结构要清晰,每一次数据处理得到了什么结果 每一步数据处理我都清楚的想知道他做了什么
C:重要的一点是写程序前,自己脑子里面应该有个很清晰的思路,画流程图是重点,我常常在还没有想好是怎么回事的情况下就匆忙动笔了,结果进展反而非常之慢 “问题是你没有 把问题先搞清楚,没有把输入,处理输入,输出这些过程在脑袋里搞清楚”
D:个人问题:付出时间的同时不能付出同等的精力,并不是不想,虽然已经很专注了,但是我知道自己脑袋里面还在想其他的事情,没有事先把头脑清空了,再来写程序。
另外自己做事情不够专心,三心二意:写程序的时候可能同时在看网页,或者是其他的,遇到一个问题不懂,去网上查很久,走很大一个弯路回来,虽然懂了不明白的那一点,但是目前进行的却被打断了。
E:目前为止比较完整的程序写了三个了,每个都不容易,不是程序难,是我写的不容易> 大家认为我可能不是编程的料
F:突然想起ziji 一个致命的缺点: 拖拉。
G:补充:这个只是模拟,其实曼彻斯特编码应该是对应与位的运算
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
新知识点一:ASSERT()
ASSERT()是一个调试程序时经常使用的宏。
assert是验证assert后面的括号里的表达式是否为真的函数,若为假,程序运行的时候就会报错.
当构造一个应用程序的时候,应该始终记住:应该让程序在出现bug或非预期的错误的时候,应该让程序尽可能早地突然死亡。这样做可以帮助你在开发——测试循环中尽早地发现错误。不导致突然死亡的错误将很难被发现;它们通常会被忽略,直到程序在客户系统中运行以后才被注意到。
检查非预期状态的最简单的方式是通过标准C库的assert宏。这个宏的参数是一个布尔表达式(Boolean expression)。当表达式的值为假的时候,assert会输出源文件名、出错行数和表达式的字面内容,然后导致程序退出。Assert宏可用于大量程序内部需要一致性检查的场合。例如,可以用assert检查程序参数的合法性、检查函数(或C++中的类方法)的前提条件和最终状态(postcondition)、检查非预期的函数返回值,等等。
每次使用assert宏,不仅可以作为一项运行期的检查,还可以被当作是嵌入代码中的文档,用于指明程序的行为。如果你的程序中包含了assert( condition ),它就是在告诉阅读代码的人:condition在这里应该始终成立;否则很可能是程序中的bug。
对于效率至上的代码,assert这样的运行时检查可能引入严重的效率损失。在这种情况下,你可以定义NDEBUG宏并重新编译源码(可以通过在编译器参数中添加 –DNDEBUG参数做到)。在这种情况下,assert宏的内容将被预处理器清除掉。应该只在当效率必须优先考虑的情况下,对包含效率至上的代码的文件设置NDEBUG宏进行编译。
因为assert可能被预处理过程清除,当使用这个宏的时候必须确信条件表达式不存在副作用。特别的,不应该在assert的条件表达式中使用这些语句:函数调用、对变量赋值、使用修改变量的操作符(如 ++ 等)。
例如,假设你在一个循环中重复调用函数do_something。这个函数在成功的情况下返回0,失败则返回非0值。但是你完全不期望它在程序中出现失败的情况。你可能会想这样写:
for (i = 0; i < 100; ++i)
assert (do_something () == 0);
不过,你可能发现这个运行时检查引入了不可承受的性能损失,并因此决定稍候指定NDEBUG以禁用运行时检测。这样做的结果是整个对assert的调用会被完全删除,也就是说,assert宏的条件表达式将永远不会被执行,do_something一次也不会被调用。因此,这样写才是正确的:
for (i = 0; i < 100; ++i) {
int status = do_something ();
assert (status == 0);
}
另外一个需要记住的是,不应该使用assert去检测不合法的用户输入。用户即使在输入不合适的信息后也不希望看到程序仅在输出一些含义模糊的错误信息后崩溃。你应该检查用户的非法输入并向用户返回可以理解的错误信息。只当进行程序内部的运行时检查时才应使用assert宏。
一些建议使用assert宏的地方:
• 检查函数参数的合法性,例如判断是否为NULL指针。由 { assert (pointer != NULL)} 得到的错误输出
Assertion ‘pointer != ((void *)0)’ failed.
与当程序因对NULL指针解引用得到的错误信息
Segmentation fault (core dumped)
相比而言要清晰得多。
• 检查函数参数的值。例如,当一个函数的foo参数必须为正数的时候我们可以在函数开始处进行这样的检查:
assert (foo > 0);
这会帮助你发现错误的调用;同时它很清楚地告诉了读代码的人:这个函数对参数的值有特殊的要求。
不要就此退缩;在你的程序中适当地时候使用assert宏吧。
使用Assertion来提高你代码的可靠性
以下是一些使用assertion的四种情况及其对应的例子,这些方式可以让java程序的可靠性更高。
一、检查控制流; 在if-then-else和swith-case语句中,我们可以在不应该发生的控制支流上加上assert false语句。如果这种情况发生了,assert能够检查出来。
例如:x取值只能使1,2,3,我们的程序可以如下表示
switch (x)
{ case 1: …;
case 2: …;
case 3: …
default: assert false:"x value is invalid: "+x;
}
二、在私有函数计算前,检查输入参数是否有效;对于一私有些函数,要求输入满足一些特定的条件,那么我们可以在函数开始处使用assert进行参数检查。对于公共函数,我们通常不使用assertion检查,因为一般来说,公共函数必须对无效的参数进行检查和处理。而私有函数往往是直接使用的。
例如:某函数可能要求输入的参数必须不为null。那么我们可以在函数的一开始加上 assert parameter1!=null : "paramerter is null in test method";
三、在函数计算后,检查函数结果是否有效;对于一些计算函数,函数运行完成后,某些值需要保证一定的性质,因此我们可以通过assert检查该值。
例如,我们有一个计算绝对值的函数,那么我们就可以在函数的结果处,加上一个语句:
assert value>=0:"Value should be bigger than 0:"+value;
通过这种方式,我们可以对函数计算完的结果进行检查。
四、检查程序不变量;有些程序中,存在一些不变量,在程序的运行生命周期,这些不变量的值都是不变的。这些不变量可能是一个简单表达式,也可能是一个复杂的表达式。对于一些关键的不变量,我们可以通过assert进行检查。
例如,在一个财会系统中,公司的支出和收入必须保持一定的平衡关系,因此我们可以编写一个表达式检查这种平衡关系,如下表示。
private boolean isBalance() {
……
}
在这个系统中,在一些可能影响这种平衡关系的方法的前后,我们都可以加上assert验证:assert isBalance():"balance is destoried";
///////////////////////////////////////////////////////////////////////////////////////////////
新知识点(二)memset
。void *memset(void *s,int c,size_t n)
总的作用:将已开辟内存空间 s 的首 n 个字节的值设为值 c。
2。例子
#i nclude
#i nclude
main(){
char *s="Golden Global View";
clrscr();
memset(s,'G',6);
printf("%s",s);
getchar();
return 0;
}
3。memset() 函数常用于内存空间初始化。如:
char str[100];
memset(str,0,100);
4。memset()的深刻内涵:用来对一段内存空间全部设置为某个字符,一般用在对定义的字符串进行初始化为‘ ’或‘\0’;例:char a[100];memset(a, '\0', sizeof(a));
memcpy用来做内存拷贝,你可以拿它拷贝任何数据类型的对象,可以指定拷贝的数据长度;例:char a[100],b[50]; memcpy(b, a, sizeof(b));注意如用sizeof(a),会造成b的内存地址溢出。
strcpy就只能拷贝字符串了,它遇到'\0'就结束拷贝;例:char a[100],b[50];strcpy(a,b);如用strcpy(b,a),要注意a中的字符串长度(第一个‘\0’之前)是否超过50位,如超过,则会造成b的内存地址溢出。
5.补充:某人的一点心得
memset可以方便的清空一个结构类型的变量或数组。
如:
struct sample_struct
{
char csName[16];
int iSeq;
int iType;
};
对于变量
struct sample_strcut stTest;
一般情况下,清空stTest的方法:
stTest.csName[0]='\0';
stTest.iSeq=0;
stTest.iType=0;
用memset就非常方便:
memset(&stTest,0,sizeof(struct sample_struct));
如果是数组:
struct sample_struct TEST[10];
则
memset(TEST,0,sizeof(struct sample_struct)*10);
6。strcpy
原型:extern char *strcpy(char *dest,char *src);
用法:#i nclude
功能:把src所指由NULL结束的字符串复制到dest所指的数组中。
说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
返回指向dest的指针。
memcpy
原型:extern void *memcpy(void *dest, void *src, unsigned int count);
用法:#i nclude
功能:由src所指内存区域复制count个字节到dest所指内存区域。
说明:src和dest所指内存区域不能重叠,函数返回指向dest的指针。
memset
原型:extern void *memset(void *buffer, int c, int count);
用法:#i nclude
功能:把buffer所指内存区域的前count个字节设置成字符c。
说明:返回指向buffer的指针。
本文来自CSDN博客,转载出处:http://blog.csdn.net/wangjiaoni/archive/2007/06/03/1636089.aspx