2023_open_source_contest_warmup_1st_issue1

This commit is contained in:
yanglong 2023-06-17 21:31:14 +08:00
parent 062b70f073
commit 5675b77101
7 changed files with 651 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_TEST_HASH
bool "Config test hash"
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_TEST_HASH),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,301 @@
# 热身赛一级赛题1基于cortex-m3-emulator实现哈希表并测试验证
## 1. 简介
本项目是基于cortex-m3-emulator实现哈希表并测试验证
test_hash.h定义所需要的宏结构体函数声明
test_hash.c用于实现哈希表的创建、删除、增删改查等具体操作以及构建测试函数并且注入到shell中
## 2. 数据结构设计说明
- 通过数组和链表实现哈希表链地址法解决哈希冲突默认数组长度TABLE_SIZE节点数据结构Entry哈希表数据结构HashTable
```c
/* the size of hash table */
#define TABLE_SIZE (1024)
/* element of the hash table's chain list */
struct Entry
{
char* key;
void* value;
struct Entry* next;
void (*FreeValue)(void*);
};
/* HashTable */
typedef struct
{
struct Entry ** table;
}HashTable;
```
- 定义哈希表的创建、删除、增删改查
```c
/* new an instance of HashTable */
HashTable* HashTableNew();
/*
delete an instance of HashTable,
all values are removed auotmatically.
*/
void HashTableDelete(HashTable* ht);
/*
add or update a value to ht,
free_value(if not NULL) is called automatically when the value is removed.
return 0 if success, -1 if error occurred.
*/
int HashTablePut(HashTable* ht, char* key, void* value);
int HashTablePut2(HashTable* ht, char* key, void* value, void(*free_value)(void*));
/* get a value indexed by key, return NULL if not found. */
void* HashTableGet(HashTable* ht, char* key);
/* remove a value indexed by key */
void HashTableRemove(HashTable* ht, char* key);
```
- 实现哈希表的创建、删除、增删改查
```c
/* constructor of struct Entry */
static void InitEntry(struct Entry* entry)
{
entry->key = NULL;
entry->value = NULL;
entry->next = NULL;
entry->FreeValue = NULL;
}
/* destructor of struct Entry */
static void FreeEntry(struct Entry* entry)
{
if (entry){
if (entry->FreeValue){
entry->FreeValue(entry->value);
}
free(entry->key);
entry->key = NULL;
free(entry);
}
}
/* the classic Times33 hash function */
static unsigned int Hash33(char* key)
{
unsigned int hash = 0;
while (*key){
hash = (hash << 5) + hash + *key++;
}
return hash;
}
/* new a HashTable instance */
HashTable* HashTableNew()
{
HashTable* hash_table = malloc(sizeof(HashTable));
if (NULL == hash_table){
HashTableDelete(hash_table);
return NULL;
}
hash_table->table = malloc(sizeof(struct Entry*) * TABLE_SIZE);
if (NULL == hash_table->table){
HashTableDelete(hash_table);
return NULL;
}
memset(hash_table->table, 0, sizeof(struct Entry*) * TABLE_SIZE);
return hash_table;
}
/* delete a HashTable instance */
void HashTableDelete(HashTable* hash_table)
{
if (hash_table){
if (hash_table->table){
int i = 0;
for (i = 0; i < TABLE_SIZE; i++){
struct Entry* p = hash_table->table[i];
struct Entry* q = NULL;
while (p){
q = p->next;
FreeEntry(p);
p = q;
}
}
free(hash_table->table);
hash_table->table = NULL;
}
free(hash_table);
}
}
/* insert or update a value indexed by key without FreeValue */
int HashTablePut(HashTable* hash_table, char* key, void* value)
{
return HashTablePut2(hash_table,key,value,NULL);
}
/* insert or update a value indexed by key with FreeValue */
int HashTablePut2(HashTable* hash_table, char* key, void* value, void(*FreeValue)(void*))
{
int i = Hash33(key) % TABLE_SIZE;
struct Entry* p = hash_table->table[i];
struct Entry* prep = p;
char* key_str = malloc(strlen(key) + 1);
if (key_str == NULL){
return -1;
}
char* value_str = malloc(strlen(value) + 1);
if (value_str == NULL){
return -1;
}
strcpy(key_str, key);
strcpy(value_str,value);
while (p){ /* if key is already stroed, update its value */
if (strcmp(p->key, key) == 0){
if (p->FreeValue) {
p->FreeValue(p->value);
}
p->value = value_str;
p->FreeValue = FreeValue;
break;
}
prep = p;
p = p->next;
}
if (p == NULL){ /* if key has not been stored, then add it */
struct Entry * entry = malloc(sizeof(struct Entry));
if (NULL == entry){
free(key_str);
key_str = NULL;
free(value_str);
value_str = NULL;
return -1;
}
InitEntry(entry);
entry->next = NULL;
entry->key = key_str;
entry->value = value_str;
entry->FreeValue = FreeValue;
if (prep == NULL){
hash_table->table[i] = entry;
}
else{
prep->next = entry;
}
}
return 0;
}
/* get a value indexed by key */
void* HashTableGet(HashTable* hash_table, char* key)
{
int i = Hash33(key) % TABLE_SIZE;
struct Entry* p = hash_table->table[i];
while (p){
if (strcmp(key, p->key) == 0){
return p->value;
}
p = p->next;
}
return NULL;
}
/* remove a value indexed by key */
void HashTableRemove(HashTable* hash_table, char* key)
{
int i = Hash33(key) % TABLE_SIZE;
struct Entry* p = hash_table->table[i];
struct Entry* prep = p;
while (p){
if (strcmp(key, p->key) == 0) {
FreeEntry(p);
if (p == prep) {
hash_table->table[i] = NULL;
}
else {
prep->next = p->next;
}
}
prep = p;
p = p->next;
}
}
```
## 3. 测试程序说明
- 测试哈希表的基本操作
```c
/* the test order menu */
void ShowMenu()
{
printf("================order menu================\n");
printf("==========0:insert(TestHash 0 x 2)========\n");
printf("==========1:get(TestHash 1 x)=============\n");
printf("==========2:update(TestHash 2 x 1)========\n");
printf("==========3:remove(TestHash 3 x)==========\n");
}
HashTable* hash_table = NULL;
/* test for hash table*/
void TestHash(int argc, char* argv[])
{
if (argc == 1){
printf("please use TestHash help to check orders\n");
return;
}
if (strcmp(argv[1],"help") == 0) ShowMenu();
if (strcmp(argv[1],"0") == 0){ // insert
if(hash_table == NULL){
hash_table = HashTableNew();
}
HashTablePut(hash_table,argv[2],argv[3]);
char* value = (char*)HashTableGet(hash_table,argv[2]);
printf("insert key=%s,val=%s; sucessful!\n",argv[2],value);
}else if (strcmp(argv[1],"1") == 0){ // get
if(hash_table == NULL){
printf("error: hash table is NULL. please insert first.\n");
return;
}
char* value = (char*)HashTableGet(hash_table,argv[2]);
if (value == NULL){
printf("without such key(%s)\n",argv[2]);
}else{
printf("get key=%s,value=%s; answer=%s\n",argv[2],value,value);
}
}else if (strcmp(argv[1],"2") == 0){ // update
if (hash_table == NULL){
printf("error: hash table is NULL. please insert first.\n");
return;
}
char* value = (char*)HashTableGet(hash_table,argv[2]);
if (value == NULL){
printf("without such key(%s). please insert first.\n",argv[2]);
}else{
HashTablePut(hash_table,argv[2],argv[3]);
printf("update key=%s,old_value=%s,value=%s; sucessful\n",argv[2],value,argv[3]);
}
}else if (strcmp(argv[1],"3") == 0){ // remove
if (hash_table == NULL){
printf("error: hash table is NULL. please insert first.\n");
return;
}
HashTableRemove(hash_table,argv[2]);
printf("remove key=%s; sucessful!\n",argv[2]);
}
return;
}
PRIV_SHELL_CMD_FUNCTION(TestHash, a hash test sample, PRIV_SHELL_CMD_MAIN_ATTR);
```
## 4. 运行结果(##需结合运行测试截图按步骤说明##
1. 输入help查看letter shell可以调用的命令
2. 输入TestHash命令提示用TestHash help查看TestHash的命令
3. 没有插入元素就查看元素TestHash 1 x --> 哈希表为空,提示先插入
4. 没有插入就删除元素TestHash 3 x --> 哈希表为空,提示先插入
5. 插入x=2: TestHash 0 x 2
6. 查找x: TestHash 1 x
7. 更新x=100: TestHash 2 x 100
8. 查找更新后的x: TestHash 1 x
9. 删除x: TestHash 3 x
10. 确认是否被删除: TestHash 1 x
![](./test.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -0,0 +1,260 @@
/*
* 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 table
* @version: 1.0
* @author: bdislab_final
* @date: 2023/6/17
*/
#include "test_hash.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <transform.h>
#ifdef ADD_XIZI_FETURES
/* constructor of struct Entry */
static void InitEntry(struct Entry* entry)
{
entry->key = NULL;
entry->value = NULL;
entry->next = NULL;
entry->FreeValue = NULL;
}
/* destructor of struct Entry */
static void FreeEntry(struct Entry* entry)
{
if (entry){
if (entry->FreeValue){
entry->FreeValue(entry->value);
}
free(entry->key);
entry->key = NULL;
free(entry);
}
}
/* the classic Times33 hash function */
static unsigned int Hash33(char* key)
{
unsigned int hash = 0;
while (*key){
hash = (hash << 5) + hash + *key++;
}
return hash;
}
/* new a HashTable instance */
HashTable* HashTableNew()
{
HashTable* hash_table = malloc(sizeof(HashTable));
if (NULL == hash_table){
HashTableDelete(hash_table);
return NULL;
}
hash_table->table = malloc(sizeof(struct Entry*) * TABLE_SIZE);
if (NULL == hash_table->table){
HashTableDelete(hash_table);
return NULL;
}
memset(hash_table->table, 0, sizeof(struct Entry*) * TABLE_SIZE);
return hash_table;
}
/* delete a HashTable instance */
void HashTableDelete(HashTable* hash_table)
{
if (hash_table){
if (hash_table->table){
int i = 0;
for (i = 0; i < TABLE_SIZE; i++){
struct Entry* p = hash_table->table[i];
struct Entry* q = NULL;
while (p){
q = p->next;
FreeEntry(p);
p = q;
}
}
free(hash_table->table);
hash_table->table = NULL;
}
free(hash_table);
}
}
/* insert or update a value indexed by key without FreeValue */
int HashTablePut(HashTable* hash_table, char* key, void* value)
{
return HashTablePut2(hash_table,key,value,NULL);
}
/* insert or update a value indexed by key with FreeValue */
int HashTablePut2(HashTable* hash_table, char* key, void* value, void(*FreeValue)(void*))
{
int i = Hash33(key) % TABLE_SIZE;
struct Entry* p = hash_table->table[i];
struct Entry* prep = p;
char* key_str = malloc(strlen(key) + 1);
if (key_str == NULL){
return -1;
}
char* value_str = malloc(strlen(value) + 1);
if (value_str == NULL){
return -1;
}
strcpy(key_str, key);
strcpy(value_str,value);
while (p){ /* if key is already stroed, update its value */
if (strcmp(p->key, key) == 0){
if (p->FreeValue) {
p->FreeValue(p->value);
}
p->value = value_str;
p->FreeValue = FreeValue;
break;
}
prep = p;
p = p->next;
}
if (p == NULL){ /* if key has not been stored, then add it */
struct Entry * entry = malloc(sizeof(struct Entry));
if (NULL == entry){
free(key_str);
key_str = NULL;
free(value_str);
value_str = NULL;
return -1;
}
InitEntry(entry);
entry->next = NULL;
entry->key = key_str;
entry->value = value_str;
entry->FreeValue = FreeValue;
if (prep == NULL){
hash_table->table[i] = entry;
}
else{
prep->next = entry;
}
}
return 0;
}
/* get a value indexed by key */
void* HashTableGet(HashTable* hash_table, char* key)
{
int i = Hash33(key) % TABLE_SIZE;
struct Entry* p = hash_table->table[i];
while (p){
if (strcmp(key, p->key) == 0){
return p->value;
}
p = p->next;
}
return NULL;
}
/* remove a value indexed by key */
void HashTableRemove(HashTable* hash_table, char* key)
{
int i = Hash33(key) % TABLE_SIZE;
struct Entry* p = hash_table->table[i];
struct Entry* prep = p;
while (p){
if (strcmp(key, p->key) == 0) {
FreeEntry(p);
if (p == prep) {
hash_table->table[i] = NULL;
}
else {
prep->next = p->next;
}
}
prep = p;
p = p->next;
}
}
/* the test order menu */
void ShowMenu()
{
printf("================order menu================\n");
printf("==========0:insert(TestHash 0 x 2)========\n");
printf("==========1:get(TestHash 1 x)=============\n");
printf("==========2:update(TestHash 2 x 1)========\n");
printf("==========3:remove(TestHash 3 x)==========\n");
}
HashTable* hash_table = NULL;
/* test for hash table*/
void TestHash(int argc, char* argv[])
{
if (argc == 1){
printf("please use TestHash help to check orders\n");
return;
}
if (strcmp(argv[1],"help") == 0) ShowMenu();
if (strcmp(argv[1],"0") == 0){ // insert
if(hash_table == NULL){
hash_table = HashTableNew();
}
HashTablePut(hash_table,argv[2],argv[3]);
char* value = (char*)HashTableGet(hash_table,argv[2]);
printf("insert key=%s,val=%s; sucessful!\n",argv[2],value);
}else if (strcmp(argv[1],"1") == 0){ // get
if(hash_table == NULL){
printf("error: hash table is NULL. please insert first.\n");
return;
}
char* value = (char*)HashTableGet(hash_table,argv[2]);
if (value == NULL){
printf("without such key(%s)\n",argv[2]);
}else{
printf("get key=%s,value=%s; answer=%s\n",argv[2],value,value);
}
}else if (strcmp(argv[1],"2") == 0){ // update
if (hash_table == NULL){
printf("error: hash table is NULL. please insert first.\n");
return;
}
char* value = (char*)HashTableGet(hash_table,argv[2]);
if (value == NULL){
printf("without such key(%s). please insert first.\n",argv[2]);
}else{
HashTablePut(hash_table,argv[2],argv[3]);
printf("update key=%s,old_value=%s,value=%s; sucessful\n",argv[2],value,argv[3]);
}
}else if (strcmp(argv[1],"3") == 0){ // remove
if (hash_table == NULL){
printf("error: hash table is NULL. please insert first.\n");
return;
}
HashTableRemove(hash_table,argv[2]);
printf("remove key=%s; sucessful!\n",argv[2]);
}
return;
}
PRIV_SHELL_CMD_FUNCTION(TestHash, a hash test sample, PRIV_SHELL_CMD_MAIN_ATTR);
#endif

View File

@ -0,0 +1,74 @@
/*
* 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.h
* @brief a application of hash table
* @version 1.0
* @author bdislab_final
* @date 2023/6/17
*/
#ifndef TEST_HASH_H
#define TEST_HASH_H
#ifdef __cplusplus
extern "C" {
#endif
/* the size of hash table */
#define TABLE_SIZE (1024)
/* element of the hash table's chain list */
struct Entry
{
char* key;
void* value;
struct Entry* next;
void (*FreeValue)(void*);
};
/* HashTable */
typedef struct
{
struct Entry ** table;
}HashTable;
/* new an instance of HashTable */
HashTable* HashTableNew();
/*
delete an instance of HashTable,
all values are removed auotmatically.
*/
void HashTableDelete(HashTable* ht);
/*
add or update a value to ht,
free_value(if not NULL) is called automatically when the value is removed.
return 0 if success, -1 if error occurred.
*/
int HashTablePut(HashTable* ht, char* key, void* value);
int HashTablePut2(HashTable* ht, char* key, void* value, void(*free_value)(void*));
/* get a value indexed by key, return NULL if not found. */
void* HashTableGet(HashTable* ht, char* key);
/* remove a value indexed by key */
void HashTableRemove(HashTable* ht, char* key);
#ifdef __cplusplus
}
#endif
#endif

7
run.sh Executable file
View File

@ -0,0 +1,7 @@
#!/bin/bash
cd /home/yanglong/Desktop/xiuos/xiuos/Ubiquitous/XiZi_IIoT
make BOARD=cortex-m3-emulator distclean
make BOARD=cortex-m3-emulator menuconfig
make BOARD=cortex-m3-emulator
sleep
qemu-system-arm -machine lm3s6965evb -nographic -kernel build/XiZi-cortex-m3-emulator.elf