我的实现大概流程:
1)首先用fopen()打开文件,输入任意字符串,然后把字符串的每个字符当成一个节点存入链表;
2)把字符串转换成十六进制数据格式,保存到一个char数组里面,再用fwrite()写入到文件中;
3)然后用快速排序对链表的数据进行排序,打印出来。
具体函数实现看代码。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*
1、实现终端输入任意字符串转十六进制,并保存到文件;
将输入的字符串按照每个节点当做属性值创建链表,链表可遍历查询
2、用快速排序对上面链表数据进行排序
*/
//链表节点
typedef struct Node
{
char data;//数据域
struct Node * next;//指针域,保存逻辑上的下一个
}Node;
//插入节点到链表
Node * Add_Node(Node * head , char * str)
{
int n = strlen(str);//字符串字符个数
Node * p = head;
while(p != NULL && p->next != NULL)//让p走到最后一个节点位置
{
p = p->next;
}
Node * tail = p;//链表尾节点
Node * pnew = NULL;//指向新创建的节点
for(int i = 0;i < n;i++) //把字符串每一个字符作为一个节点存入链表
{
//把数据写入新创建节点
pnew = (Node *)malloc(sizeof(Node));
pnew->data = str[i];
pnew->next = NULL;
//把新节点存入链表
if(head == NULL) //从无到有
{
head = pnew;
tail = pnew;
}
else //从多到少
{
//尾插
tail->next = pnew;
tail = pnew;
}
}
return head;//返回链表首节点的地址
}
//打印链表
void print_list(Node * head)
{
Node * p = head;
while(p)
{
printf("%c ",p->data);
p = p->next;
}
putchar('\n');
}
//销毁链表,防止内存泄漏
void Destroy_list(Node * head)
{
Node * p = head;
while(p)
{
//把节点一个个摘下来 free
head = head->next;
p->next = NULL;
free(p);
p = head;
}
}
//求链表元素个数
int Elem_num(Node * head)
{
int count = 0;
Node * p = head;
while(p)
{
count++;
p = p->next;
}
return count;
}
//根据下标访问链表对应下标的元素 下标从 0 开始
char * Find_data_addr(Node * head,int index)
{
if(head == NULL)
{
printf("List is NULL\n");
return NULL;
}
Node * p = head;
while(index-- && p != NULL)
{
p = p->next;//
}
if(p == NULL)
{
printf("index is error\n");
return NULL;
}
return &(p->data);//返回地址
}
/*
quick_sort : 对链表数据快速排序
@head : 待排序链表
@left : 待排序序列的第一个元素
@right : 待排序序列的最后一个元素
*/
Node * quick_sort(Node * head , int left , int right)
{
if(left >= right) //退出递归
{
return head;
}
char piv = *Find_data_addr(head, left);//基准值
int l = left;
int r = right;//索引
while(l < r)
{
while(l < r && *Find_data_addr(head, r) >= piv)//索引r往左走找比基准值小的元素
{
r--;
}
if(l < r)
{
*Find_data_addr(head, l) = *Find_data_addr(head, r);//交换
}
while(l < r && *Find_data_addr(head, l) < piv)//索引l往右走找比基准值大的元素
{
l++;
}
if(l < r)
{
*Find_data_addr(head, r) = *Find_data_addr(head, l);
}
if(l >= r) //找完了,r的位置就是基准值待插入的位置
{
*Find_data_addr(head, r) = piv;
}
}
//一轮快排之后,序列[left,r-1] 的所有元素都比基准值小,[r+1,right] 都比基准值大
quick_sort(head, left, r - 1);
quick_sort(head, r + 1, right);
}
//字符串转十六进制
void str_to_hex(char *str,int str_len,char *save,int save_len)
{
int ch1,ch2;
int i;
for(i = 0;i < str_len;i++)
{
ch1 = (str[i] & 0xf0) >> 4;//取高位
ch2 = str[i] & 0x0f;
//数字转字符
ch1 += ch1 > 9 ? 0x57 : 0x30;
ch2 += ch2 > 9 ? 0x57 : 0x30;
save[2 * i] = ch1;
save[2 * i + 1] = ch2;
}
}
FILE * fopen_file()
{
char filename[] = "hex.txt";
FILE * fp = fopen(filename , "a+");//读写打开,文件不存在,则创建
//文件存在,打开后,原始读的位置在文件开头,原始写的位置在文件末尾
if(fp == NULL)
{
printf("fopen error!\n");
return NULL;
}
printf("fopen success!\n");
return fp;
}
void fwrite_file(FILE * fp,char * save)
{
int ret;
ret = fwrite(save,1,strlen(save),fp);
if(ret == -1)
{
printf("fwrite error\n");
return ;
}
fflush(fp);//冲洗流,立刻把内存内容写入磁盘
printf("fwrite success!\n");
}
int main()
{
//打开文件
FILE * fp = fopen_file();
char str[128] = {'0'};//保存输入的字符串
char save[128] = {'0'};;//保存字符串转化为十六进制的数据
Node * list = NULL;//初始化空链表
//输入任意字符串
while(scanf("%s",str) != EOF) //循环输入
{
if(strcmp(str,"#") == 0)
{
printf("Iput Over!\n");
break;
}
list = Add_Node(list, str);
str_to_hex(str, strlen(str), save, strlen(str));
printf("%s\n",save);
//写入文件
fwrite_file(fp, save);
}
print_list(list);
int len = Elem_num(list);
//printf("len = %d\n",len);
//printf("%c\n",*Find_data_addr(list, 2));
list = quick_sort(list, 0, len - 1);//快速排序
printf("After Quick Sort:\n");
print_list(list);
Destroy_list(list);
return 0;
}
最后:
我把代码写在一个.c了,有精力可以分模块写,.c .h分开写,再搞个Makefile啥的。