MIPS中的一维数组和二维数组

MIPS中使用数组 1.一维数组 ​ 数组存储需要申请内存空间 .data array: .space 40 # 存储这些数需要用到数组,数组需要使用 10 * 4 = 40 字节 # 一个 int 整数需要占用 4 个字节,需要存储 10 个 int 整数 # 因此,array[0] 的地址为 0x00,array[1] 的地址为 0x04 # array[2] 的地址为 0x08,以此类推。 str: .asciiz "The numbers are:\n" space: .asciiz " " .text li $v0,5 syscall # 输入一个整数 move $s0, $v0 # $s0 is n li $t0, 0 # $t0 循环变量 loop_in: beq $t0, $s0, loop_in_end # $t0 == $s0 的时候跳出循环 li $v0, 5 syscall # 输入一个整数 sll $t1, $t0, 2 # $t1 = $t0 << 2,即 $t1 = $t0 * 4 sw $v0, array($t1) # 把输入的数存入地址为 array + $t1 的内存中 addi $t0, $t0, 1 # $t0 = $t0 + 1 j loop_in # 跳转到 loop_in loop_in_end: la $a0, str li $v0, 4 syscall # 输出提示信息 li $t0, 0 loop_out: beq $t0, $s0, loop_out_end sll $t1, $t0, 2 # $t1 = $t0 << 2,即 $t1 = $t0 * 4 lw $a0, array($t1) # 把内存中地址为 array + $t1 的数取出到 $a0 中 li $v0, 1 syscall # 输出 $a0 la $a0, space li $v0, 4 syscall # 输出一个空格 addi $t0, $t0, 1 j loop_out loop_out_end: li $v0, 10 syscall # 结束程序 2.二维数组 .data matrix: .space 256 # int matrix[8][8] 8*8*4 字节 # matrix[0][0] 的地址为 0x00,matrix[0][1] 的地址为 0x04,…… # matrix[1][0] 的地址为 0x20,matrix[1][1] 的地址为 0x24,…… # …… str_enter: .asciiz "\n" str_space: .asciiz " " # 这里使用了宏,%i 为存储当前行数的寄存器,%j 为存储当前列数的寄存器 # 把 (%i * 8 + %j) * 4 存入 %ans 寄存器中 .macro getindex(%ans, %i, %j) sll %ans, %i, 3 # %ans = %i * 8 add %ans, %ans, %j # %ans = %ans + %j sll %ans, %ans, 2 # %ans = %ans * 4 .end_macro .text li $v0, 5 syscall move $s0, $v0 # 行数 li $v0, 5 syscall move $s1, $v0 # 列数 # 这里使用了循环嵌套 li $t0, 0 # $t0 是一个循环变量 in_i: # 这是外层循环 beq $t0, $s0, in_i_end li $t1, 0 # $t1 是另一个循环变量 in_j: # 这是内层循环 beq $t1, $s1, in_j_end li $v0, 5 syscall # 注意一下下面几行,在 Execute 页面中 Basic 列变成了什么 getindex($t2, $t0, $t1) # 这里使用了宏,就不用写那么多行来算 ($t0 * 8 + $t1) * 4 了 sw $v0, matrix($t2) # matrix[$t0][$t1] = $v0 addi $t1, $t1, 1 j in_j in_j_end: addi $t0, $t0, 1 j in_i in_i_end: # 这里使用了循环嵌套,和输入的时候同理 li $t0, 0 out_i: beq $t0, $s0, out_i_end li $t1, 0 out_j: beq $t1, $s1, out_j_end getindex($t2, $t0, $t1) lw $a0, matrix($t2) # $a0 = matrix[$t0][$t1] li $v0, 1 syscall la $a0, str_space li $v0, 4 syscall # 输出一个空格 addi $t1, $t1, 1 j out_j out_j_end: la $a0, str_enter li $v0, 4 syscall # 输出一个回车 addi $t0, $t0, 1 j out_i out_i_end: li $v0, 10 syscall 事实上,在做矩阵转化一题时,我用了利用一维数组模拟二维数组 ...

September 11, 2023 · 3 min · sudo

git指令的初步学习

面向OO的git指令 ​ 在秋季学期开设的OOpre课程中,我首次接触到使用Gitlab对代码进行版本管理,在第一次OOpre作业中我就受到了提交库的拷打,现在是2023年9月10日晚上22:46,开始编写面向OO的git指令 windows命令行操作经典指令 cd:change dictionary cd D: #只有转移磁盘需要加冒号: cd OO #进一步转移到目录下文件夹 cd .. #回退一层目录 ​ 2.pwd:print working dictionary 打印当前工作目录 ​ 3. git 指令 git是一个终端 提交注意 ​ 在每一次作业的发布中,分为作业发布区和个人仓库区,常见的操作是从作业发布区进行repository的clone,在本地完成作业后push到个人仓库区,需要注意的是公共发布区是没有push权限的,下面以第一次作业为例 完成作业的常见步骤 从公共发布区clone ​ 需要注意的是这里的每一个步骤都可以通过IDEA编译器操作或是通过git终端操作,这里我们主要介绍通过git的操作方式(我更加喜欢)。 ​ 进行源的clone,通过以下代码实现 1 git clone url path ​ 其中url代表远程仓库的地址如SSH密钥,path代表路径,绝对路径或相对路径均可以,如果指定的路径不存在则会创建该目录,笔者经过验证,在路径不存在的情况下,确实会进行生成。 需要注意的是在clone后已经存在.git文件 对代码进行修改后的一系列 常用指令git init git init指令用于生成本地的.git跟踪版本文件,是万恶的开端 git status git status用于查看当前文件的情况,是否被跟踪(tracked 用于代码管理),是否有修改等等 git add git add 指令是很常用的操作,用于将文件添加到tracked,常见的有这几种用法 1 2 3 4 //将.git目录下全体文件加入tracked git add . //添加单个文件进行版本管理 git add <filename>//其中如果filename中包含空格的话需要对文件名进行双引号处理 "filename" 通常对文件进行修改后或新建文件后需要进行git add 这时可以通过git status 进行文件状态的查询 ...

September 10, 2023 · 2 min · sudo

malloc分配二维数组

利用malloc分配二维数组 先利用malloc分配出连续的行,再分别对每行分配内存 1 2 3 4 5 int row,col;//二维数组的行数和列数 int** a=(int**)malloc(sizeof(int)*row);//分配出连续的行头 for(int i=0;i<row;i++){ a[i]=(int* )malloc(sizeof(int)*col);//分配每一行的内存 } 注:每一行的内存是连续的,相邻两行的内存不一定连续

July 16, 2023 · 1 min · sudo

Leetcode01

用hash解决leetcode01两数之和 题意分析:在一个数组中找到和为target的两个元素,并返回下标数组 1. 做法一:双层暴力循环 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 int *twoSum(int *nums,int numsSize,int target,int *returnSize) { static int ret[10]={0}; for(int i=0;i<numsSize;i++){ for(int j=i+1;j<numsSize;j++){ if(nums[i]+nums[j]==target){ //int* ret=(int *)malloc(sizeof(int)*10); ret[0]=i,ret[1]=j; *returnSize=2; return ret; } } } *returnSize=0; return NULL; } 2. 做法二:hash ​ **利用hash的做法即为涉及到查找,我们设置一个集合,初始状态为空,在遍历原数组的过程中,就在这个集合中查找target-a[i],如果有则停止查找,如果没有则将该元素加入集合** ```c //leetcode支持ut_hash函数库 typedef struct { int key; int value; UT_hash_handle hh;//make this structure hashable }map; map* hashMAP=NULL; void hashMapAdd(int key,int value) { map*s; HASH_FIND_INT(hashMap,&key,s); if(s==NULL){ s=(map*)malloc(sizeof(map)); s->key=key; HASH_ADD_INT(hashMap,key,s); } s->value=value; } map* hashMapFind(int key) { map*s; HASH_FIND_INT(hashMap,&key,s); return s; } void hashMapCleanup() { map*cur,*tmp; HASH_ITER(hh,hashMap,cur,tmp){ HASH_DEL(hashMap,cur); free(cur); } } void hashPrint(){ map*s; for(s=hashMap;s!=NULL;s=(map*)(s->hh.next)) { print("key %d ,value %d\n",s->key,s->value); } } int *twoSum(int *nums,int numsSize,int target,int *returnSize) { int i,*ans; map* hashMapRes; hashMap=NULL; ans=(int*)malloc(sizeof(int)*2); for(i=0;i<numsSize;i++){ hashMapAdd(nums[i],i); } hashPrint();//经典打印检查 for(i=0;i<numsSize;i++){ hashMapRes=hashMapFind(target-nums[i]); if(hashMapRes&&hashMapRes->value!=i){ ans[0]=i; ans[1]=hashMapRes->value; *returnSize=2; return ans; } } hashMapCleanup(); *returnSize=0; return NULL; } ``` ​ 此种做法中涉及到很多使用头文件函数库uthash.h中的用法,当然我们也可以将这些封装好的函数进行手搓,关于函数库uthash.h会在下一篇中介绍 **手搓hash** ```c //每个元素的关键是值和下标 struct node{ int key; int value; struct node*link; }; struct node *hash[10000]={NULL}; //这里的整数值都比较小,可以考虑直接取余法(质数),但是会处理一些冲突 int HASH(int key) { return key%13; } int *twoSum(int *nums,int numsSize,int target,int *returnSize) { int*a=(int*)malloc(sizeof(int)*2); for(int i=0;i<numsSize;i++){ //以下代码为target>nums[i] if(hash[HASH(target-nums[i])]==NULL){ struct node *p=(struct node*)malloc(sizeof(struct node)); p->key=nums[i];p->value=i;p->link=NULL; hash[HASH(nums[i])]=p; }else{ struct node *q=hash[HASH(target-nums[i])]; while(q!=NULL){ if(q->value!=i)//不同下标 { a[0]=q->value,a[1]=i; *returnSize=2; return a; } q=q->link; } } } *returnSize=0; return NULL; } ``` ​ **但是测试用例中会出现target<nums[i]的情况,即可能出现hash数组下标为负数的情况,以上版本不能通过**

July 15, 2023 · 1 min · sudo

C语言内存分区

C语言内存分区 5大分区 栈区 向下生长 编译器自动分配释放 存储:局部变量 形参 返回值 堆区 向上生长 程序员调用和分配 malloc free 全局(静态)区 全局变量 静态变量 常量区 字符串 数字 代码区 程序代码 下面来看一段代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int *twoSum(int *nums,int numsSize,int target,int *returnSize) { int ret[10]={0}; for(int i=0;i<numsSize;i++){ for(int j=i+1;j<numsSize;j++){ if(nums[i]+nums[j]==target){ ret[0]=i,ret[1]=j; *returnSize=2; return ret; } } } *returnSize=0; return NULL; } ​ 这是leetcode第一题 ,函数要求返回存储原数组下标的新数组,出现过错误在于在函数中去建立临时变量数组,再返回数组地址, ...

July 14, 2023 · 1 min · sudo