个性和共性,对共性的封装。新的语言是如何诞生的
本文的编程环境:tcc.exe,tlink.exe,c0s.obj,cs.lib,maths.lib,emu.lib。
先来看这样一个程序:
/*
**用户依次输入:字符串a,一个字符ch、字符串b,根据字符ch“+”或“-”对a和b进行运算,将结果显示出来
*/
main()
{
char a[20];
char b[20];
char ch;
gets(a);
printf("%c\n",ch = getch());
gets(b);
if(ch != '+' && ch!='-')
{
printf("error!");
return;
}
printf("-------------\n");
if(ch == '+')printf("%d",atoi(a) + atoi(b));
if(ch == '-')printf("%d",atoi(a) - atoi(b));
}
这是一个支持加法和减法计算的小程序,如果想要让它支持乘法和除法,只需要在最后的判断中加入对‘*’和‘/'的判断在就好了。
现在来分析一下这个小程序:蓝色部分是这个程序的共性,即不管输入的是什么,都是一样的处理;剩下两句是个性:即对输入的进行了加和减的运算。
接下来对这个程序进行个性与共性的分离:
现有的共性已经摆在这里,我们也没有多大的改动空间了(即使使用一个函数代替蓝色部分,但这实质上只是转移了位置而已,不是共性与个性分离)。
来分析一下个性的部分,这两个都是对两个数据进行一个字符的运算,这里就体现了共性:运算和一个字符,有了这样的思路就可以把运算和字符进行
封装:
char * code = "+-";
int add(int a, int b){return a + b;};
int sub(int a, int b){return a - b;};
int (*func[2])(int, int) = {add,sub};
main()
{
char a[20];
char b[20];
char ch;
int n;
gets(a);
printf("%c\n",ch = getch());
gets(b);
for(n = 0;code[n] && code[n] != ch;n++)
;
if(!code[n])
{
printf("error!");
return;
}
printf("---------------\n");
printf("%d",func[n](atoi(a),atoi(b)));
}
把字符和运算分别放在了两个数组,首先对字符判断,然后执行相应位置的程序。这时main(){}里面的内容是共性,外面的也是共性,但是他们的层次不同,外面的是通过main里面的个性进行更高一层次的分析抽象出来的共性。对比一下这两个程序,除了代码量第二个比第一个多以外,不管从哪里看都是第二个好一点。如果对第二个进行扩展,也是很简单的事:只需在两个数组中加上相应的运算字符和函数。
但是这样的封装也带来了一个问题:字符个运算两个相互独立,在这一层次上这是两个个性,如果字符和函数数组内的元素不是一一对应怎么办?既然出现了问题,那么我们再来重复上一个步骤:把这两个个性在更高一层次找到共性。
运算和字符能有什么共性呢?我们可以把它们封装在一起啊。
typedef struct
{
char ch;
int (*f)(int, int);
}ItemType;
int add(int a, int b){return a + b;};
int sub(int a, int b){return a - b;};
ItemType item[2] = {'+',add,'-',sub};
main()
{
char a[20];
char b[20];
char ch;
int n;
gets(a);
printf("%c\n",ch = getch());
gets(b);
for(n = 0;item[n].ch && item[n].ch != ch;n++)
;
if(!item[n].ch)
{
printf("error!");
return;
}
printf("---------------\n");
printf("%d",item[n].f(atoi(a),atoi(b)));
}
看,这里诞生一了一个新东西:ItemType,这是一个新类型,里面放着运算字符,和运算函数指针。这是为了解决这个为题而诞生的新数据类型。
再继续进行,这只是一个程序,如果想要其他程序也可以使用这些东西,那么可以把这里面的共性再进行与个性分离,可以吧共性放在一个h文件中,使用时就调用它
建一个ys2.h
typedef struct
{
char ch;
int (*f)(int, int);
}ItemType;
func(ItemType * item)
{
char a[20];
char b[20];
char ch;
int n;
gets(a);
printf("%c\n",ch = getch());
gets(b);
for(n = 0;item[n].ch && item[n].ch != ch;n++)
;
if(!item[n].ch)
{
printf("error!");
return;
}
printf("---------------\n");
printf("%d",item[n].f(atoi(a),atoi(b)));
}
ys2.c要使用它
#include "ys2.h"
int add(int a, int b){return a + b;};
int sub(int a, int b){return a - b;};
ItemType item[2] = {'+',add,'-',sub};
main()
{
func(item);
}
这样就可以扩大使用范围,为什么没有吧红色部分封装进去呢?如果封装进去那么这个头文件就成了单纯的解决加减的,而运算应该是个性,是由编写者丰富的,可以写一些其他的运算。
再继续进行,如果这是一个很复杂的问题,到这里还是很麻烦,那么我们可以搭建一个新的开发工具,使用这个工具专门开发解决这个问题的程序。
先编写一个main.c
extern char * code;
extern int (**f)(int, int);
main()
{
char a[20],b[20],ch;
int n;
gets(a);
printf("%c\n",ch = getch());
gets(b);
for(n = 0;code[n] && code[n] != ch;n++)
;
if(!code[n])
{
printf("error!");
return;
}
printf("---------------\n");
printf("%d",f[n](atoi(a),atoi(b)));
}
对main.c只编译不连接,生成main.obj
然后编写一个开发环境:cc.exe
char (*str[3]) = { "echo off","tcc -c %","tlink c0s main %,%,,cs"};
char buffer[100];
void creat(char * old, char * name ,char * new)
{
int i;
char a[2] = {0,0};
new[0] = 0;
for(i = 0;old[i];i++)
{
if(old[i] != '%')
{
a[0] = old[i];
strcat(new,a);
}
if(old[i] == '%')
{
strcat(new,name);
}
}
}
main(int n,char ** name)
{
int i;
if(n<2){printf("hello,but there is no files name");return;}
for(i = 0;str[i];i++)
{
creat(str[i],name[1],buffer);
system(buffer);
}
}
cc.exe就是一个新的开发环境了,编写mc.c
char * code = "+-*/";
int add(int a, int b){return a + b;};
int sub(int a, int b){return a - b;};
int mul(int a, int b){return a * b;};
int div(int a, int b){return a / b;};
int (*func[4])(int, int) = {add,sub,mul,div};
int (**f) (int, int) = func;
输入cc mc编译,新的开发环境就对应了新的开发模式,即开发程序的模式就不一样了。如果对这些已有的语言封装呢?
写一个mc.h
#define YUNSUAN(str) char * code = str;
#define NEW int
#define OP1 (int a, int b){return a
#define OP2 b;};
#define FUNCTION int (*func[])(int, int) = {
#define MAKE_IT };int (**f) (int, int) = func;
然后就可以这样写程序了
#include "mc.h"
YUNSUAN("+-")
NEW add OP1 + OP2
NEW sub OP1 - OP2
FUNCTION add,sub
MAKE_IT
这一段代码是属于cc的,这就可以说是一种新的计算机语言,新的计算机语言就这样诞生了!
当然,现在的计算机语言不可能就是这么简单就产生了,但是具体思路就是这样:对已有的语言进行封装,使之更容易解决某一方面的问题。
个性和共性,对共性的封装。新的语言是如何诞生的相关推荐
- 【转CSDN常高伟】如何学习一门新的语言
原文:http://blog.csdn.net/chgaowei/archive/2011/05/29/6452793.aspx 这两天在看<编程人生>,这本书确实非常不错.而且看得也特别 ...
- 幼谈苹果新开发语言:Swift和苹果的用心
今天是个值得纪念的日子:由于苹果的WWDC大会.苹果的每次WWDC(全球开发人员大会)举行都让我们像打了肾上腺素这么兴奋.幸福.惊叹.震撼.深思. 今年也不例外,最关键的是苹果带来了它的一门新开发语言 ...
- 新程序语言 Wyvern 将不同Web语言融合在一起
如果你是一名Web开发者,你最喜欢哪种编程语言? CSS? JavaScript? PHP? HTML 5?为什么选择这种语言?卡内基梅隆大学的研究人员现在开发出一种新的语言,试图将所有这些语言结合在 ...
- SMLT中增加新的语言
1.SMLT,增加新的语言,如果提示NLS错误 ->2 2.se38中执行RSCPINST,在NLS中增加新的语言 3.选中语言,选择菜单 import language 4.输入补丁文件路径, ...
- ubuntu下使用Tesseract-ocr(编译、安装、使用、训练新的语言库)
本文前半部分是来自http://www.qisanfen.com/?p=185的一篇文章,主要讲了安装.训练的大致流程,注意如果需要训练语言库需要把所需要的库安装完整 后半部分大致是官方wiki的翻译 ...
- 如何学习一门新的语言
这两天在看<编程人生>,这本书确实非常不错.而且看得也特别的轻松.其中有几个人都谈到了如何学习新的语言,但是给我最深刻的是google的首席java架构师joshua bloch.正好最近 ...
- 如何快速的学习一门新的语言
前言 程序的世界变化非常快,总是出新的框架,新的语言,新的名词,如何那快速的跟上这些变化,使自己保持竞争力,而不落伍呢? 语言设计的目的 笔记觉的,首先要看一下这门语言设计的目的是什么,主要想解决哪方 ...
- PCA9555PW 原厂封装 新到货
PCA9555PW 74HC1G14GV 74VC1G11GW NX2301P PBSS5240T TPS53353DQPR CYUSB3035-BZXI 以上型号,对的上绝对优势价格出,实单可谈
- 模块的封装之C语言类的继承和派生
[交流][微知识]模块的封装(二):C语言的继承和派生 在模块的封装(一):C语言的封装中,我们介绍了如何使用C语言的结构体来实现一个类的封装,并通过掩码结构体的方式实 现了类成员的保护.这一部分,我 ...
最新文章
- 为全局变量赋值_Postman全局变量设置和运用
- Vijos p1165 火烧赤壁 离散化+单调栈
- SQL2008R2 Reporting Services 報表產生器 3.0 快速上手
- DL之Attention-ED:基于TF NMT利用带有Attention的 ED模型训练、测试(中英文平行语料库)实现将英文翻译为中文的LSTM翻译模型过程全记录
- 静态链表和动态链表 区别
- php 12小时,使用php怎么将12小时制转换为24小时制
- 编辑距离问题(Edit Distance Problem)
- android am start activity,adb shell am start -n package/.XXXactivity命令学习汇总
- ofo现在还有退路吗?
- 基于Windows AD的单点登录系统
- java实现选择排序(思路与实现)
- 节后 威金/Viking 来拜年
- 二进制转十六进制(参考XYJ)
- Google推出移动搜索 80亿网页、8亿图片尽在掌中
- 堡垒机和跳板机的三大区别分析-行云管家
- *关键字retry:很像goto语句,跳到标记处
- 初探直播客户端(android)技术
- 网络攻防实践 第八周作业
- 基于改进的 CASA 模型反演30m分辨率NPP
- 关于今天烧坏树莓派板子一事的所思所想