C和指针,第十二章,第七题

一开始我有些想法,但是懒得写测试用例,所以打算用chatgpt生成,结果不能用,所以又专门花时间重新写了这题。

chatgpt对代码的理解,可以用来纠错和问问题,但是全部工作交给它做,很明显他还不能胜任,不过如果chatgpt能干完所有事,那么程序员也可以大规模淘汰了,所幸它还没有这样的能力,暂时不用紧张,不过以后可不好说。

也有可能是我用的免费,加上用户访问量比较大的问题,如果是付费版,我这点任务他应该是能全部完成的,但是细节上,还是需要自己修改,比如释放链表时,ChatGPT就很明显没有考虑到二级链表的多个结构,只是释放了一个,然后就释放一级列表,所以我参考了他的代码后重写了释放内存的函数。

这题中,只有测试用例和函数名由ChatGPT给出,其他由本人原创完成,代码简单,逻辑简单,语句没有优化精简。

念在初学的份上,请多宽恕宽恕。

/**
 * @file point_seven.c
 * @author your name (you@domain.com)
 * @brief 把一个单词插入到索引表中,本题是第十二章第七题,也是chatgpt生成
 * 因为我大概知道该怎么写了,但是懒得写测试用例,所以选择了Ai帮忙
 * 
 * 我发现Ai写的有点问题,可能是复制的原因,我明天重新写过,还是不能偷懒
 * @version 0.1
 * @date 2023-03-13
 * 
 * @copyright Copyright (c) 2023
 * 
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>

/**
 * @brief 二级链表的节点结构体,存储一个单词和指向下一个节点的指针
 */
struct WordNode {
    char* word;             /**< 节点存储的单词 */
    struct WordNode* next;  /**< 指向下一个二级链表节点的指针 */
};
/**
 * @brief 一级链表的节点结构体,存储一个字母和一个指向该字母对应的二级链表的指针
 */
typedef struct Node {
    char letter;            /**< 节点存储的字母 */
    struct WordNode* words; /**< 指向该字母对应的二级链表的指针 */
    struct Node* next;      /**< 指向下一个一级链表节点的指针 */
} Node;



/**
 * 打印索引表中所有单词的信息
 * @param index 索引表的头指针
 */
/**
 * 打印索引表中的所有单词及其对应的页码
 * 
 * @param index 索引表
 */
void printIndexList(Node *index);
 

/**
 * @brief 清空索引表
 * 
 * @param index 指向一级链表的指针
 */
void clearIndexList(Node** index);


/**

@brief 用于插入单词到索引表中

@param list 一个指向指向一级链表的指针的指针

@param word 要插入的单词字符串

@return true 插入成功

@return false 插入失败
*/
bool insertWordToList(Node** list, char* word);
int main()
{
    // 定义索引表指针
    struct Node* index = NULL;
    char *word[] = {"apple","abple","Banana","cherry", "orange"};
    // 测试插入新单词,返回真
    bool success = insertWordToList(&index, word[0]);
    printf("Insert 'apple' success? %d\n", success);

    // 测试插入已存在的单词,返回假
    success = insertWordToList(&index, word[0]);
    printf("Insert 'apple' success? %d\n", success);

    //测试单词插入效果,也可以修改首字母大小写查看排序效果。
    success = insertWordToList(&index, word[0]);
    printf("Insert 'abple' success? %d\n", success);

    // 测试插入非字母开头的单词,返回假
    success = insertWordToList(&index, "123");
    printf("Insert '123' success? %d\n", success);

    // 测试插入新单词,返回真
    success = insertWordToList(&index, word[2]);
    printf("Insert 'banana' success? %d\n", success);

    // 测试插入新单词,返回真
    success = insertWordToList(&index, word[3]);
    printf("Insert 'cherry' success? %d\n", success);

    // 测试插入新单词,返回真
    success = insertWordToList(&index, word[4]);
    printf("Insert 'orange' success? %d\n", success);

    // 打印索引表
    printf("\nIndex list:\n");
    printIndexList(index);

    // 释放索引表内存
    clearIndexList(&index);
    system("pause");
    return 0;
}

bool insertWordToList(Node** list, char* word)
{
    Node *prev = *list; //记录当前一级指针,字母。
    Node *curr = prev; //当前一级指针。
    if(word == NULL || word[0] == '\0'){
        printf("the word is empty");
        return false;
    }
    if(!isalpha(word[0]))//第一位不是字母直接返回
        return false;
    
    int flag = 0;//效验索引是否存在
    while(curr != NULL ) //查找单词是否重复
    {
        if(curr->letter == word[0])//查看索引首字母是否相同
        {
            flag = 1;
            struct WordNode * this = curr->words;
            while(this != NULL)//查找是否有相同单词
            {
                if(strcmp(this->word,word) == 0)
                    return false;
                this = this->next;
            }
        }
        curr = curr->next;
    }

    if(flag == 0)//建立索引
    {
        Node * new = (Node *)malloc(sizeof(Node));
        new->words = NULL;
        new->next = NULL;
        if(new == NULL)
            return false;
        new->letter = word[0];
        curr = prev;//指针指向链头
        if(curr != NULL){
            Node * temp = NULL;
            int fl = 0;//效验位,效验是否成功插入,如果没有说明比所有元素都小,插入到链尾
            while (curr != NULL)//一级指针字母排序
            {
                if(new->letter < curr->letter)
                {
                    if(curr == prev){
                        new->next = *list;
                        *list = new;
                        fl = 1;
                        break;
                    }
                    else{
                        new->next = curr;
                        temp->next = new;
                        fl = 1;
                        break;
                    }
                }
                temp = curr;
                curr = curr->next;
            }
            if(fl == 0)
            {
                new->next = NULL;
                temp->next = new;
            }
        }
        else{
            new->next = NULL;
            *list  = new;
        }
    }
    prev = *list;//重新记录更新后的链头
    struct WordNode * str = (struct WordNode *)malloc(sizeof(struct WordNode)); // 建立二级链表储存单词
    str->next = NULL;
    str->word = word;//本质上是二级链表指针指向输入过来的单词位置,储存位置还是在原来的内存,如果要把数据存在结构中最好还是开辟一点内存,这样不会改动原字符串
    curr = prev; // 回到一级链表头
    while (curr != NULL)
    {
        if(curr->letter == word[0])//找到对应的字母
        {
            struct WordNode * this = curr->words;
            struct WordNode * root = this;//初始指针用于特殊情况,更新头指针
            struct WordNode * prev = NULL;//保存上一个节点
            if(this == NULL)
            {
                str->next = NULL;
                curr->words = str;
                break;
            }
            while(this != NULL){//比较单词排序
                if(strcmp(str->word,this->word) < 0)
                {
                    if(this == root)
                    {
                        str->next = this;
                        curr->words = str;
                        break;
                    }
                    else {
                        str->next = this;
                        prev->next = str;
                        break;
                    }
                }
                else{//如果上面没执行,说明在链尾
                        str->next = NULL;
                        this->next = str;
                        break;
                }
                prev = this;
                this = this->next;
        }
        }
        curr = curr->next;
    }
    return true;
}
    


void printIndexList(Node *index)
{
    Node * curr = index;
    while (curr != NULL)
    {
        printf("首字母: %c\n",curr->letter);
        struct WordNode * second= curr->words;//二级指针
        printf("单词: ");
        while (second != NULL)
        {
            printf("%s ",second->word);
            second = second->next;
        }
        printf("\n");
        curr = curr->next;
    }
    
}

void clearIndexList(Node** index)
{
     if (*index == NULL) {
        return;
    }
    
    Node * prev = *index;
    while (prev != NULL)
    {
        struct WordNode * second = prev->words;//指向第二级链表的指针
        struct WordNode * temp = NULL;//临时指针
        while (second != NULL)
        {
            temp = second;
            second = second->next;
            free(temp);
        }
        
        clearIndexList(&prev->next);
        Node *tempNode = prev;
        prev = prev->next;
        free(tempNode);
    }
    
    *index = NULL;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值