MIPS,位于堆栈中的字符串中出现的次数

MIPS, Number of occurrences in a string located in the stack

我在 MIPS 汇编中有一个练习要解决(我有一些疑问但其他事情很清楚)但是我在编写它的代码时遇到了一些问题。练习问我: 编写一个程序,从键盘获取一个字符串,计算出现次数较多的字符的出现次数并显示出来。

我如何检查所有 26 个字符并找出谁的出现次数更高?

示例: 给我一个字符串:Hello world! 出现次数较多的字符是:l

非常感谢未来的回答。

P.s。 这是我的第一部分:

        #First message      
        li $v0, 4
        la $a0, mess
        syscall

        #Stack space allocated
        addi $sp, $sp, -257 

        #Read the string
        move $a0, $sp
        li $a1, 257
        li $v0, 8
        syscall

由于这是您的任务,我将把 MIPS 汇编实现留给您。我将用更高级的语言向您展示代码的逻辑:

// You'd keep these variables in some MIPS registers of your choice
int c, i, count, max_count=0;
char max_char;

// Iterate over all ASCII character codes   
for (c = 0; c < 128; c+=1) {
    count = 0;
    // Count the number of occurences of this character in the string
    for (i = 0; string[i]!=0; i+=1) {
        if (string[i] == c) count++;
    }
    // Was is greater than the current max?
    if (count > max_count) {
        max_count = count;
        max_char = c;
    }
}

// max_char now hold the ASCII code of the character with the highest number
// of occurences, and max_count hold the number of times that character was
// found in the string.

@Michael,我看到你在发帖前回答了,我只是想用更详细的答案重复一遍。如果您自己编辑以添加更多解释,那么我将删除我的。我没有直接编辑你的,因为你发帖的时候我已经编辑到一半了。无论如何:

@Marco:
您可以创建一个包含 26 个计数器(初始化为 0)的临时数组。

每个计数器对应每个字母(即每个字母出现的次数)。例如 counter[0] 对应字母 'a' 的出现次数, counter[1] 对应字母 'b' 等...

然后遍历输入字符序列中的每个字符,并对每个字符执行:
a) 获取字符在counter数组中的索引。
b) 将 counter["obtained index"] 增加 1。

获取字符的索引,您可以执行以下操作:
a) 首先确保字符不是大写,即只允许 'a' 到 'z' 而不是 'A' 到 'Z'。如果不是,请转换它。
b) 从字符中减去字母'a'。这样 'a'-'a' 给出 0,'b'-'a' 给出 1,'c'-'a' 给出 2,等等...

我会用C语言演示,因为这是你在MIPS上的练习(我的意思是目标是学习MIPS汇编语言):

#include <stdio.h>

int main()
{
    //Maximum length of string:
    int stringMaxLength = 100;

    //Create string in stack. Size of string is length+1 to
    //allow the '[=10=]' character to mark the end of the string.
    char str[stringMaxLength + 1];

    //Read a string of maximum stringMaxLength characters:
    puts("Enter string:");
    scanf("%*s", stringMaxLength, str);
    fflush(stdin);

    //Create array of counters in stack:
    int counter[26];

    //Initialize the counters to 0:
    int i;
    for (i=0; i<26; ++i)
        counter[i] = 0;

    //Main counting loop:
    for (i=0; str[i] != '[=10=]'; ++i)
    {
        char tmp = str[i]; //Storing of str[i] in tmp, to write tmp if needed,
        //instead of writing str[i] itself. Optional operation in this particular case.

        if (tmp >= 'A' && tmp <= 'Z') //If the current character is upper:
            tmp = tmp + 32; //Convert the character to lower.

        if (tmp >= 'a' && tmp <='z') //If the character is a lower letter:
        {
            //Obtain the index of the letter in the array:
            int index = tmp - 'a';

            //Increment its counter by 1:
            counter[index] = counter[index] + 1;
        }
        //Else if the chacacter is not a lower letter by now, we ignore it,
        //or we could inform the user, for example, or we could ignore the
        //whole string itself as invalid..
    }

    //Now find the maximum occurences of a letter:
    int indexOfMaxCount = 0;
    int maxCount = counter[0];
    for (i=1; i<26; ++i)
        if (counter[i] > maxCount)
        {
            maxCount = counter[i];
            indexOfMaxCount = i;
        }

    //Convert the indexOfMaxCount back to the character it corresponds to:
    char maxChar = 'a' + indexOfMaxCount;

    //Inform the user of the letter with maximum occurences:
    printf("Maximum %d occurences for letter '%c'.\n", maxCount, maxChar);

    return 0;
}

如果你不明白为什么我把大写字母加32转换成小写字母,那么请继续阅读:

每个字符在内存中对应一个整数值,当你对字符进行算术运算时,就相当于将它们变成编码中对应的数字table。
encoding 只是一个 table,它将这些字母与数字匹配。
例如 'a' 对应 ASCII encoding/decoding/table.
中的数字 97 例如 'b' 对应 ASCII encoding/decoding/table 中的数字 98。

所以'a'+1给出97+1=98就是字符'b'。它们都是内存中的数字,区别在于你如何表示(解码)它们。同样的table的编码,当然也用于解码。

示例:

printf("%c", 'a'); //Prints 'a'.  
printf("%d", (int) 'a'); //Prints '97'.  
printf("%c", (char) 97); //Prints 'a'.  
printf("%d", 97); //Prints '97'.  
printf("%d", (int) 'b'); //Prints '98'.  
printf("%c", (char) (97 + 1)); //Prints 'b'.  
printf("%c", (char) ( ((int) 'a') + 1 ) ); //Prints 'b'.  
//Etc...  
//All the casting in the above examples is just for demonstration,  
//it would work without them also, in this case.