首页 > 解决方案 > 玛丽:如何打印姓名

问题描述

我有一个问题,希望用户输入名字和姓氏,然后打印出来。这个问题还希望我在名字和姓氏之间也打印一个空格,我无法弄清楚如何做到这一点。我也这样做了,如果用户输入“$”,程序将停止接受输入并继续打印子程序。到目前为止,这是我的代码。

 /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

标签: assemblymarie

解决方案


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

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

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

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

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

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

(c) 在从名字条目到姓氏条目的转换时,在名称字符串数据结构中直接输入一个空格,以便打印输出将在它们之间打印一个空格,而无需真正了解名字和姓氏的任何特殊信息。

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


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


您正在使用子例程,但在遇到转换而不是“返回”时直接从子例程跳回主例程 - 虽然这是有效的,但它是非常糟糕的形式,因为它是非结构化的控制流。这种控制流是 Dijkstra在 1968 年发表“Go To Statement Considered Harmful ”的原因。

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

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

另一种解决方案是将更多功能移动到子例程中,例如,输入整个名字。循环和递增将在子例程中进行,因此,只有在输入了整个名字后,它才会返回给调用者。将main简单地调用一个子例程,然后调用另一个(循环已移至子例程中)。


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


推荐阅读