第2天 栈和寄存器(上)

第2天 栈和寄存器

多文件编程

笔者在私下和很多C语言的爱好者和初学者交流的过程中发现,大家已经能够使用C语言做出来很出色的程序了。但是这些出色的程序中的一部分竟然只有一个源文件。所以,笔者决定要介绍一下如何使用多个源文件进行编程。不得不说,多文件编程有非常多的优势。比如在维护上非常方便,同时也给多人合作提供了便利。当然,笔者我最喜欢多文件编程的一点就是因为它看起来舒服。接下来,我们就一起来学习如何进行多文件编程。

进入DEV-C++集成开发环境之后,在顶部菜单中找到“文件”→“新建”→“项目”。在弹出的对话框中选择"空项目"(Empty Project),注意还需要选择开发的语言并给项目起名。点击确定后需要对工程文件进行保存。

之后请在左侧的项目管理中找到刚刚新建的项目,新建的项目默认有一个源代码文件,请将它移除并在项目中添加我们在昨天编写的源文件。

接下来我们需要在我们的项目中新建一个源文件,并把它命名为 kia_style.h 实际上它是一个头文件。这样我们就可以把我们之前编写的除了最基本框架的部分都扔到 kia_style.h 这个头文件中。于是 kia_style.h 就变成了:

#include<stdio.h>
#include<conio.h>
#include<string.h>
#include<stdlib.h>
#include<windows.h>

#ifndef KIA_STYLE_H
#define KIA_STYLE_H

unsigned short kia_fc=7;
unsigned short kia_bc=0;

void kia_refreshcolor() {
    HANDLE hCon=GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(hCon,(kia_fc%16)|(kia_bc%16*16));
}

void kia_color(unsigned short c) {
    kia_fc=c;
    kia_refreshcolor();
}

void kia_out(char *str) {
    unsigned short kia_sfc=kia_fc;
    if(strcmp(str,"none")==0)
        kia_color(7);
    printf("%s",str);
    kia_color(kia_sfc);
}

void kia_outln(char *str) {
    unsigned short kia_sfc=kia_fc;
    if(strcmp(str,"none")==0)
        kia_color(7);
    printf("%s\n",str);
    kia_color(kia_sfc);
}

void kia_limout(unsigned char lim,char *str,char style) {
    unsigned char i=0,j=0,len=strlen(str);
    if(len<=lim) {
        kia_out(str);
        for(i=0; i<(lim-len); i++)
            kia_out(" ");
        if(style!=0)
            kia_outln("");
    }
    if(len>lim) {
        if(style==0) {
            for(i=0; i<(lim-3); i++)
                printf("%c",str[i]);
            kia_out("...");
        } else {
            while((j*lim+i)<len) {
                for(i=0; i<lim; i++) {
                    printf("%c",str[j*lim+i]);
                    if((j*lim+i)>=len)
                        break;
                }
                if(style==abs(style))
                    printf("\n");
                if((j*lim+i)<len)
                    for(i=0; i<abs(style); i++)
                        printf(" ");
                j++;
            }
            if(style!=abs(style))
                printf("\n");
        }
    }
}

void kia_tag(char *str) {
    strlwr(str);
    if(strcmp(str,"tip")==0) {
        kia_color(10);
        kia_limout(10,"tip",0);
    } else if(strcmp(str,"error")==0) {
        kia_color(12);
        kia_limout(10,"error",0);
    } else if(strcmp(str,"warning")==0) {
        kia_color(13);
        kia_limout(10,"warning",0);
    } else {
        kia_color(11);
        kia_limout(10,str,0);
        kia_color(14);
    }
}

#endif

这样一来,主文件就会变得非常的简单清爽。按照笔者的习惯,主文件被命名为 main.c

#include "kia_style.h"

int kia_end() {
    kia_tag("tip");
    kia_limout(69,"Press any key to return.",10);
    getch();
    kia_fc=7;
    kia_bc=0;
    kia_refreshcolor();
    return 0;
}

int main(int argc, char *argv[]) {
    SetConsoleTitle("kiasm virtual machine");
    kia_tag("tip");
    kia_limout(69,"test-00000-test-11111-test-22222-test-33333-test-44444-test-55555-test-66666-test",10);
    kia_tag("error");
    kia_limout(69,"test-00000-test-11111-test-22222-test-33333-test",10);
    kia_tag("warning");
    kia_limout(69,"test-00000-test-11111-test-22222-test-33333-test",10);
    kia_tag("test");
    kia_limout(69,"test-00000-test-11111-test-22222-test-33333-test",10);
    kia_tag("testtesttest");
    kia_limout(69,"none",10);
    return kia_end();
}

这里有两件事需要引起特别的注意。首先在 kia_style.h 头文件中

#ifndef KIA_STYLE_H
#define KIA_STYLE_H

//省略程序块

#endif

这里#ifndef#define#endif都是预处理命令,它们的作用是避免头文件中的函数和变量被重复声明。

其次,在主文件中只需要包括一个 kia_style.h 头文件,因为主函数没有直接调用其他的头文件,在kia_style.h 头文件中调用的其他头文件应当在kia_style.h 头文件中包含,而不是在主文件中包含。另外值得注意的是,由于 kia_style.h 头文件是我们自行开发的头文件,所以它要被双引号包裹,而不是被尖括号包裹。

现在可以点击编译并运行试试看,是不是得到了和昨天一模一样的结果。

无类型语言的建立

虽然说在那些已经非常健壮的编程语言中无类型语言已经是过去时了。但是如果我们一开始就建立一种有类型语言的话,似乎会给我们制造编程语言的历程带来很多额外的负担。所以,暂时来说笔者还是要建立一种无类型的语言,在后续的章节中我会告诉你,有类型语言是如何实现的。

所谓无类型语言并不是说一种数据类型都没有的语言,它只有一种数据类型。这种数据类型可以根据大家的喜好来决定。笔者最喜欢的类型是无符号的字符型,即 unsigned char 。选择这种类型作为无类型语言的唯一的数据类型的原因就是它很容易就能变成其他的类型。为我们后续创造有类型的编程语言提供了极大的便利。如果每一次都要写 unsigned char 来定义这种数据类型未免太过于麻烦了。所以我们使用 typedefunsigned char 起一个别名供我们使用。这里笔者起的名字是 kia_t

typedef unsigned char kia_t;

预知后事如何,请听下回分解。关注我,第一时间获得更新动态。