玛丽:如何打印姓名

MARIE: How to print a name

我遇到一个问题,希望用户输入名字和姓氏,然后将其打印出来。 这个问题还希望我 打印出名字和姓氏之间的 space ,我不知道该怎么做。我还做了这样,如果用户输入“$”,程序将停止接收输入并转到打印子例程。到目前为止,这是我的代码。

 /main program
 FirstNameLoop,     JnS SubInputFirstName
                    Load Name
                    Add One
                    Store Name
                    Jump FirstNameLoop

 LastNameLoop,      Jns SubInputLastName
                    Load Name
                    Add One
                    Store Name
                    Jump LastNameLoop


 /subroutine for inputting firstname
 SubInputFirstName, Hex 0
                    Input
                    Store Temp
                    Subt Comma
                    Skipcond 400
                    Jump StoreFirstName
                    Load Comma
                    Add One
                    StoreI Name
                    Jump LastNameLoop
 StoreFirstName,    Load Temp
                    StoreI Name
                    JumpI SubInputFirstName
                
 End,               JnS subPrintString
                    Load NamePrint
                    Add One
                    Store NamePrint
                    Jump End
 Finish,            Halt
                

 /subroutine for entering last name                    
 SubInputLastName,  HEX 0
                    Input 
                    Store Temp
                    Subt Dollar
                    Skipcond 400
                    Jump StoreLastName
                    Jump End

 StoreLastName,     Load Temp
                    StoreI Name
                    JumpI SubInputLastName


 /subroutine for printing name
 subPrintString,    HEX 0
                    LoadI NamePrint
                    Store Temp
                    Subt Period
                    Skipcond 400
                    Jump PrintName
                    Jump Finish
 PrintName,         Load Temp               
                    Output
                    JumpI subPrintString
                
 NamePrint, HEX 300       
 Dollar, Dec 36
 Name, HEX 300
 One, DEC 1
 Temp, DEC 0
 Space, DEC 32
 Comma, DEC 44
 Period, DEC 46

计算机几乎可以记住任何东西,但必须准确地告诉它要记住什么以及何时记住,否则它没有被编程记住的信息可能会丢失并且无法恢复。

由于您将名字和姓氏存储在同一个数据结构中,一旦开始打印,程序就无法知道名字结束和姓氏开始的位置——该信息已被删除丢失。 (事实上​​,一旦请求姓氏的首字符,该信息就会丢失。)

有许多方法可以将信息从存在的地方捕获并传送到需要的地方。首先,我们查看程序中信息仍然存在的点——它位于名字条目和姓氏条目之间的逻辑转换处。这是程序中我们唯一知道一些特别的地方(关于名字和姓氏)。当程序看到 , 字符时,它会停止输入名字并转为输入姓氏。 (我们可以将程序视为状态机,并且,它们的各个部分都视为状态:此处程序逻辑上从名字输入状态过渡到姓氏输入状态。)

作为从输入名字到输入姓氏的逻辑转换的一部分,您可以

(a) 捕获当前名称指针,因为它指向姓氏的第一个字符(尚未捕获)。在此转换中捕捉到这一点后,打印代码可以询问并回答以下问题:这是姓氏的第一个字符吗?如果是,则在输出中插入 space。

(b) 在名字循环中放置一个计数器(但不在名字循环中)。当名字循环完成时,计数器将停止递增,因此它将保持在名字的长度。稍后,打印代码可以询问并回答以下问题:我们是否打印了与名字中一样多的字符,以便在名字的最后一个字符后插入 space 到输出中。

(c) 在从名字条目到姓氏条目的过渡处直接将 space 输入到名称字符串数据结构中,以便打印输出将在它们之间打印一个 space 而无需真的知道关于名字和姓氏的任何特别之处。

(d) 将名字和姓氏存储在不同的数据结构中(两个单独的字符串)。打印第一个字符串,然后打印一个space,然后打印第二个字符串


类似地,作为从接受姓氏到打印的过渡的一部分,您应该向字符串附加一个 . 字符,以便打印例程知道在哪里停止。否则,您可能会寻找 0 (nul) 字符而不是 . 用于输出打印终止。


你正在使用子程序,但遇到转换时也直接从子程序跳回主程序,而不是“returning”——虽然这行得通,但这是非常糟糕的形式,因为它是非结构化的控制流。这种控制流是 Dijkstra 在 1968 年发布“Go To Statement Considered Harmful”的原因。

无法用结构化伪代码或 C 编写该控制流 — 在任何现代编程语言中,我们都不能直接从 subroutine/function 跳到另一个 subroutine/function 中的任何地方,例如 main。一个函数唯一能做的就是对它的调用者 return 。这样,一个函数可以从同一程序中的任何其他函数使用,甚至可以从某个其他函数的多个位置或多个其他函数使用。一个函数,一旦编写,也可以在另一个程序中使用。

有许多可能的解决方案,其中之一是,子例程将 return 给出一个答案,告诉调用者是否发生了转换。调用者然后使用答案来决定是留在循环中还是过渡到 main.

的下一部分

另一个解决方案是将更多功能移到子例程中,例如,输入完整的名字。循环和递增将在子例程内进行,因此,当输入整个名字时,它只会 return 到调用者。 main 将简单地调用一个子例程,然后调用另一个(循环已移至子例程中)。


第二个子程序实际上是第一个子程序的副本,只有一个不同,即用于转换的字符。通过抽象转换字符的概念——将 ,$ 作为参数传递——同一个子例程可以用于名字和姓氏条目。