中国DOS联盟论坛

中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net  论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

游客:  注册 | 登录 | 命令行 | 会员 | 搜索 | 上传 | 帮助 »
中国DOS联盟论坛 » DOS开发编程 & 发展交流 (开发室) » [分享]我写的ROT13加编/解码程序!
作者:
标题: [分享]我写的ROT13加编/解码程序! 上一主题 | 下一主题
bush
银牌会员




积分 2165
发帖 730
注册 2004-4-21
状态 离线
『楼 主』:  [分享]我写的ROT13加编/解码程序!

用TC编写,大小9.84kB,可以用来对文本文件加密。大家可以来试一下,看看有没有什么问题,rot13.exe 压缩包
    用法是 rot13 源文件 编码文件
    但不要使两个参数同名。
    ROT13 是一种简单的编码,它把字母分成前后两组,每组13个,编码和解码
的算法相同,仅仅交换字母的这两个部分。

我发现标准的程序无法正确地处理中文,原因好像是几个ctype.h标准函数处理非ASCII字符不太严密
所以我重写了一个,可以处理中文,
以下是源代码:

#include
int main(int argc,char*argv[])
{
FILE *in,*out;
  char c,tmp;
if(argc<3)
        {
        printf("SYNTAX: rot13 sourcefile output\n";
        exit(1);
        }
in=fopen(argv[1],"r";
if(!in)
        {
        printf("cannot open sourcefile!\n";
        exit(2);
        }
out=fopen(argv[2],"w";
if(!out)
        {
        printf("cannot open output!\n";
        exit(3);
        }
while((c=getc(in))+1)
        if(c&0x40)
                {
                tmp=c&0x1f;
                if(tmp&&tmp0x0d&&tmp<0x1b)
                        putc(c-13,out);
                else putc(c,out);
                }
        else putc(c,out);
/*putch(isalpha(c)? tolower(c)<''n''? c+13: c-13: c);*/
return 0;
}



[此贴子已经被作者于2004-6-20 下午 09:05:38编辑过]




2004-6-20 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
bush
银牌会员




积分 2165
发帖 730
注册 2004-4-21
状态 离线
『第 2 楼』:  

原来的
程序是:
main(c){putch(isalpha(c)? tolower(c)<'n'? c+13: c-13: c);}
只处理英文字母!

2004-6-20 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
Kinglion
铂金会员

痴迷DOS者


积分 5792
发帖 1921
注册 2003-6-20
来自 金獅電腦軟體工作室
状态 离线
『第 3 楼』:  

支持原创!



熟能生巧,巧能生精,一艺不精,终生无成,精亦求精,始有所成,臻于完美,永无止境!
金狮電腦軟體工作室愿竭诚为您服务!
QQ群:8393170(定期清理不发言者)
个人网站:http://www.520269.cn
电子邮件:doujiehui@vip.qq.com
微信公众号: doujiehui
2004-6-20 00:00
查看资料  发送邮件  访问主页  发短消息 网志  OICQ (79207959)  编辑帖子  回复  引用回复
jihao1234567
中级用户




积分 258
发帖 58
注册 2003-10-11
状态 离线
『第 4 楼』:  

唔,楼主强大……但是我不会C………………



奋发向上!!!
2004-6-21 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
willsort
元老会员

Batchinger


积分 4432
发帖 1512
注册 2002-10-18
状态 离线
『第 5 楼』:  

Re bush:

  同 Kinglion 兄,支持原创,本版的优秀代码仍然是"物以稀为贵"的,可惜水平有限,心有余而力不足。

  楼主的代码没有什么大问题,只是作为一个加密程序来说,功能还是略显不足了些。再提一个小建议,while((c=getc(in))+1) 我认为还是改为 while((c=getc(in)) != EOF) 好些,因为EOF是标准的一部分,而-1却不是。类似的技巧,虽然可以体现编程者的机智,但仍然少用为妙。

  另有一个疑惑,我知道c&0x40是判断字母表以上的字符,但是c&0x1f是什么意思呢?


[此贴子已经被作者于2004-6-21 下午 07:58:35编辑过]






※ Batchinger 致 Bat Fans:请访问 [讨论]批处理编程的异类 ,欢迎交流与共享批处理编程心得!
2004-6-21 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
bush
银牌会员




积分 2165
发帖 730
注册 2004-4-21
状态 离线
『第 6 楼』:  好!



  Quote:
[

我之所以要用位操作取代标准函数,是因为isalpha(c)和 tolower(c) 在当c是非ascii字符时,会产生不合理的结果。
字母表以上的字符共同点都是第五位为‘1’;但c&0x40还不足以判断字母表的字符,因为还有几个符号第五位也为‘1’;如果像原来的英文程序上,用tolower(c)判断是否小于'n',则会把后面那几个符号误认为是大于'n'的字母。

同时:tolower() 不会对最高位为1的符号(汉字就是)处理;c&0x1f是为了对两种情况(ascii字符和非ascii字符)一视同仁地处理。后面就可以比大小决定是向前rot13还是向后rot13.

2004-6-22 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
willsort
元老会员

Batchinger


积分 4432
发帖 1512
注册 2002-10-18
状态 离线
『第 7 楼』:  

/*
    Will Sort 改编注:
   
    本程序根据 “中国DOS联盟之联合DOS论坛 → DOS开发编程 & 发展交流 (开发室)
→ 浏览:[分享]我写的ROT13加编/解码程序! ”一文中所附的程序改编。欢迎原作者
bush 和其他爱好者提出宝贵意见。

    改编摘要:
    1,exit函数改为return语句
        使用exit需要包含stdlib.h,而return关键字也可实现同样功能;
        
    2,while((c=getc(in))+1)改为while((c=fgetc(in)) != EOF)                     
    tc中getc为宏,fgetc为函数,都调用底层io函数,虽然getc较为高效,但是文件
函数惯常使用f为首字母;
        -1(即 EOF,tc中定义的文本文件结束符的常数, 某些函数读取错误也会返回此
    值)的用法不值得鼓励,因为它并非标准c定义的内容,在其他c编译系统中可能出现编
    译错误;

    3,位运算改为逻辑运算
        位运算其高效性值得怀疑;而作者所说的不合理也并非因为ctype函数,而是 char
    这个变量类型,几乎所有的IO函数都是返回和调用int 型字符的,因为char 的界限是
    0-127,所以getc返回的非ascii值都只保存了其低7位的值,导致作者所说的问题。而
    作者所说的对中文的处理似乎并非原文输出,也非对所有中文字符绕转,而只是对某些
    中文字符进行处理,这样做的意义何在?这里改用逻辑运算的原因在于,实现此简单的
    功能无需付出额外的包含ctype.h的代价。

    4,char c,temp改为int c, temp
        参见3

    5,一些书写风格上的改变
        无它,习惯而已。

用TC编写,大小9.84kB,可以用来对文本文件加密。大家可以来试一下,看看有没有什么问
题,rot13.exe 压缩包
    用法是 rot13 源文件 编码文件
    但不要使两个参数同名。
    ROT13 是一种简单的编码,它把字母分成前后两组,每组13个,编码和解码
的算法相同,仅仅交换字母的这两个部分。

我发现标准的程序无法正确地处理中文,原因好像是几个ctype.h标准函数处理非ASCII字符
不太严密
所以我重写了一个,可以处理中文,
以下是源代码:
*/

#include
int main(int argc,char*argv[]) {
    FILE *in, *out;
        int c;

    if (argc= 'a' && c = 'A' && c = 'n' && c = 'N' && c <= 'Z')
            putc(c-13, out);
        else
            putc(c, out);
    }
    /*putch(isalpha(c)? tolower(c)<''n''? c+13: c-13: c);*/
    return 0;
}




※ Batchinger 致 Bat Fans:请访问 [讨论]批处理编程的异类 ,欢迎交流与共享批处理编程心得!
2004-7-11 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
bush
银牌会员




积分 2165
发帖 730
注册 2004-4-21
状态 离线
『第 8 楼』:  

to  Will Sort:

我所说的不用ctype函数,并非只是 因为“char其低7位的值”原因(如果是那样,程序是很好处理的):

举例说明一下:

#include
int main()
{
char s[]="你好";
int i=0;
char c;
for(;i<4;i++)
  printf("%c %s\n",s,isalpha(s)? " is a letter.":" not letter.";
for(i=0;i<4;i++)
  printf("%c %s\n",s,islower(s)? " is a lowercase letter.":" not a lowercase letter.";
for(i=0;i<4;i++)
  printf("%c %s\n",s,isupper(s)? " is a uppercase letter.":" not a uppercase letter.";
  return 0;
  }
上面这段小程式将对两个汉字(四个字符)进行测试——是否字母、是否大写、是否小写:

结果显示:

? is a letter.
? is a letter.
? is a letter.
? is a letter.

? is a lowercase letter.
? is a lowercase letter.
? not a lowercase letter.
? is a lowercase letter.

? is a uppercase letter.
? is a uppercase letter.
? is a uppercase letter.
? is a uppercase letter.

看见了吧,都是字母,且有几个既是大写又是小写!
这种逻辑关系让我大惑不解, 如果再使用 tolower() toupper()函数,则结果更加莫明其妙,

如果有ctype函数实现的原型就好了!

由于汉字超范围的原因:对于高低位的ASCII值都落在0x5b-0x5f、0x7b-0x7f区间的汉字不会发生变化,比例算很小的吧。



2004-7-19 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
willsort
元老会员

Batchinger


积分 4432
发帖 1512
注册 2002-10-18
状态 离线
『第 9 楼』:  

   Re bush:  这两天正在整理我以前发过的旧帖,偶然见到这个未结的话题,重新测试了一下,得出以下结论。  8楼程序的问题恰恰还是出在“char其低7位的值”上。我们知道,C标准未定义char型是否有符号,所以很多编译器的实现(包括TC2),都将char分为了signed char和unsigned char,如果定义时缺省符号修饰关键词,那么与int一样,它被默认为signed char。而上述程序中的char s[]="你好";则正是定义了有符号的字符数组。  此时,问题就很明白了,"你好"二字被拆为4个大于128的字符,分别存入数组s中,但是因为s是有符号的,不能大于128,所以他们被转为负值;而ctype的函数显然对此没有准备,因为其算法大概是通过查询一个长为128/256的整型数组来实现的,数组通过位运算保存了1-128/256每个字符所具有的类型,而查询的字符就是这个数组的下标索引值。那么显然,如果这个下标值为负,结果就成了未定义的,取真值也成了可能。而toupper和tolower也基于类似的原因出错了。  所以,解决它的办法很简单,只有将字符数组的定义前加一个unsigned即可,这也是大多数C编程者经常忽略的修饰符。  至于,你所说的原型,只要查看ctype.h即可得到,录于下方,从中可以很明显的看出其中的算法。

  Quote:
#define _IS_SP 1   /* is space */
#define _IS_DIG 2   /* is digit indicator */
#define _IS_UPP 4   /* is upper case */
#define _IS_LOW 8   /* is lower case */
#define _IS_HEX 16   /* [A-F or [a-f] */
#define _IS_CTL 32   /* Control */
#define _IS_PUN 64   /* punctuation */extern char _Cdecl _ctype[];  /* Character type array */#define isalnum(c) (_ctype[(c) + 1] &amp; (_IS_DIG | _IS_UPP | _IS_LOW))
#define isalpha(c) (_ctype[(c) + 1] &amp; (_IS_UPP | _IS_LOW))
#define isascii(c) ((unsigned)(c) &lt; 128)
#define iscntrl(c) (_ctype[(c) + 1] &amp; _IS_CTL)
#define isdigit(c) (_ctype[(c) + 1] &amp; _IS_DIG)
#define isgraph(c) ((c) &gt;= 0x21 &amp;&amp; (c) &lt;= 0x7e)
#define islower(c) (_ctype[(c) + 1] &amp; _IS_LOW)
#define isprint(c) ((c) &gt;= 0x20 &amp;&amp; (c) &lt;= 0x7e)
#define ispunct(c) (_ctype[(c) + 1] &amp; _IS_PUN)
#define isspace(c) (_ctype[(c) + 1] &amp; _IS_SP)
#define isupper(c) (_ctype[(c) + 1] &amp; _IS_UPP)
#define isxdigit(c) (_ctype[(c) + 1] &amp; (_IS_DIG | _IS_HEX))#define _toupper(c) ((c) + 'A' - 'a')
#define _tolower(c) ((c) + 'a' - 'A')
#define toascii(c) ((c) &amp; 0x7f)int _Cdecl tolower(int ch);
int _Cdecl toupper(int ch);





※ Batchinger 致 Bat Fans:请访问 [讨论]批处理编程的异类 ,欢迎交流与共享批处理编程心得!
2005-4-12 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复

请注意:您目前尚未注册或登录,请您注册登录以使用论坛的各项功能,例如发表和回复帖子等。


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转: