2023_open_source_contest_warmup_1st_issue1

This commit is contained in:
cwolf9 2023-06-05 15:41:24 +08:00
parent 7754a149a9
commit a03f6de225
6 changed files with 395 additions and 1 deletions

View File

@ -1,9 +1,13 @@
menu "test app"
menuconfig USER_TEST
bool "Enable application test function "
default n
default y
if USER_TEST
menuconfig USER_HASH_TABLE
bool "Config test hash table"
default y
menuconfig USER_TEST_ADC
bool "Config test adc"
default n

View File

@ -25,6 +25,10 @@ endif
ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
SRC_FILES := test_shell.c
ifeq ($(CONFIG_USER_HASH_TABLE),y)
SRC_FILES += test_hash/test_hash.c
endif
ifeq ($(CONFIG_USER_TEST_ADC),y)
SRC_FILES += test_adc.c
endif

View File

@ -0,0 +1,108 @@
# 热身赛一级赛题1基于cortex-m3-emulator实现哈希表并测试验证
[toc]
参赛战队bdislab_0
赛题issue热身赛一级赛题1
完成情况:实现哈希表,支持链地址法解决哈希冲突。
## 1. 简介注册shell命令以及哈希命令集说明
**0. 注册TestHashTable命令**
源文件见APP_Framework/Applications/app_test/test_hash/test_hash.c
**1. 插入(key, value)对**
```
TestHashTable 1 key value
```
说明:
- 当插入的key不存在时返回 success。
- 当插入的key已经存在时新值value会覆盖旧值。
- 注意key支持`int`或`string`等若干类型数值但value仅支持`int`范围内的数值。
**2. 查询key对应的(key, value)对**
```
TestHashTable 2 key value
```
说明:
- 当查询的key存在时输出对应的(key, value)对。
- 当查询的key不存在时返回 not exist。
**3. 删除key对应的(key, value)对**
```
TestHashTable 3 key value
```
说明:
- 当删除的key存在时删除对应的(key, value)对。
- 当删除的key不存在时返回 not exist。
**4. 执行帮助**
```
TestHashTable help
```
输出指令集帮助。
## 2. 数据结构设计说明
首先,设计了一个结构体 `struct Hash_entry` 表示每一项哈希结构字段如下包含原始的key变量字符串类型的okey哈希后的key变量int类型的key和value变量。
```
struct Hash_entry {
char *okey;
int key;
int val;
struct Hash_entry *next;
struct Hash_entry *prev;
};
```
第二哈希的模数为MOD。通过拉链法解决哈希冲突所以定义了MOD个哈希链表的头即`struct Hash_entry *hts[MOD]`。并定义了一个数组记录每种哈希值对应链表的长度,即`int htlen[MOD]`。
第三,获取哈希值的函数:`int get_hash_val(char *okey)`。
第四,插入:`int insert_kv(char *okey, char *val)`。
第五,查询:`int query_key(char *okey)`。
第六,删除:`int delete_key(char *okey)`。
## 3. 测试程序说明
测试结果,打印验证功能:均正确。
## 4. 运行结果:测试流程及截图
注意key支持`int`或`string`等若干类型数值但value仅支持`int`范围内的数值。
测试流程:
1. 首先查看哈希表指令集执行帮助:`TestHashTable help`
2. 插入(1, 1)对:`TestHashTable 1 1 1`插入成功返回success
3. 重复插入(1, 2)对:`TestHashTable 1 1 2`新值2覆盖旧值1
4. 查询2对应的(key, value)对:`TestHashTable 2 2`返回not exist
5. 查询1对应的(key, value)对:`TestHashTable 2 1`输出key(1), value(2)
6. 删除1对应的(key, value)对:`TestHashTable 3 1`删除成功返回success
7. 查询1对应的(key, value)对:`TestHashTable 2 1`返回not exist
8. 插入(1, 10)对:`TestHashTable 1 1 10`插入成功返回success
9. 查询1对应的(key, value)对:`TestHashTable 2 1`输出key(1), value(10)
测试截图:
![](evaluation.png)
总结注册shell命令打印验证功能均正确。
## 附录
修改/新增的文件列表:
```
APP_Framework/Applications/app_test/Kconfig
APP_Framework/Applications/app_test/Makefile
APP_Framework/Applications/app_test/test_hash/
APP_Framework/Applications/app_test/test_hash/README.md
APP_Framework/Applications/app_test/test_hash/test_hash.c
APP_Framework/Applications/app_test/test_hash/evaluation.png
```
赛题链接: https://www.gitlink.org.cn/xuos/xiuos/issues/261
提交指南: https://www.gitlink.org.cn/competitions/index/track1_2023_xiuos

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

@ -0,0 +1,265 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: test_hash.c
* @brief: a application of hash function
* @version: 2.0
* @author: XiUOS Team: bdislab_0
* @date: 2023/6/5
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <transform.h>
#include "test_hash.h"
/**
* @brief Priv-shell Command definition
*
* @param _func Command function
* @param _desc Command description
* @param _attr Command attributes if need
*/
#define PRIV_SHELL_CMD_FUNCTION(_func, _desc, _attr) SHELL_EXPORT_CMD(_attr, _func, _func, _desc)
struct Hash_entry *create_hash_entry(char *okey_, int key_, int val_) {
return NULL;
}
struct Hash_entry *hts[MOD];
int htlen[MOD];
int get_hash_val(char *okey) {
int ans = 0;
while(*okey) {
ans = (ans * 233 + *okey) % MOD;
okey ++;
}
return ans;
}
char * str_copy(char *s, char *t) {
int len = strlen(t) + 1;
s = (char *)malloc(len);
for(int i = 0; i < len; ++i) s[i] = t[i];
s[len] = '\0';
return s;
}
void insert_tail(struct Hash_entry *head, struct Hash_entry *last, struct Hash_entry *tmp) {
last->next = tmp;
tmp->next = head;
tmp->prev = last;
head->prev = tmp;
}
int str_to_int(char *str) {
int ans = 0;
while(*str) {
ans = (ans * 10 + *str - '0');
str ++;
}
return ans;
}
int insert_kv(char *okey, char *val) {
int key = get_hash_val(okey);
int ret = NOT_EXIST_VAL;
if(htlen[key] == 0) {
hts[key] = (struct Hash_entry *)malloc(sizeof(struct Hash_entry));
hts[key]->prev = hts[key];
hts[key]->next = hts[key];
hts[key]->okey = str_copy(hts[key]->okey, okey);
hts[key]->key = key;
hts[key]->val = str_to_int(val);
// printf("insert_kv: %p %s %d %d\n", hts[key], hts[key]->okey, key, hts[key]->val);
htlen[key] += 1;
return ret;
}else {
struct Hash_entry *head = hts[key];
if(strcmp(head->okey, okey) == 0) {
ret = head->val;
head->val = str_to_int(val);
}else {
head = head->next;
while(head != hts[key]) {
if(strcmp(head->okey, okey) == 0) {
ret = head->val;
head->val = str_to_int(val);
break;
}
head = head->next;
}
}
if(ret != NOT_EXIST_VAL) {
return ret;
}
struct Hash_entry *new_he = (struct Hash_entry *)malloc(sizeof(struct Hash_entry));
new_he->prev = new_he;
new_he->next = new_he;
new_he->okey = str_copy(new_he->okey, okey);
new_he->key = key;
new_he->val = str_to_int(val);
insert_tail(hts[key], hts[key]->prev, new_he);
htlen[key] += 1;
return ret;
}
}
int query_key(char *okey) {
int val = NOT_EXIST_VAL;
int key = get_hash_val(okey);
if(htlen[key] != 0) {
struct Hash_entry *head = hts[key];
if(strcmp(head->okey, okey) == 0) {
val = head->val;
}else {
head = head->next;
while(head != hts[key]) {
if(strcmp(head->okey, okey) == 0) {
val = head->val;
break;
}
head = head->next;
}
}
}
return val;
}
int delete_key(char *okey) {
int ret = NOT_EXIST_VAL;
int key = get_hash_val(okey);
if(htlen[key] != 0) {
struct Hash_entry *head = hts[key];
if(strcmp(head->okey, okey) == 0) {
ret = head->val;
struct Hash_entry * le = head->prev, *ri = head->next;
le->next = ri;
ri->prev = le;
hts[key] = ri;
free(head->okey);
free(head);
htlen[key] -= 1;
}else {
head = head->next;
while(head != hts[key]) {
if(strcmp(head->okey, okey) == 0) {
ret = head->val;
struct Hash_entry * le = head->prev, *ri = head->next;
le->next = ri;
ri->prev = le;
// hts[key] = ri;
free(head->okey);
free(head);
htlen[key] -= 1;
break;
}
head = head->next;
}
}
}
return ret;
}
void TestHashTable(int argc, char *argv[])
{
printf("%d parameter(s): ", argc);
for (char i = 1; i < argc; i++) {
printf("%s ", argv[i]);
}
printf("\r\n");
if(argc == 4 && argv[1][0] == '1') {// x.c 1 key val
int val = insert_kv(argv[2], argv[3]);
if(val == NOT_EXIST_VAL) {
printf("insert key (%s), val (%s) success\n", argv[2], argv[3]);
}else {
printf("insert key (%s), val (%s) repeat, old value (%d) is overwritten\n", argv[2], argv[3], 1);
}
}else if(argc == 3 && argv[1][0] == '2') {// x.c 2 key
int val = query_key(argv[2]);
if(val == NOT_EXIST_VAL) {
printf("query key(%s), not exist\n", argv[2]);
}else {
printf("query key(%s), answer: %d\n", argv[2], val);
}
}else if(argc == 3 && argv[1][0] == '3') {// x.c 3 key
// del
int val = delete_key(argv[2]);
if(val == NOT_EXIST_VAL) {
printf("delete key(%s), not exist\n", argv[2]);
}else {
printf("delete key(%s), val(%d) success\n", argv[2], val);
}
}else if(argc == 2 && argv[1][0] == 'h') {// x.c help
// help
printf("TestHashTable help:\n");
printf("- 1 key val: insert (key, val), duplicate keys will overwrite old values. Only `int` range data is supported\n");
printf("- 2 key: query key\n");
printf("- 3 key: delete key\n");
printf("- help: help\n");
}
}
PRIV_SHELL_CMD_FUNCTION(TestHashTable, a hashtable sample, PRIV_SHELL_CMD_MAIN_ATTR);
// int main() {
// int n;
// int opt;
// char key[55], val[55];
// printf("input opertion numbers:\n");
// scanf("%d", &n);
// while(n --) {
// printf("\ninput opertion:\n");
// scanf("%d", &opt);
// if(opt == 1) {
// scanf("%s%s", key, val);
// int ret = insert_kv(key, val);
// printf("insert key: %s, val: %s, ret: %d\n", key, val, ret);
// }else if(opt == 2) {
// scanf("%s", key);
// int val = query_key(key);
// printf("query key: %s, answer: %d\n", key, val);
// }else if(opt == 3) {
// scanf("%s", key);
// int val = delete_key(key);
// printf("query key: %s, answer: %d\n", key, val);
// }
// else {
// printf("error opt\n");
// break;
// }
// }
// return 0;
// }
/*
gcc test_hash.c
./a.out
12
1 10 10
2 10
1 1 1
1 1 2
2 2
2 1
3 1
2 1
1 1 10
2 1
*/

View File

@ -0,0 +1,13 @@
const int INF = 0x3f3f3f3f;
#define MOD (1000 + 5)
#define NOT_EXIST_VAL (-INF)
struct Hash_entry {
char *okey;
int key;
int val;
struct Hash_entry *next;
struct Hash_entry *prev;
};