AI大法之C语言哈希表算法比较两个文件去重

最近朋友在工作上遇到了一个问题,经常需要比对两个文件,筛选出文件中不同的订单号。比如有两个文件:计费.txt受理.txt,文件中每一行都是一个订单号,需要找出计费.txt文件中有而受理.txt文件中没有的单号和计费.txt文件中没有而受理.txt文件中有的单号。
虽然有点绕,但仔细一看不就是简单的去重问题吗。于是我就说,这都2024年了,你把这两个文件上传给豆包文心一言kimi这些AI模型,直接让AI帮你找出来不就完事了么。结果并没有想象的那么顺利,由于文件行数不确定,大致在1W-20W行不等,上传给AI时,只给你加载一半数据,也不知道是不是没开会员的原因,想白嫖AI这条路算是行不通了。
于是我提出,干脆写个shell脚本去做这个操作呗。但朋友嫌弃shell脚本太慢了,想让我用C语言帮忙写一个,并请我喝奶茶。我心想这事情简单,有奶茶喝我就给你干了。
刚开始思路是,打开一个文件读一行,跟另一个文件每一行比,比完发现没有重复就存到一个新文件。后面一想,这样做文件行数一多,效率肯定极慢。于是问了问豆包,有什么好办法,豆包给出了个哈希表算法的建议。当了这么久牛马了,现在有了AI这个牛马,我肯定是不会自己从零开始撸代码的了,先让AI帮我写一段。
我copy过来,果然不出所料,编译都编不过。返回来质问AI,AI又老老实实给我整了一段,我找朋友要了两个测试数据,一测试发现不行,然后又让它改,然后给他提了一系列要求、比如哈希碰撞处理什么的,就这么一步步在我的调教下,终于写出了一段能用的代码。大家如果用得上可自取:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h> // 用于isspace函数

#define MAX_LINE_LENGTH 1024
#define HASH_TABLE_SIZE 100000

typedef struct Node {
    char *singleNumber;
    struct Node *next;
} Node;

Node *hashTable[HASH_TABLE_SIZE];

// 函数声明
unsigned int hashFunction(const char *str);
void insertHash(Node **hashTable, const char *singleNumber);
int containsHash(Node **hashTable, const char *singleNumber);
void freeHashTable(Node *hashTable[]);
int isNotBlankLine(const char *line);
char* trim(const char *str);

int generaFile(const char *filename1, const char *filename2)
{
    FILE *file1, *file2, *outputfd;
    char output_filename[1024] = {0};
    strncpy(output_filename, filename2, strlen(filename2) - 4);
    strcat(output_filename, "_去重后.txt");

    char line[MAX_LINE_LENGTH];
    // 初始化哈希表
    for (int i = 0; i < HASH_TABLE_SIZE; i++) {
        hashTable[i] = NULL;
    }
    // 读取第一个文件并构建哈希表
    file1 = fopen(filename1, "r");
    if (!file1) {
        perror("Error opening file1");
        return EXIT_FAILURE;
    }
    while (fgets(line, MAX_LINE_LENGTH, file1)) {
        char *trimmedLine = trim(line);
        if (isNotBlankLine(trimmedLine)) {
            insertHash(hashTable, trimmedLine);
        }
        free(trimmedLine);
    }
    fclose(file1);
    printf("load %s hash finish!\n", filename1);

    // 读取第二个文件并删除共同的单号
    file2 = fopen(filename2, "r");
    outputfd = fopen(output_filename, "w+");
    if (!file2 || !outputfd) {
        perror("Error opening file2 or outputfd");
        return EXIT_FAILURE;
    }

    while (fgets(line, MAX_LINE_LENGTH, file2)) {
        char *trimmedLine = trim(line);
        line[strcspn(line, "\n")] = 0; // 移除换行符
        if (isNotBlankLine(trimmedLine) && !containsHash(hashTable, trimmedLine)) { // 没有找到相同的且不是空行
            fputs(trimmedLine, outputfd);
            fputc('\n', outputfd); // 使用fputc确保只写入一个换行符
        }
        free(trimmedLine);
    }
    fclose(file2);
    fclose(outputfd);

    // 释放哈希表
    freeHashTable(hashTable);

    return EXIT_SUCCESS;
}

int isNotBlankLine(const char *line) {
    // 检查每一字符是否都是空白字符,如果是,则返回0,否则返回1
    while (*line) {
        if (!isspace((unsigned char)*line)) {
            return 1;
        }
        line++;
    }
    return 0;
}

char* trim(const char *str) {
    if (str == NULL) return NULL;
    const char *end;
    size_t len = strlen(str);
    // Trim leading space
    while (isspace((unsigned char)*str)) str++;
    if (*str == 0)  // All spaces?
        return strdup("");
    // Trim trailing space
    end = str + len - 1;
    while (end > str && isspace((unsigned char)*end)) end--;
    // The len is the number of non-space chars
    len = (end - str + 1);
    char *trimmed = (char *)malloc(len + 1);
    if (trimmed) {
        snprintf(trimmed, len + 1, "%s", str);
        trimmed[len] = '\0';
    }
    return trimmed;
}

int main(int argc, char *argv[])
{
    char *filename1 = argv[1];
    char *filename2 = argv[2];
    if (argc != 3) {
        printf("请指定要去重的两个文件!\n");
        printf("用法: ./quchong 文件1 文件2\n");
        printf("示例:./quchong 受理.txt 计费.txt\n");
        return 0;
    }

    if (generaFile(filename1, filename2) != EXIT_SUCCESS) {
        printf("%s 去重失败!", filename2);
        return EXIT_FAILURE;
    }

    // 注意:这里应该重新初始化哈希表
    for (int i = 0; i < HASH_TABLE_SIZE; i++) {
        hashTable[i] = NULL;
    }
    if (generaFile(filename2, filename1) != EXIT_SUCCESS) {
        printf("%s 去重失败!", filename1);
        return EXIT_FAILURE;
    }

    printf("数据去重完成!\n");

    return EXIT_SUCCESS;
}

// 哈希函数
unsigned int hashFunction(const char *str)
{
    unsigned int hash = 5381;
    int c;
    while ((c = *str++)) {
        hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
    }
    return hash % HASH_TABLE_SIZE;
}

// 插入哈希表
void insertHash(Node **hashTable, const char *singleNumber)
{
    unsigned int index = hashFunction(singleNumber);
    Node *newNode = (Node *)malloc(sizeof(Node));
    if (!newNode) {
        perror("Memory allocation failed");
        exit(EXIT_FAILURE);
    }
    newNode->singleNumber = strdup(singleNumber);
    if (!newNode->singleNumber) {
        free(newNode);
        perror("Memory allocation failed");
        exit(EXIT_FAILURE);
    }
    newNode->next = hashTable[index];
    hashTable[index] = newNode;
}

// 检查哈希表中是否包含某个单号
int containsHash(Node **hashTable, const char *singleNumber)
{
    unsigned int index = hashFunction(singleNumber);
    Node *current = hashTable[index];
    while (current) {
        if (strcmp(current->singleNumber, singleNumber) == 0) {
            return 1;
        }
        current = current->next;
    }
    return 0;
}

// 释放哈希表内存
void freeHashTable(Node *hashTable[])
{
    for (int i = 0; i < HASH_TABLE_SIZE; i++) {
        Node *current = hashTable[i];
        while (current) {
            Node *temp = current;
            current = current->next;
            free(temp->singleNumber);
            free(temp);
        }
    }
}

不得不感叹现在AI的强大啊,就几轮对话的功夫就给我写出了一个基本能用的代码,大大提高了我们的工作效率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/900240.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

4种鼓励创业创新的方法

随着市场趋于饱和&#xff0c;许多企业&#xff0c;尤其是初创企业&#xff0c;很难在竞争中保持领先地位。技术为企业彻底改变其营销和管理策略铺平了道路。另一个经过实践检验的成功渗透特定市场的方法是在办公室内部激发创新&#xff0c;从员工到品牌皆如此。 那么究竟如何…

Ajax笔记

介绍 Ajax是一种网页开发技术&#xff0c;全称是Asynchronous JavaScript and XML&#xff08;异步JavaScript和XML&#xff09;。作用如下&#xff1a; 数据交换&#xff1a;可以通过Ajax给服务器发送请求&#xff0c;并获取服务器响应的数据。即前端动态的发送Ajax到服务器端…

秦时明月2搭建笔记

1.具体配置 数据库不修改&#xff0c;如果修改了&#xff0c;gm那边也要 2.数据库 3.上传配置文件出现问题 参考&#xff1a;对于测试时&#xff0c;错误信息 Caused by: com.mysql.jdbc.PacketTooBigException: Packet for query is too large-CSDN博客 4.启动tomcat&#x…

指增和中性产品的申赎加减仓及资金调拨自动化伪代码思路

定义一些关键字代表的意义 STRUCT: 代表需要输入的格式化的信息IMPORT: 代表需要输入的外部信息&#xff0c; 这些信息通常是客观的SEARCH: 需要从某地比如数据库检索搜集信息SUM: 一种宏观的加和操作&#xff0c; 比如两个股票户ABAB&#xff0c;微观上实际还是有差异GROUP: …

Umi UI报错:连接失败,请尝试重启dev服务

Umi UI连接失败&#xff0c;请尝试重启dev服务 使用umi ui时遇到以下问题 报错如下 从报错可以看出是淘宝镜像失效的问题&#xff0c;检查淘宝镜像 可以看出淘宝镜像是最新的&#xff0c;并无问题 经过查找发现报错是因为依赖文件中使用了旧的淘宝镜像&#xff0c;在node…

【SAP Hana】X-DOC:数据仓库ETL如何抽取SAP中的CDS视图数据

【SAP Hana】X-DOC&#xff1a;数据仓库ETL如何抽取SAP中的CDS视图数据 1、无参CDS对应数据库视图2、有参CDS对应数据库表函数3、封装有参CDS为无参CDS&#xff0c;从而对应数据库视图 1、无参CDS对应数据库视图 select * from ZFCML_REP_V where mandt 300;2、有参CDS对应数…

开发涉及的安全规范整理

#1024程序员节&#xff5c;征文# 文章目录 前言安全场景与措施API调用方式鉴权参数校验日志打印数据保存加密 总结 前言 这篇文章我们来整理下写代码和方案设计中的安全规范问题&#xff0c;内容偏服务端&#xff0c;即使是入门的新人&#xff0c;如果你对安全有所了解会让成熟…

go语言中的Scanf()输入函数

Scanf() 第一种情况 package mainimport "fmt"func main() {var a intfor {fmt.Println("请输入一个整数:")fmt.Scanf("%d", &a)fmt.Println("----------------", a)} }运行结果&#xff1a; 解释&#xff1a; 出现这种现象是因…

CentOS 8在Linux虚拟机修改IP地址,出现:错误:“ens160“ 不是活动的连接。错误:未提供活动连接。

问题&#xff1a;错误&#xff1a;"ens160" 不是活动的连接。错误&#xff1a;未提供活动连接。 1.查看网络服务运行状态&#xff1a; 1)CentOS 7执行命令&#xff1a;systemctl status network 2)CentOS 8执行命令&#xff1a;systemctl status NetworkManager&a…

双十一有哪些适合学生党的好物?五款学生党必备好物分享

在双十一这个全民狂欢的购物盛宴中&#xff0c;不仅仅是寻找生活的小确幸&#xff0c;更是自我提升与投资的最佳时机。学习&#xff0c;作为个人成长的阶梯&#xff0c;其相关的好物选择显得尤为重要。本文精选了一系列学习、生活神器&#xff0c;旨在为您的学习之旅增添动力与…

手机防窥膜的工作原理是怎样的?有必要使用防窥膜吗?

在信息高度发达的社会中&#xff0c;我们通过手机可以实现非常多的操作&#xff0c;同时手机中有存在许多我们的隐私信息&#xff0c;伴随使用手机的时间增多&#xff0c;手机中的信息也有可能被暴露&#xff0c;尤其是在公共场所旁人很容易通过瞥视你的手机屏幕获取到一些信息…

青少年编程能力等级测评CPA C++(三级)-试卷1

青少年编程能力等级测评CPA C&#xff08;三级&#xff09;-试卷1 一、单项选择题&#xff08;共15题&#xff0c;每题3分&#xff0c;共45分&#xff09; CP3_1_1&#xff0e;以下有关模拟算法的叙述中&#xff0c;不正确的是&#xff08; &#xff09;。 A&#xff0e;模拟…

普通数组矩阵

文章目录 普通数组一、最大子数组二、合并区间三、轮转数组四、除自身以外数组的乘积五、缺失的第一个正数 普通数组 一、最大子数组 题目链接 方法一&#xff1a;动态规划 方法二&#xff1a;前缀和&#xff08;有点难理解&#xff09; 二、合并区间 题目链接 三、轮…

软件部署-Docker容器化技术(二)

上一期分享了Docker的一些基本内容&#xff0c;这一期主要对构建基础镜像和Docker网络、文件挂载再展开分享下&#xff0c;可能不一定做得很好&#xff0c;主要是在学习的过程中有一些自己的总结和思考&#xff0c;和大家一起学习。 名词说明&#xff1a;这里的宿主机是指liun…

【D3.js in Action 3 精译_037】4.1 DIY 实战:D3 源码分析之——d3.timeFormat() 函数

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第一部分 D3.js 基础知识 第一章 D3.js 简介&#xff08;已完结&#xff09; 1.1 何为 D3.js&#xff1f;1.2 D3 生态系统——入门须知1.3 数据可视化最佳实践&#xff08;上&#xff09;1.3 数据可…

Shopee虾皮登录不了的常见原因及解决方式

在近年来&#xff0c;随着电子商务的迅猛发展&#xff0c;Shopee虾皮作为东南亚地区的领先购物平台&#xff0c;吸引了大量用户。一些用户在使用过程中常常遇到登录问题&#xff0c;而登录不了的原因可能多种多样&#xff0c;包括网络连接不稳定、账号信息输入错误&#xff0c;…

【搭建个人图库】Docker部署Piwigo图库与公网环境远程传图全攻略

文章目录 前言1. 安装Docker2. 创建并启动Piwigo容器3. 本地访问测试与简单使用4. 公网远程访问本地Piwigo4.1 内网穿透工具安装4.2 创建远程连接公网地址4.3 使用固定公网地址远程访问 前言 本文和大家分享一下如何在Linux系统使用Docker部署一款开源的网络图片库管理系统Piw…

54页可编辑PPT | 大型集团企业数据治理解决方案

这份PPT是关于大型集团企业数据治理的全面解决方案&#xff0c;它详细介绍了数据治理的背景、需求、管理范围、框架、解决思路&#xff0c;以及数据治理在实际操作中的关键步骤。内容涵盖了数据架构、数据质量、数据应用等方面的问题&#xff0c;并提出了数据资产透视、智能搜索…

K8S如何基于Istio重新实现微服务

K8S如何基于Istio重新实现微服务 认识 Istio前言Istio 的理念Istio 的架构数据平面控制平面服务与 Istio 的关系 Istio 实践环境准备安装 Helm安装Istio 使用 Istio 代理运行应用情感分析应用的架构使用 Istio 代理运行应用Sidecar 注入Ingress 网关网关资源VirtualService 资源…

离线部署jdk8,jdk17, jdk21

目录 一、下载地址二、环境三、离线部署思路步骤 四、部署脚本 在开发过程中&#xff0c;有时我们需要在同一台机器上安装多个不同版本的 JDK&#xff0c;以满足不同项目的需求。本文将详细介绍如何在 Ubuntu 24.04 中离线安装 JDK8、JDK17 和 JDK21。 一、下载地址 建议下载O…