zoukankan      html  css  js  c++  java
  • BF解释器和几个小程序以及关于多文件编程的理解

    上SICP的时候樾哥提到了一个叫图灵完备的概念,啥是图灵完备呢?简单说就是能模拟图灵机的所有操作的语言就可以说是图灵完备的,它的计算能力和图灵机至少是等价的
    然后有这么一个很小的语言Brainfuck,它有一个类似射线的有格纸带,一个可以任意移动的指针
    规定,"<"、">"、","、"."、"+"、"-"分别表示左移、右移、读入、输出、增加1、减少1,这个做起来是很简单的
    然后是"["和"]",其等价于 while (pointer->value != 0) {do sth...}
    要实现这个操作只需要用一个栈记录所有的左括号就可以了。纸带等价于一个双向链表,这些都不是很难写。

    特意用C写了这个东西的解释器,把自己实现的stack和list放在了两个.h文件里,学到很多.jpg
    关于.h文件的用法还没有很好的掌握,这里先不管了…

    在oi中,我们通常只能提交一个源代码文件,因此多文件编程并不是必须的(或者说是必须禁止的)
    然而在实际生产生活中,我们不可能写一个长达几千行的源文件。首先这对代码能力有很高的要求,其次这阻止了多人协作/同时工作,最后只有一个源文件意味着每次修改都要重新完整地编译
    一个解决的方案比把过程分为函数更彻底,我们把一个程序分成若干部分。例如本项目里就可以把stack和list的实现分离出去,这样也有利于代码以后复用

    .h文件和.c文件在项目中承担的角色不一样:.c文件主要负责实现,也就是定义函数;.h文件主要负责声明,比如函数声明、宏定义等。这些不是C语法规定的内容,而是约定成俗的规范

    下面是关于.h头文件的事实标准:
    可以声明函数,但不可以定义函数。
    可以声明常量,但不可以定义变量。
    可以“定义”一个宏函数。注意:宏函数很像函数,但却不是函数。其实还是一个声明。
    结构的定义、自定义数据类型一般也放在头文件中。
    除了主文件(有 main() 函数的文件),其他的 .c 文件一般只定义函数,并向外暴露(可以使用 extern,也可以不使用)。
    可以将一个或多个相关的函数定义在一个 .c 文件。

    上面的内容摘自C语言模块化编程 chunlanse2014

    个人的理解是,.h文件只负责提供接口的作用,而接口两端的物品在编译时是各自独立的

    这里附赠几个个小程序,有一些是自己写的,可能有更好的写法

    
    // ,>,[-<+>] // a plus b
    // ,>,[-<->] // a minus b
    // ,>>,<<[->>[-<+>>+<]>[-<+>]<<<]>. //a times b
    // ++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>. // Hello World!
    
    
    // BFcompiler.c
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include "stack.h"
    #include "list.h"
    
    #define MAX_LENGTH 200005
    
    char seq[MAX_LENGTH];
    
    int FindNextPos(char *s, int pos) {
    	for (; s[pos] != ']'; ) pos ++;
    	return pos;
    }
    
    int main(void) {
    	scanf("%s", seq);
    	int len = strlen(seq);
    	Node* current_pointer = (Node*) malloc(sizeof(Node));
    	NodeInit(current_pointer);
    	Stack* stack = (Stack*) malloc(sizeof(Stack));
    	StackInit(stack);
    	for (int i = 0; i < len; ++ i) {
    		switch (seq[i]) {
    			case '+': {
    				add(current_pointer, 1);
    				break;
    			}
    			case '-': {
    				add(current_pointer, -1);
    				break;
    			}
    			case '>': {
    				moveRight(&current_pointer);
    				break;
    			}
    			case '<': {
    				moveLeft(&current_pointer);
    				break;
    			}
    			case ',': {
    				scanf("%d", &(current_pointer->value));
    				break;
    			}
    			case '.': {
    				printf("%c", current_pointer->value);
    				break;
    			}
    			case '[': {
    				if (current_pointer->value != 0) {
    					StackPush(stack, i);
    				} else {
    					i = FindNextPos(seq, i);
    				}
    				break;
    			}
    			case ']': {
    				if (current_pointer->value != 0) {
    					i = StackTop(stack);
    				} else {
    					StackPop(stack);
    				}
    				break;
    			}
    		}
    	}
    	return 0;
    }
    
    
    
    // stack.h
    #ifndef STACK_HEADER_FILE
    #define STACK_HEADER_FILE
    
    #define INF 0x3f3f3f3f
    
    typedef struct tmpStackNode {
    	struct tmpStackNode *next;
    	int value;
    } StackNode;
    
    typedef struct {
    	StackNode *top;
    	int size;
    } Stack;
    
    void StackNodeInit(StackNode *p);
    
    void StackInit(Stack *stack);
    
    void StackPush(Stack *stack, int value);
    
    void StackPop(Stack *stack);
    
    int StackTop(Stack *stack);
    
    #endif
    
    
    //stack.c
    #include <stddef.h>
    #include <stdlib.h>
    #include "stack.h"
    
    void StackNodeInit(StackNode *p) {
    	p->next = NULL;
    	p->value = 0;
    }
    
    void StackInit(Stack *stack) {
    	stack->top = (StackNode*) malloc(sizeof(StackNode*));
    	StackNodeInit(stack->top);
    	stack->size = 0;
    }
    
    void StackPush(Stack *stack, int value) {
    	StackNode *tmp = (StackNode*) malloc(sizeof(StackNode));
    	StackNodeInit(tmp);
    	tmp->value = value;
    	tmp->next = stack->top;
    	stack->top = tmp;
    	stack->size += 1;
    }
    
    void StackPop(Stack *stack) {
    	if (stack->size < 1) return ;
    	StackNode *tmp = stack->top;
    	stack->top = stack->top->next;
    	stack->size -= 1;
    	free(tmp);
    	tmp = NULL;
    }
    
    int StackTop(Stack *stack) {
    	if (stack->size < 1) return INF;
    	return stack->top->value;
    }
    
    
    // list.h
    #ifndef LIST_HEADER_FILE
    #define LIST_HEADER_FILE
    
    typedef struct tmpNode {
    	struct tmpNode *next, *prev;
    	int value;
    } Node;
    
    void NodeInit(Node *p);
    
    void add(Node *p, int value);
    
    void moveLeft(Node **p);
    
    void moveRight(Node **p);
    
    #endif
    
    //list.c
    #include <stddef.h>
    #include <stdlib.h>
    #include "list.h"
    
    void NodeInit(Node *p) {
    	p->next = p->prev = NULL;
    	p->value = 0;
    }
    
    void add(Node *p, int value) {
    	p->value += value;
    }
    
    void moveLeft(Node **p) {
    	if ((*p)->prev == NULL) return ;
    	(*p) = (*p)->prev;
    }
    
    void moveRight(Node **p) {
    	if ((*p)->next == NULL) {
    		(*p)->next = (Node*) malloc(sizeof(Node));
    		NodeInit((*p)->next);
    		(*p)->next->prev = (*p);
    	}
    	(*p) = (*p)->next;
    }
    

    本文来自博客园,作者:jjppp。本博客所有文章除特别声明外,均采用CC BY-SA 4.0 协议

  • 相关阅读:
    mojoPortal学习笔记之页面访问权限控制
    页面中添加某模块
    styletreeview.css页面菜单
    mojoPortalprovider模式学习之1.1之IndexBuilderManager
    mojoportal学习笔记之HtmlContent模块
    CLR via c#学习笔记 之 引用类型与值类型
    mojoportal中解决下载文件名乱码问题
    mojoportal学习笔记之显示所有菜单
    blogmodule.css博客栏目
    [转]数据访问组件SqlHelper
  • 原文地址:https://www.cnblogs.com/jjppp/p/14191153.html
Copyright © 2011-2022 走看看