C语言中的协程程序

2020-05-25 03:43:01

int解压缩器(Void){static int c,len;crBegin;While(1){c=getchar();if(c==EOF)Break;if(c==0xFF){len=getchar();c=getchar();While(len--)crReturn(C);}Else crReturn(C);}crReturn(EOF);crish;}。

void parser(Int C){crBegin;While(1){/*第一个字符已在c*/if(c==EOF)Break;if(isalpha(C)){do{add_to_Token(C);crReturn();}While(isalpha(C));get_Token(Word);}add_to_Token(C);get_Token(PUNCT);crReturn();}crish;}。

我们已经将解压缩器和解析器都重写为被调用者,对于上次我们不得不进行的大规模重构,根本不需要。每个函数的结构都精确地反映了其原始形式的结构。阅读器可以推导出解析器识别的语法,或者说解压器使用的压缩数据格式,这比通过读取模糊的状态机代码容易得多。一旦您理解了新的格式,控制流就会很直观:当解压缩器有一个字符时,它会用crReturn将其传递回调用者,并在需要另一个字符时等待再次调用。当解析器需要另一个字符时,它使用crReturn返回,并等待使用参数c中的新字符再次调用。代码有一个小小的结构变化:parser()现在在循环的末尾有它的getchar()(好吧,对应的crReturn),而不是在开始处,因为当进入函数时,第一个字符已经在c中了。我们可以接受这种微小的结构变化,或者如果我们真的对它有强烈的感觉,我们可以指定parser()需要一个初始化调用,然后才能开始向它提供字符。当然,和以前一样,我们不必使用协程宏来重写这两个例程。一个就足够了;另一个可以是它的调用者。我们已经实现了我们计划实现的目标:一种可移植的ANSIC方法,可以在生产者和消费者之间传递数据,而无需将其重写为显式状态机。我们通过将C预处理器与switch语句的一个很少使用的特性相结合来创建隐式状态机,从而实现了这一点。当然,这个把戏违反了书中的每一个编码标准。试着在你公司的代码中这样做,你可能会受到严厉的斥责,如果不是纪律处分的话!您在宏中嵌入了无与伦比的花括号,在子块中使用了大小写,对于crReturn宏,其内容具有极大的破坏性。你没有因为这种不负责任的编码行为而被当场解雇,这真是个奇迹。你该为自己害臊。我认为这里的编码标准有问题。我在本文中展示的示例不是很长,也不是很复杂,在重写为状态机时仍然可以理解。但是,随着函数变长,所需的重写程度变得更高,清晰度的损失也会变得非常非常严重。考虑一下。由CASE STATE1:/*执行某些活动*/IF(条件)STATE=STATE2;ELSE STATE=STATE3形式的小块构建的函数;

对于读者来说,与由小块组成的函数没有太大不同,一个是调用方,另一个是被调用方,是真的,但函数的视觉结构是相同的,它们提供的对其底层算法的洞察力也完全一样小。同样会因为使用mycoroutine宏而解雇您的人,也会因为用goto语句连接的小块构建函数而解雇您!这一次他们是对的,因为这样的函数布局严重地模糊了算法的结构。编码标准旨在清晰明了。通过将开关、返回和用例等重要内容隐藏在混淆宏中,编码标准会声称您模糊了程序的语法结构,违反了清晰度要求。但是您这样做是因为您揭示了程序的算法结构,而这很可能是读者想知道的!任何以牺牲算法清晰度为代价而坚持句法清晰度的编码标准都应该重写。如果你的雇主因为你使用这个把戏而解雇了你,在保安人员把你拖出大楼时,反复告诉他们这一点。在严肃的应用程序中,这个玩具协同程序实现不太可能有用,因为它依赖于静态变量,因此它不是可重入的或多线程的。理想情况下,在实际应用程序中,您可能希望能够在几个不同的上下文中调用相同的函数,并且在给定上下文中的每次调用时,在相同上下文中的最后一次返回之后立即恢复控制。这很容易做到。我们安排一个额外的函数参数,它是指向上下文结构的指针;我们将所有LocalState和协程状态变量声明为该结构的元素。有点难看,因为突然之间你不得不