嵌入式解谜日志之数据结构—基本概念
O(1) < O(logn) < O(N) < O(nlogn) < O(n²) (for嵌套)< O(n³) < O(2ⁿ) < O(n!②结构体定义的是指针的引用:(per->ag)特征:支持随机访问--head+5 head[0]O(1)是指一组性质相同的值的集合及定义在此集合上的一些操作的总称。结构体的引用:①结构体的定义是变量的引用:(per.age)#ifndef _SEQLIST_H
数据结构
(1)定义:相互之间存在一种或多种特定关系的数据元素的集合
(2)逻辑结构分类:
- 集合:所有数据在同一集合中,关系平等
- 线性:数据和数据之间一对一的关系
- 树:一对多(目录)
- 图:多对多(地图,网)
(3)物理结构(在内存当中的存储关系)
- 顺序存储:数据存放在连续的存储单位中。逻辑关系和物理关系一致
- 链式:数据存放的存储单位是随机或任意的,可以连续也可以不连续
struct Per数据元素
{
char name;//数据项
int age;
char phone;
}
struct Per list[100]; //数据对象
数据对象为一个集合——》包含了多个数据元素——》数据元素有多个数据项组成——》数据项由变量组成
(4)数据的类型:ADT(abstruct datatype):是指一组性质相同的值的集合及定义在此集合上的一些操作的总称。
抽象数据类型=数学模型+操作
(5)程序=数据+算法
1.算法
- 是解决特定问题求解步骤的描述,计算机中表现为指令的有限序列,每条指令表示一个或多个操作。(函数及函数的调用)
①算法的特征
- 输入输出特性:输入是可选的,输出是必须的(可以没有传参)
- 有穷性:执行的步骤会自动结束,不能是死循环,并且每一步是在可以接受的时间内完成(不能死循环,并且每一步都可以在接受的时间内完成)
- 确定性:同一个输入,会得到唯一的输出
- 可行性:每一个步骤都是可以实现的
②算法设计要求
-
正确性
- 语法正确
- 合法的输入能得到合理的结果
- 对非法的输入,给出满足要求的规格说明
- 对精心选择,甚至刁难的测试都能正常运行,结果正确
-
可读性:便于交流,阅读,理解(画流程图,给程序备注)
-
健壮性:输入非法数据,能进行相应的处理,而不是产生异常
-
高效性:存储低,效率高(代码简化)
③算法时间复杂度分析(衡量算法的好坏)
算法时间复杂度是执行这个算法所花时间的度量。
④时间复杂度推导规则:(事前分析法)
- 用常数1取代运行时间中的所有加法常数
- 在修改后的运行函数中,只保留最高阶项
- 如果最高阶存在且不是1,则取除这个项相乘的常数
⑤常见时间复杂度排序
O(1) < O(logn) < O(N) < O(nlogn) < O(n²) (for嵌套)< O(n³) < O(2ⁿ) < O(n!) < O(nⁿ)
时间复杂度越小越好算法越好
// 示例1:基本循环 int i, sum; // 8 for(10000) // n次循环 { sum = i+sum; // 2n +3 } a = c; b = c; a = d; // 时间复杂度:O(n) // 示例2:数学公式计算 int n; // 4 n = (n+1)*n/2; // 4 // 时间复杂度:O(1) // 示例3:嵌套循环 for(i=0; i<n; i++) // n次 { for(j=0; j<n; j++) // n次 { // 执行操作 } } // 时间复杂度:O(n²)
线性表:零个或多个数据元素的有限序列
顺序表:存储空间是连续的
特征:支持随机访问--head+5 head[0] O(1)
劣势:①插入,删除需要整体移动 O(N)
②不支持动态存储功能。(空间不能随着使用量自动变化,需要手动修改)
(1)线性表特征
- 元素之间是有顺序的
- 如果存在多个元素,第一个元素无前驱,最后一个没有后继
- 其他的元素只有一个前驱和一个后继
- 当线性表元素的个数n(n>=0)定义为线性表的长度
- 当n=0时,为空表
- 在非空的表中每个元素都有一个确定的位置
(2)线性表的常规操作ADT
typedef struct person
{
char name[32];
char sex;
int age;
int score;
}DATATYPE; //给结构体struct person取个别名:DATATYPE
typedef struct list
{
DATATYPE *head; //数组指针
int Tlen; //数组的容量
int Clen; //数组有效元素个数
}Seqlist; //表头结构
/*
* 创建顺序表
* 参数:len - 顺序表的初始容量
* 返回值:成功返回创建的顺序表指针,失败返回NULL
*/
SeqList *CreateSeqList(int len);
/*
* 销毁顺序表
* 参数:list - 要销毁的顺序表指针
* 返回值:0表示成功,非0表示失败
*/
int DestroySeqList(SeqList *list);
/*
* 显示顺序表中的所有元素
* 参数:list - 要显示的顺序表指针
* 返回值:0表示成功,非0表示失败(如顺序表为空或不存在)
*/
int ShowSeqList(SeqList *list);
/*
* 在顺序表尾部插入元素
* 参数:list - 目标顺序表指针;data - 要插入的数据元素
* 返回值:0表示成功,非0表示失败(如顺序表已满)
*/
int InsertTailSeqList(SeqList *list, DATATYPE data);
/*
* 判断顺序表是否已满
* 参数:list - 要判断的顺序表指针
* 返回值:1表示已满,0表示未满,-1表示参数无效
*/
int IsFullSeqList(SeqList *list);
/*
* 判断顺序表是否为空
* 参数:list - 要判断的顺序表指针
* 返回值:1表示为空,0表示非空,-1表示参数无效
*/
int IsEmptySeqList(SeqList *list);
/*
* 在顺序表指定位置插入元素
* 参数:list - 目标顺序表指针;data - 要插入的数据元素;pos - 插入位置(从0开始)
* 返回值:0表示成功,非0表示失败(如位置无效或表已满)
*/
int InsertPosSeqList(SeqList *list, DATATYPE data, int pos);
/*
* 在顺序表中查找指定名称的元素
* 参数:list - 要查找的顺序表指针;name - 要查找的名称字符串
* 返回值:成功返回元素位置索引(从0开始),失败返回-1
*/
int FindSeqList(SeqList *list, char *name);
/*
* 修改顺序表中指定名称元素的数据
* 参数:list - 目标顺序表指针;old - 要修改的元素名称;new - 新的数据
* 返回值:0表示成功,非0表示失败(如未找到对应元素)
*/
int ModifySeqList(SeqList *list, char *old, DATATYPE new);
/*
* 删除顺序表中指定名称的元素
* 参数:list - 目标顺序表指针;name - 要删除的元素名称
* 返回值:0表示成功,非0表示失败(如未找到对应元素)
*/
int DeleteSeqList(SeqList *list, char *name);
/*
* 清空顺序表中的所有元素(保留表结构)
* 参数:list - 要清空的顺序表指针
* 返回值:0表示成功,非0表示失败
*/
int ClearSeqList(SeqList *list);
相关函数:

代码示例
01typedef.c
typedef unsigned int u32_t; // 定义别名
#include <string.h>
typedef struct Per
{
char name[50];
int age;
char phone[50];
} PER;
int main(int argc, char *argv[])
{
u32_t a; // 使用别名定义变量
unsigned int b; // 直接使用原始类型定义变量
struct Per per; // 使用原始结构体名
strcpy(per.name, "zhangsan"); // 1000
per.age = 20;
PER p; // 使用别名定义结构体变量
return 0;
}
运行结果:程序正常编译运行,无输出
结构体的引用:①结构体的定义是变量的引用:(per.age)
②结构体定义的是指针的引用:(per->ag)
内存泄露检测工具
sudo apt-get install valgrind
valgrind ./all
seqlist.h
.h:对应的头文件
目的:防止头文件重复包含带来的重复定义问题
格式:
#ifndef _SEQLIST_H_(文件名转换的)
#define _SEQLIST_H_(声明,宏定义)#endif
#ifndef _SEQLIST_H_
#define _SEQLIST_H_
typedef struct person
{
char name[32];
char sex;
int age;
int score;
} DATATYPE;
typedef struct list
{
// 数组指针(指针指向这个存储数据的连续内存:结构体(数组首元素))
DATATYPE *head;//head:指向数据存储(DATATYPE)的指针,相当于动态数组的首地址
// 数组的容量
int tlen;
// 数组的有效元素个数
int clen;
} SeqList;
// 创建顺序表
SeqList *CreateSeqList(int len);
// 显示顺序表数据
int ShowSeqList(SeqList *list);
// 顺序表尾插
int InsertTailSeqList(SeqList *list, DATATYPE *data);
// 是否满
int IsFullSeqList(SeqList *list);
// 是否空
int IsEmptySeqList(SeqList *list);
// 按位置插入
int InsertPosSeqList(SeqList *list, DATATYPE *data, int pos);
// 查找顺序表
int FindSeqList(SeqList *list, char *name);
// 修改顺序表
int ModifySeqList(SeqList *list, char *old, DATATYPE *newdata);
// 清空表
int ClearSeqList(SeqList *list);
// 销毁顺序表
int DestroySeqList(SeqList *list);
// 删除一个元素
int DeleteSeqList(SeqList *list, char *name);
//获得有效元素个数
int GetSizeSeqList(SeqList *list);
DATATYPE* GetItemSeqlist(SeqList*list, int pos);
#endif
seqlist.c
#include "seqlist.h"//包入自己写的头文件,用""引用
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
SeqList *CreateSeqList(int len)//创建顺序表
{
SeqList *sl = malloc(sizeof(SeqList)); // 分配顺序表结构体内存
//解释sizeof(Seqlist):包含数据存储空间和tlen,clen
if (NULL == sl)
{
perror("CreateSeqList malloc error\n"); // 内存分配失败处理
return NULL;
}
sl->head = malloc(sizeof(DATATYPE) * len); // 分配数据存储空间
//解释sizeof(DATATYPE)*len:相当于有len(传入的个数)个DATATYPE数组
if (NULL == sl->head)
{
perror("CreateSeqList malloc2 error\n"); // 数据空间分配失败处理
return NULL;
}
sl->tlen = len; // 设置总长度
sl->clen = 0; // 初始化当前长度为0
return sl;
//两个结构体的内存空间
}
//list->head:结构名指向结构体中的元素
int InsertTailSeqList(SeqList *list, DATATYPE *data)//顺序表尾插
{
// list->head[list->clen] =*data;//list->clen代表顺序表的数据当前位置,当前位置的数组下标位置
if (IsFullSeqList(list)) // 检查是否已满
{
printf("seqlist is full\n"); // 已满提示
return 1;
}
/*
list->head[list->clen]:表示当前顺序表位置
sizeof(DATATYPE):表示DATATYPE结构体大小
data是DATAYPE结构体类型
*/
memcpy(&list->head[list->clen], data, sizeof(DATATYPE)); // 复制数据到尾部
list->clen++; // 当前长度加1
return 0;
}
int IsFullSeqList(SeqList *list)//判断顺序表是否满
{
return list->clen == list->tlen; // 判断当前有效长度是否等于数组总容量
}
int ShowSeqList(SeqList *list)//遍历顺序表中的数据
{
int len = GetSizeSeqList(list); // 获取当前元素个数
int i = 0;
for (i = 0; i < len; ++i)
{
//解释list->head[i].name:顺序表名指向结构体元素head,但head(数组的首地址)为指针指向另一个结构体,继续指向结构体中的元素name
printf("name:%s sex:%c age:%d score:%d\n", list->head[i].name,
list->head[i].sex, list->head[i].age, list->head[i].score);
};
return 0;
}
/**
* @brief Get the Size Seq List object
*
* @param list 被查询的顺序表
* @return int 顺序表有效元素的个数
*/
int GetSizeSeqList(SeqList *list)
{
return list->clen; // 返回当前元素个数
}
int IsEmptySeqList(SeqList *list)//判断当前长度是否为0
{
return 0 == list->clen;
}
/**
* @brief 按位置插入元素
*
* @param list 待插入的顺序表
* @param data 需要插入的数据
* @param pos 顺序表的下标
* @return int 0 表示成功 1表示失败
*/
int InsertPosSeqList(SeqList *list, DATATYPE *data, int pos)//按位置(pos)插入元素
{
if (IsFullSeqList(list)) // 检查是否已满
{
printf("seqlist is full\n");
return 1;
}
int len = GetSizeSeqList(list);
if (pos < 0 || pos > len) // 检查位置是否合法
{
printf("pos is incorrect\n");
return 1;
}
// 整体后移,让出位置
for (int i = list->clen; i > pos; i--)
{
// list->head[i] = list->head[i - 1];
memcpy(&list->head[i], &list->head[i - 1], sizeof(DATATYPE)); // 后移元素
}
memcpy(&list->head[pos], data, sizeof(DATATYPE)); // 插入新元素
list->clen++; // 当前长度加1
return 0;
}
/**
* @brief 按名字查找信息
*
* @param list 待查询的顺序表
* @param name 要查询的人员信息名字
* @return int 成功的 0>=len-1 失败 -1
*/
int FindSeqList(SeqList *list, char *name)
{
int len = GetSizeSeqList(list);
for (int i = 0; i < len; i++) // 遍历查找
{
if (0 == strcmp(list->head[i].name, name)) // 比较名字
{
return i; // 找到返回位置
}
}
return -1; // 未找到返回-1
}
DATATYPE* GetItemSeqlist(SeqList*list, int pos)// 检查位置是否合法
{
int len = GetSizeSeqList(list);
if (pos < 0 || pos > len)
{
printf("pos is incorrect\n");
return NULL;//返回值为指针类型
}
return &list->head[pos]; // 返回指定位置元素的指针
}
int ModifySeqList(SeqList *list, char *oldname, DATATYPE *newdata)//修改元素
{
int ret = FindSeqList(list, oldname); // 查找要修改的元素
if(-1 == ret) // 未找到
{
printf("modify failure...\n");
return 1;
}
memcpy(&list->head[ret], newdata, sizeof(DATATYPE)); // 修改数据
return 0;
}
// 清空表:原理:将数据重新定位到开头,用新的数据去覆盖
int ClearSeqList(SeqList *list)
{
list->clen = 0; // 将当前长度设为0
return 0;
}
// 销毁顺序表
int DestroySeqList(SeqList *list)
{
free(list->head); // 空间使用的是堆,需要释放数据存储空间
free(list); // 释放顺序表结构体
return 0;
}
int DeleteSeqList(SeqList *list, char *name)//删除一个元素
{
int pos=FindSeqList(list, name);//按名字查找
if(-1==pos)
{
printf("no found per %s\n",name);
return -1;
}
//将该位置之后的说有元素向前移动一位
int i=0;
for (i=pos;i<list->clen-1;i++)
{
memccpy(&list->head[i],&list->head[i+1],sizeof(DATATYPE));
}
list->clen--;//长度减一
return 0;
}
内存泄漏检测工具(命令):sudo apt-get install valgrind
编译:valgrind ./all
堆的空间释放顺序:先释放head,在释放顺序表
main.c
#include<stdio.h>
#include<stdlib.h>
#include"seqlist.h"
int main(int argc, char **argv)
{
SeqList *s1=CreateSeqList(5);//创建一个顺序表
DATATYPE data[] =
{
{"zhangsan", 'm', 20, 80}, // 定义测试数据
{"lisi", 'f', 23, 84},
{"wangmaizi", 'f', 32, 90},
{"guanerge", 'm', 50, 91},
{"liubei", 'm', 51, 92},
};
InsertTailSeqList(s1, &data[0]); // 将data[i]中的数据尾部插入数据
InsertTailSeqList(s1, &data[1]); //dat[i]相当于代表二维数组一整排的元素,所以不用在指向data中的元素
InsertTailSeqList(s1, &data[2]);
InsertPosSeqList(s1,&data[2],1);
ShowSeqList(s1);
char want_name[20]="lisi";
int ret=FindSeqList(s1, want_name);//找lisi的位置,并把位置放在ret中
if(-1==ret)
{
printf("can't find per %s\n",want_name);
}else
{
DATATYPE *tmp=GetItemSeqlist(s1,ret);//检查位置在数据中是否合法
printf("find per,%s %d\n",tmp->name,tmp->score);
}
ModifySeqList(s1,"list",&data[4]);//修改元素
ShowSeqList(s1);//遍历
DestroySeqList(s1);//删除顺序表
//system("pause");
return 0;
}
}

Makefile:工程管理工具(代替gcc用make编译)
1.第一个版本:
#目标名:依赖文件
#第二行的开头是一个tab
all:main.c seqlist.c
gcc main.c seqlist.c -o all
clean://clean为清除,重新编译
//命令 make clean
rm all
2.第二个版本:
#目标名:依赖文件
#第二行的开头是一个tab
#在一条规则中,$^代表依赖文件 $@代表规则中的目标名
#$^,$@都是Makefile的内部变量
all:main.c seqlist.c
gcc $^ -o $@ #使用内部变量简化命令
cp main.c 1.c #添加复制命令
clean:
rm all $^ # 删除可执行文件和源文件
3.第三个版本:(最终版本)
# .o 目标文件
SRC= main.o # 定义源文件列表
SRC+= seqlist.o
DST=all # 定义目标文件名
CC=gcc # 定义编译器
LIB= -lm # 定义链接库
%.o:%.c
$(CC) -c $^ -o $@ # 编译规则:将.c文件编译为.o文件
$(DST):$(SRC)
$(CC) $^ -o $@ $(LIB) # 链接规则:将.o文件链接为可执行文件
clean:
rm $(DST) *.o # 清理规则:删除可执行文件和目标文件
顺序表与链表的实现及应用(含字典功能与操作对比)
使用顺序表实现查字典功能
- 支持连续查询单词,输入
#quit退出程序。- 数据格式示例如下:
seqlist.h
顺序表结构定义及操作接口声明
#ifndef _SEQLIST_H_
#define _SEQLIST_H_
// 数据类型定义:存储单词和释义
typedef struct person {
char word[50]; // 单词字段,最多50字符
char mean[512]; // 释义字段,最多512字符
} DATATYPE;
// 顺序表结构体
typedef struct list {
DATATYPE *head; // 指向动态数组的指针
int tlen; // 数组总容量
int clen; // 当前有效元素个数
} SeqList;
// 函数声明
SeqList *CreateSeqList(int len); // 创建顺序表
int ShowSeqList(SeqList *list); // 显示全部数据
int InsertTailSeqList(SeqList *list, DATATYPE *data); // 尾部插入
int IsFullSeqList(SeqList *list); // 判断是否满
int IsEmptySeqList(SeqList *list); // 判断是否空
int InsertPosSeqList(SeqList *list, DATATYPE *data, int pos); // 按位置插入
int FindSeqList(SeqList *list, char *name); // 查找指定单词
int ModifySeqList(SeqList *list, char *old, DATATYPE *newdata); // 修改数据
int ClearSeqList(SeqList *list); // 清空顺序表
int DestroySeqList(SeqList *list); // 销毁顺序表
int DeleteSeqList(SeqList *list, char *name); // 删除指定元素
int GetSizeSeqList(SeqList *list); // 获取有效元素个数
DATATYPE *GetItemSeqlist(SeqList *list, int pos); // 获取指定位置元素
int ShowSeqListOne(SeqList *list, int inx); // 显示单条记录
#endif
seqlist.c
#include "seqlist.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/**
* 创建顺序表
* @param len 初始容量
* @return 成功返回指针,失败返回 NULL
*/
SeqList *CreateSeqList(int len)
{
SeqList *sl = malloc(sizeof(SeqList));
if (NULL == sl)
{
perror("CreateSeqList malloc error\n");
return NULL;
}
sl->head = malloc(sizeof(DATATYPE) * len);
if (NULL == sl->head)
{
perror("CreateSeqList malloc2 error\n");
return NULL;
}
sl->tlen = len;
sl->clen = 0;
return sl;
}
/**
* 尾部插入数据
* @param list 目标顺序表
* @param data 待插入数据
* @return 0 成功,1 失败(已满)
*/
int InsertTailSeqList(SeqList *list, DATATYPE *data)
{
if (IsFullSeqList(list))
{
printf("seqlist is full\n");
return 1;
}
memcpy(&list->head[list->clen], data, sizeof(DATATYPE)); // 安全拷贝
list->clen++;
return 0;
}
/**
* 判断顺序表是否已满
* @param list 顺序表
* @return 1 满,0 未满
*/
int IsFullSeqList(SeqList *list)
{
return list->clen == list->tlen;
}
/**
* 显示整个顺序表内容
* @param list 顺序表
* @return 0
*/
int ShowSeqList(SeqList *list)
{
int len = GetSizeSeqList(list);
for (int i = 0; i < len; ++i)
{
printf("word:%s mean:%s\n", list->head[i].word, list->head[i].mean);
}
return 0;
}
/**
* 获取顺序表有效元素个数
* @param list 顺序表
* @return 元素个数
*/
int GetSizeSeqList(SeqList *list)
{
return list->clen;
}
/**
* 判断顺序表是否为空
* @param list 顺序表
* @return 1 空,0 非空
*/
int IsEmptySeqList(SeqList *list)
{
return 0 == list->clen;
}
/**
* 在指定位置插入数据
* @param list 顺序表
* @param data 待插入数据
* @param pos 插入位置(0-based)
* @return 0 成功,1 失败
*/
int InsertPosSeqList(SeqList *list, DATATYPE *data, int pos)
{
if (IsFullSeqList(list))
{
printf("seqlist is full\n");
return 1;
}
int len = GetSizeSeqList(list);
if (pos < 0 || pos > len)
{
printf("pos is incorrect\n");
return 1;
}
// 从后往前移动元素,腾出位置
for (int i = list->clen; i > pos; i--)
{
memcpy(&list->head[i], &list->head[i - 1], sizeof(DATATYPE));
}
memcpy(&list->head[pos], data, sizeof(DATATYPE));
list->clen++;
return 0;
}
/**
* 查找指定单词的位置
* @param list 顺序表
* @param name 要查找的单词
* @return 找到返回索引,否则返回 -1
*/
int FindSeqList(SeqList *list, char *name)
{
int len = GetSizeSeqList(list);
for (int i = 0; i < len; i++)
{
if (0 == strcmp(list->head[i].word, name))
{
return i;
}
}
return -1;
}
/**
* 获取指定位置的元素
* @param list 顺序表
* @param pos 位置
* @return 指向该位置元素的指针,非法位置返回 NULL
*/
DATATYPE* GetItemSeqlist(SeqList* list, int pos)
{
int len = GetSizeSeqList(list);
if (pos < 0 || pos >= len) // 修正:pos 应 < len
{
printf("pos is incorrect\n");
return NULL;
}
return &list->head[pos];
}
/**
* 修改指定单词的数据
* @param list 顺序表
* @param oldname 原单词
* @param newdata 新数据
* @return 0 成功,1 失败(未找到)
*/
int ModifySeqList(SeqList *list, char *oldname, DATATYPE *newdata)
{
int ret = FindSeqList(list, oldname);
if (-1 == ret)
{
printf("modify failure...\n");
return 1;
}
memcpy(&list->head[ret], newdata, sizeof(DATATYPE));
return 0;
}
/**
* 清空顺序表(不清除内存)
* @param list 顺序表
* @return 0
*/
int ClearSeqList(SeqList *list)
{
list->clen = 0;
return 0;
}
/**
* 销毁顺序表并释放内存
* @param list 顺序表
* @return 0
*/
int DestroySeqList(SeqList *list)
{
free(list->head);
free(list);
return 0;
}
/**
* 显示指定位置的一条记录
* @param list 顺序表
* @param inx 索引
* @return 0 成功,1 失败
*/
int ShowSeqListOne(SeqList *list, int inx)
{
int len = GetSizeSeqList(list);
if (inx < 0 || inx >= len) // 修正:inx 应 < len
{
printf("pos is incorrect\n");
return 1;
}
printf("word:%s mean:%s\n", list->head[inx].word, list->head[inx].mean);
return 0;
}
顺序表的实现文件,包含所有接口函数的具体实现。
main.c
主程序:加载字典文件,支持交互式查询
#include <stdio.h>
#include <stdlib.h>
#include "seqlist.h"
#include <string.h>
int main(int argc, char** argv)
{
FILE* fp = fopen("/home/linux/dict.txt", "r");
if (NULL == fp)
{
perror("fopen");
return 1;
}
SeqList* sl = CreateSeqList(20000);
if (NULL == sl)
{
fprintf(stderr, "CreateSeqList error\n");
return 1;
}
// 从文件逐行读取并构建字典
// 交互式查询
// 第一部分:从文件读取数据,解析后存入顺序链表(假设sl是顺序链表结构体指针)
while (1)
{
DATATYPE data;
char *word = NULL;
char *mean = NULL;
char linebuf[1024] = {0};
if (NULL == fgets(linebuf, sizeof(linebuf), fp))
{
break; // 文件读取结束
}
word = strtok(linebuf, " ");//strtok 是 C 语言中用于 分割字符串 的函数,作用是按照指定的分隔符,可以 “记住上次切割的位置”
mean = strtok(NULL, "\r"); // 去除回车符
strcpy(data.word, word);
strcpy(data.mean, mean);
InsertTailSeqList(sl, &data);
}
// 交互式查询
while (1)
{
char want_word[50] = {0};
printf("input word: ");
fgets(want_word, sizeof(want_word), stdin); // 输入如 "book\n"
want_word[strlen(want_word) - 1] = '\0'; // 去掉末尾换行符
if (0 == strcmp(want_word, "#quit"))
{
break;
}
int ret = FindSeqList(sl, want_word);
if (-1 == ret)
{
printf("cant find %s\n", want_word);
}
else
{
ShowSeqListOne(sl, ret); // 输出释义
}
}
fclose(fp);
DestroySeqList(sl); // 释放资源
return 0;
}
说明:
fgets会保留换行符\n,因此用strlen(want_word)-1可将其替换为\0,实现去换行。
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐

所有评论(0)