单链表——小练习题

来源:互联网 发布:如何关闭mac开机声音 编辑:程序博客网 时间:2024/05/19 05:01
/*********************************************************************************************
    2、一种日志文件的格式,每行是一条记录,由行号、日期、时间三个字段组成,
由于记录是按时间先后顺序写入的,可以看作所有记录是按日期排序的,对于日期相同的记录再按时间排序。
现在要求从这样的一个日志文件中读出所有记录组成一个链表,在链表中首先按时间排序,对于时间相同的记录再按日期排序,
最后写回文件中。

比如原文件的内容是:
    1 2009-7-30 15:16:42
    2 2009-7-30 15:16:43
    3 2009-7-31 15:16:41
    4 2009-7-31 15:16:42
    5 2009-7-31 15:16:43
    6 2009-7-31 15:16:44

重新排序输出的文件内容是:
    1 2009-7-31 15:16:41
    2 2009-7-30 15:16:42
    3 2009-7-31 15:16:42
    4 2009-7-30 15:16:43
    5 2009-7-31 15:16:43
    6 2009-7-31 15:16:44

***********************************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>

typedef struct day
{
    unsigned char    day;
    unsigned char    mouth;
    unsigned short    year;
}Day;

typedef struct time
{
    unsigned char    second;
    unsigned char    minute;
    unsigned char    hour;
}Time;

typedef struct Record
{
    char        pRecord[24];
    Day            day;
    Time        time;
    struct Record    *next;
}RecordNode;

void CreateLinkListHead(RecordNode **pHead)
{
    *pHead = (RecordNode *)malloc(sizeof(RecordNode));
    assert(NULL != *pHead);

    (*pHead)->next = NULL;
}

int GetLine(FILE *pFile, char line[])
{
    assert(NULL != pFile);
    int iCharaterNumber = 0;
    char elem;

    while(((elem = fgetc(pFile)) != EOF) && (elem != '\n'))
    {
        line[iCharaterNumber++] = elem;
    }

    line[iCharaterNumber] = '\0';

    return    iCharaterNumber; /*返回每一行的字符数,返回0时结束*/
}

void ReadFile(RecordNode *pHead)
{
    RecordNode *pHelpNode = pHead;
    char line[24];
    memset(line, 0, sizeof(line));

    FILE *pFile = fopen("record_by_date", "r"); /*打开读文件*/
    if(NULL == pFile)
    {
        perror("fopen record_by_date file error ! \n");
        exit(1);
    }

    while(GetLine(pFile, line) > 0) /*获取文件的每一行内容,存放到line[] 数组中*/
    {
        RecordNode *pNode = (RecordNode *)malloc(sizeof(RecordNode));
        memset(pNode, 0, sizeof(RecordNode));
        assert(NULL != pNode);

        strncpy(pNode->pRecord, line, sizeof(line)); /*获取的每一行的内容存放到分配的结点中去*/
        pNode->next = NULL;

        pHelpNode->next = pNode;
        pHelpNode = pNode;

        memset(line, 0, sizeof(line));
    }

    fclose(pFile); /*关闭读文件*/
}

void GetTime(const RecordNode *pNode, char time[])
{
    char str[24];
    memset(str, 0, sizeof(str));
    strncpy(str, pNode->pRecord, sizeof(str));

    char *token = strtok(str, " ");
    while((token = strtok(NULL, " ")) != NULL)
    {
        strcpy(time, token); /*从结点的时间字符串中获取出来*/
    }
}

RecordNode * GetNode(RecordNode *pHead)
{
    RecordNode *pNode = pHead->next;
    if(NULL != pNode)
    {
        pHead->next = pNode->next;
        return    pNode;
    }
    else
    {
        return    NULL;
    }
}

void SetTime(RecordNode *pNode, char time[])
{
    char second[3];
    char minute[3];
    char hour[3];

    memset(second, 0, sizeof(second));
    memset(minute, 0, sizeof(minute));
    memset(hour, 0, sizeof(hour));

    strncpy(hour, time, 2);
    strncpy(minute, time+3, 2);
    strncpy(second, time+6, 2);

    pNode->time.second = (char)atoi(second);
    pNode->time.minute = (char)atoi(minute);
    pNode->time.hour = (char)atoi(hour);
}

RecordNode * SearchNode(RecordNode *pNewHead, RecordNode *pNode)
{
    RecordNode *pHelpNode = pNewHead->next;
    while(pHelpNode)
    {
        if(pHelpNode->time.hour > pNode->time.hour)
        {
            break;
        }
        else if(pHelpNode->time.minute > pNode->time.minute)
        {
            break;
        }
        else if(pHelpNode->time.second > pNode->time.second)
        {
            break;
        }
        else
        {
            pHelpNode = pHelpNode->next;
        }
    }

    if(pHelpNode == NULL)
    {
        pHelpNode = pNewHead->next;
        while(pHelpNode->next)
        {
            pHelpNode = pHelpNode->next;
        }

        return    pHelpNode;
    }
    else
    {
        RecordNode *preNode = pNewHead;
        while(preNode->next != pHelpNode)
        {
            preNode = preNode->next;
        }

        return    preNode;
    }
}

void CreateNewLinkList(RecordNode *pNewHead, RecordNode *pNode)
{
    RecordNode *pHelpNode = pNewHead->next;
    if(pHelpNode == NULL)
    {
        pNewHead->next = pNode;
        pNode->next = NULL;
    }
    else
    {
        pHelpNode = SearchNode(pNewHead, pNode); /*找到插入点*/
        pNode->next = pHelpNode->next;
        pHelpNode->next = pNode;
    }
}

void Modify(RecordNode *pHead)
{
    unsigned int num = 1;
    char *token = NULL;
    char str[24] = {0};

    RecordNode *pNode = pHead->next;
    while(pNode)
    {
        strncpy(str, pNode->pRecord, sizeof(str)); /*用临时数组把原结点的字符串储存起来*/
        token = strtok(str, " "); /*token指向前面的序号*/

        memset(str, 0, sizeof(str));
        sprintf(str, "%u", num); /*按时间顺序把序号写入到临时数组*/
        str[strlen(str)] = ' '; /*小心序号后面有一个空格*/

        strcat(str, pNode->pRecord+strlen(token)); /*按时间顺序修改好完整的字符串保存到临时数组*/
        strncpy(pNode->pRecord, str, sizeof(str)); /*写回原结点*/

        pNode = pNode->next;
        num++;
    }
}

void DestroyNode(RecordNode *pHead)
{
    RecordNode *pNode = pHead->next;
    while(pNode)
    {
        pHead->next = pNode->next;
        free(pNode);
        pNode = pHead->next;
    }

    free(pHead);
    pHead = NULL;
}

void WriteFile(RecordNode *pHead)
{
    char time[12];

    memset(time, 0, sizeof(time));

    FILE *pFile = fopen("record_by_time", "w"); /*打开写文件*/
    assert(NULL != pFile);

    RecordNode *pNewHead = (RecordNode *)malloc(sizeof(RecordNode)); /*分配一个新的头结点,用来存放排序后的结点*/
    memset(pNewHead, 0, sizeof(RecordNode));

    pNewHead->next = NULL;
    RecordNode *pNode = NULL;
    while((pNode = GetNode(pHead)) != NULL)
    {
        GetTime(pNode, time); /*从pNode结点里面获取最后的时间字符串,存放到time[]数组中去*/

        SetTime(pNode, time); /*time[] 数组的时间字符从,写入到pNode结点的结构体时间成员中去*/

        CreateNewLinkList(pNewHead, pNode); /*按照时间顺序排序后的结点插入到新的链表中去*/
    }

    free(pHead);
    pHead = pNewHead;

    Modify(pHead); /*把每个结点按日期顺序的序号修改为按时间数序的序号*/

    pNode = pHead->next;
    while(pNode)
    {
        fputs(pNode->pRecord, pFile);
        fputc('\n', pFile); /*每写入一个结点记得要换行*/

        printf("write : %s \n", pNode->pRecord);
        pNode = pNode->next;
    }

    fclose(pFile); /*关闭写文件*/

    DestroyNode(pHead); /*最后释放所有结点的空间*/
}

int main(void)
{
    RecordNode    *pHead = NULL;

    CreateLinkListHead(&pHead); /*创建文件内容行的头结点*/
    
    ReadFile(pHead); /*读取文件的每一行,存放到链表的每一个结点*/
    
    WriteFile(pHead); /*从record_by_date文件中读取的每一行内容按时间迅速写到record_by_time文件中去*/

    return    0;
}
0 0
原创粉丝点击