当前位置: 首页 > news >正文

【数据结构】顺序表实现通讯录

在这里插入图片描述

前言
在上一节中我们实现了顺序表,现在我们将使用顺序表完成通讯录的实现。(注:本人水平有限,“小屎山”有些许bug,代码冗余且语无伦次,望谅解!😅)


文章目录

  • 一、数据结构设计
  • 二、初始化和内存管理
    • 初始化
    • 动态扩容
  • 三、基础功能实现:增删改查
    • 添加联系人
    • 删除联系人
    • 修改联系人
    • 查找联系人
    • 显示通讯录
  • 四、文件操作
    • 保存至文件
    • 从文件读取
  • 五、所有代码
    • contact.h
    • contact.c
    • main.c

一、数据结构设计

首先,定义一个结构体Contact来存储单个联系人的信息,包括姓名、性别、年龄和手机号。

typedef struct Contact {char name[NAME_MAX]; //姓名char sex[SEX_MAX];   //性别int age;             //年龄char phone[PHONE_MAX];//手机号
}Contact;

然后,定义一个结构体SeqList(序列表)用于存储所有联系人信息。该结构体包含一个指向Contact结构体数组的指针data,以及两个整数,size表示当前有效数据个数,capacity表示当前数组容量。

typedef struct SeqList {Contact* data; //通讯录信息int size;  //有效数据个数int capacity;  //通讯录总容量
}ConList;

二、初始化和内存管理

初始化

在程序开始之前,我们需要进行初始化操作,即为SeqList中的data分配内存,并设置初始值。

int ContactInit(ConList* list) {   assert(list);Contact* tmp = (Contact*)malloc(sizeof(Contact));if (tmp==NULL) {printf("内存分配失败\n");return -1;}list->data = tmp;list->size = 0;list->capacity = 1;return 0;
}

动态扩容

如果SeqList中的data数组已满,我们需要进行扩容。

int resizeConList(ConList* list) {assert(list);int newCapacity = list->capacity * 2;Contact* newData = (Contact*)realloc(list->data, sizeof(Contact) * newCapacity);if (newData == NULL) {printf("内存分配失败\n");return -1;}list->data = newData;list->capacity = newCapacity;return 0;
}

三、基础功能实现:增删改查

添加联系人

添加联系人时,需要先检查是否有足够的空间,如果没有则扩容。然后,通过标准输入获取联系人信息。

int ContactAdd(ConList* list) {assert(list);char sign = 'N';do {if (list->size >= list->capacity) {int ret = resizeConList(list);if (ret == -1) {printf("通讯录扩大失败\n");return -1;}}printf("请输入姓名:>");scanf(" %20s", list->data[list->size].name); // 限制输入长度printf("请输入性别:>");scanf(" %7s", list->data[list->size].sex); // 限制输入长度printf("请输入年龄:>");if (scanf("%d", &(list->data[list->size].age)) != 1) {printf("无效的年龄输入\n");return -1;}printf("请输入手机号:>");scanf(" %20s", list->data[list->size].phone); // 限制输入长度list->size++;ContactShow(list);printf("Y 继续添加   N 结束   请输入:>");scanf(" %c", &sign); // 注意空格,用于吸收前一个输入后可能残留的换行符printf("***********************************\n");} while (sign == 'Y' || sign == 'y');return 0;
}

删除联系人

删除联系人时,需要输入要删除的联系人的序号。

int ContactDel(ConList* list) {assert(list);ContactShow(list);int input = 0;//要删除联系人序号char sign = 0;do {printf("\n");printf("选择要删除的联系人的序号:>");scanf("%d", &input);for (int i = input; i < list->size; i++) {list->data[i - 1] = list->data[i];}list->size--;ContactShow(list);printf("Y 继续删除  N 结束  请输入:>");scanf(" %c", &sign);} while (sign=='Y'||sign=='y');return 0;
}

修改联系人

修改联系人与添加联系人类似,但需要先定位到要修改的联系人。

int ContactModify(ConList* list) {assert(list);ContactShow(list);int input = 0;//要修改的联系人序号char sign = 0;do {printf("\n");printf("选择要修改的联系人序号:>");scanf("%d", &input);//联系人信息修改printf("请输入姓名:>");scanf(" %20s", list->data[input-1].name); printf("请输入性别:>");scanf(" %7s", list->data[input - 1].sex);printf("请输入年龄:>");if (scanf("%d", &(list->data[input - 1].age)) != 1) {printf("无效的年龄输入\n");return -1;}printf("请输入手机号:>");scanf(" %20s", list->data[input - 1].phone); ContactShow(list);printf("Y 继续修改  N 结束  请输入:>");scanf(" %c",&sign);} while (sign == 'Y' || sign == 'y');return 0;
}

查找联系人

可以通过姓名或手机号进行查找。

int ContactFind(ConList* list) {assert(list);int input = 0;char keyword[21] = {0};//联系人关键字int sign = 0;//联系人是否找到判断do {sign = 0;printf("选择查找联系人方式  1 姓名查找  2 手机号查找  0 退出查找:>");scanf("%d", &input);if (!input) return 0;//退出查找printf("请输入查找关键字:>");scanf(" %20s", keyword);  // 限制输入长度switch (input) {case 1:      // 按姓名查找for (int i = 0; i < list->size; i++) {if (strcmp(list->data[i].name, keyword) == 0) {printf("找到联系人:%d\n", i + 1);sign = 1;break;}}break;case 2:       // 按手机号查找for (int i = 0; i < list->size; i++) {if (strcmp(list->data[i].phone, keyword) == 0) {printf("找到联系人的序号:%d\n", i + 1);sign = 1;break;}}break;default:printf("无效的选项\n");break;}} while (input);if (!sign) {printf("未找到联系人\n");}return 0;
}

显示通讯录

int ContactShow(ConList* list) {assert(list);int count = 1;//序号printf("--------------------------------------------------------------\n");printf("|序号|        姓名        |  性别  |年龄|       手机号       |\n");while (count <= list->size) {printf("--------------------------------------------------------------\n");printf("|%-4d|%-20s|%-8s|%-4d|%-20s|\n",count,list->data[count - 1].name, list->data[count - 1].sex, list->data[count - 1].age,list->data[count - 1].phone);count++;}printf("--------------------------------------------------------------\n");return 0;
}

四、文件操作

保存至文件

使用二进制模式将所有联系人信息保存到文件。

int ContactSave(ConList* list) {assert(list);FILE* file = fopen("contact.dat", "wb");if (file == NULL) {printf("无法创建或打开文件\n");return -1;}// 写入通讯录的大小(元素数量)fwrite(&(list->size), sizeof(int), 1, file);// 写入通讯录的数据fwrite(list->data, sizeof(Contact), list->size, file);fclose(file);file=NULL;return 0;
}

从文件读取

与保存操作相反,从文件中读取所有联系人信息。

int ContactLoad(ConList* list) {assert(list);FILE* file = fopen("contact.dat", "rb+");if (file == NULL) {printf("无法打开文件\n");return -1;}// 读取通讯录的大小(元素数量)fread(&(list->size), sizeof(int), 1, file);// 根据读取到的大小动态分配内存if (list->size) {Contact* tmp = (Contact*)realloc(list->data, sizeof(Contact) * list->size);if (tmp == NULL) {printf("内存分配失败\n");fclose(file);return -1;}list->data = tmp;// 读取通讯录的数据fread(list->data, sizeof(Contact), list->size, file);list->capacity = list->size; // 在这个简单示例中,将容量设置为大小}fclose(file);return 0;
}

五、所有代码

contact.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>#define NAME_MAX 20 
#define SEX_MAX 7   
#define PHONE_MAX 20typedef struct Contact {char name[NAME_MAX]; //姓名char sex[SEX_MAX];   //性别int age;             //年龄char phone[PHONE_MAX];//手机号
}Contact;typedef struct SeqList {Contact* data; //通讯录信息int size;  //有效数据个数int capacity;  //通讯录总容量
}ConList;//添加联系人
int ContactAdd(ConList* list);
//删除联系人
int ContactDel(ConList* list);
//修改联系人
int ContactModify(ConList* list);
//查找指定联系人
int ContactFind(ConList* list);//通讯录的初始化
int ContactInit(ConList* list);
//通讯录扩容
int resizeConList(ConList* list);
//通讯录销毁
void ContactDestroy(ConList* list);
//查看通讯录
int ContactShow(ConList* list);//检测contact.dat存不存在,如果不存在就创建一个
int checkAndCreateFile(const char* filename);
//保存通讯录到文件
int ContactSave(ConList* list);
//从文件中读取通讯录
int ContactLoad(ConList* list);

contact.c

#include"contact.h"int ContactInit(ConList* list) {   assert(list);Contact* tmp = (Contact*)malloc(sizeof(Contact));if (tmp==NULL) {printf("内存分配失败\n");return -1;}list->data = tmp;list->size = 0;list->capacity = 1;return 0;
}int resizeConList(ConList* list) {assert(list);int newCapacity = list->capacity * 2;Contact* newData = (Contact*)realloc(list->data, sizeof(Contact) * newCapacity);//通常扩容选择1.5倍或者2倍进行扩容if (newData == NULL) {printf("内存分配失败\n");return -1;}list->data = newData;list->capacity = newCapacity;return 0;
}int ContactAdd(ConList* list) {assert(list);char sign = 'N';do {if (list->size >= list->capacity) {int ret = resizeConList(list);if (ret == -1) {printf("通讯录扩大失败\n");return -1;}}printf("请输入姓名:>");scanf(" %20s", list->data[list->size].name); // 限制输入长度printf("请输入性别:>");scanf(" %7s", list->data[list->size].sex); // 限制输入长度printf("请输入年龄:>");if (scanf("%d", &(list->data[list->size].age)) != 1) {printf("无效的年龄输入\n");return -1;}printf("请输入手机号:>");scanf(" %20s", list->data[list->size].phone); // 限制输入长度list->size++;ContactShow(list);printf("Y 继续添加   N 结束   请输入:>");scanf(" %c", &sign); // 注意空格,用于吸收前一个输入后可能残留的换行符printf("***********************************\n");} while (sign == 'Y' || sign == 'y');return 0;
}int ContactShow(ConList* list) {assert(list);int count = 1;//序号printf("--------------------------------------------------------------\n");printf("|序号|        姓名        |  性别  |年龄|       手机号       |\n");while (count <= list->size) {printf("--------------------------------------------------------------\n");printf("|%-4d|%-20s|%-8s|%-4d|%-20s|\n",count,list->data[count - 1].name, list->data[count - 1].sex, list->data[count - 1].age,list->data[count - 1].phone);count++;}printf("--------------------------------------------------------------\n");return 0;
}int ContactDel(ConList* list) {assert(list);ContactShow(list);int input = 0;//要删除联系人序号char sign = 0;do {printf("\n");printf("选择要删除的联系人的序号:>");scanf("%d", &input);for (int i = input; i < list->size; i++) {list->data[i - 1] = list->data[i];}list->size--;ContactShow(list);printf("Y 继续删除  N 结束  请输入:>");scanf(" %c", &sign);} while (sign=='Y'||sign=='y');return 0;
}int ContactModify(ConList* list) {assert(list);ContactShow(list);int input = 0;//要修改的联系人序号char sign = 0;do {printf("\n");printf("选择要修改的联系人序号:>");scanf("%d", &input);//联系人信息修改printf("请输入姓名:>");scanf(" %20s", list->data[input-1].name); printf("请输入性别:>");scanf(" %7s", list->data[input - 1].sex);printf("请输入年龄:>");if (scanf("%d", &(list->data[input - 1].age)) != 1) {printf("无效的年龄输入\n");return -1;}printf("请输入手机号:>");scanf(" %20s", list->data[input - 1].phone); ContactShow(list);printf("Y 继续修改  N 结束  请输入:>");scanf(" %c",&sign);} while (sign == 'Y' || sign == 'y');return 0;
}int ContactFind(ConList* list) {assert(list);int input = 0;char keyword[21] = {0};//联系人关键字int sign = 0;//联系人是否找到判断do {sign = 0;printf("选择查找联系人方式  1 姓名查找  2 手机号查找  0 退出查找:>");scanf("%d", &input);if (!input) return 0;//退出查找printf("请输入查找关键字:>");scanf(" %20s", keyword);  // 限制输入长度switch (input) {case 1:      // 按姓名查找for (int i = 0; i < list->size; i++) {if (strcmp(list->data[i].name, keyword) == 0) {printf("找到联系人:%d\n", i + 1);sign = 1;break;}}break;case 2:       // 按手机号查找for (int i = 0; i < list->size; i++) {if (strcmp(list->data[i].phone, keyword) == 0) {printf("找到联系人的序号:%d\n", i + 1);sign = 1;break;}}break;default:printf("无效的选项\n");break;}} while (input);if (!sign) {printf("未找到联系人\n");}return 0;
}void ContactDestroy(ConList* list) {assert(list);// 释放动态分配的数组内存if (list->data != NULL) {free(list->data);}// 将各成员变量设置为初始状态list->data = NULL;list->size = 0;list->capacity = 0;
}int ContactSave(ConList* list) {assert(list);FILE* file = fopen("contact.dat", "wb");if (file == NULL) {printf("无法创建或打开文件\n");return -1;}// 写入通讯录的大小(元素数量)fwrite(&(list->size), sizeof(int), 1, file);// 写入通讯录的数据fwrite(list->data, sizeof(Contact), list->size, file);fclose(file);file=NULL;return 0;
}int ContactLoad(ConList* list) {assert(list);FILE* file = fopen("contact.dat", "rb+");if (file == NULL) {printf("无法打开文件\n");return -1;}// 读取通讯录的大小(元素数量)fread(&(list->size), sizeof(int), 1, file);// 根据读取到的大小动态分配内存if (list->size) {Contact* tmp = (Contact*)realloc(list->data, sizeof(Contact) * list->size);if (tmp == NULL) {printf("内存分配失败\n");fclose(file);return -1;}list->data = tmp;// 读取通讯录的数据fread(list->data, sizeof(Contact), list->size, file);list->capacity = list->size; // 在这个简单示例中,将容量设置为大小}fclose(file);return 0;
}int checkAndCreateFile(const char* filename) {FILE* file;// 尝试以读模式打开文件file = fopen(filename, "r");// 检查文件是否已经存在if (file != NULL) {// 文件存在,关闭文件fclose(file);printf("contact.dat存在\n");return 0;  // 返回0表示文件已存在,无需创建}else {// 文件不存在,以写模式创建一个新文件file = fopen(filename, "w");if (file != NULL) {fclose(file);printf("文件创建成功\n");return 1;  // 返回1表示文件成功创建}else {// 文件创建失败,可能是因为权限或磁盘空间不足等原因printf("文件创建失败\n");return -1;  // 返回-1表示文件创建失败}}
}

main.c

#include"contact.h"void menu() {printf("-------------------------------------\n");printf("-----1 添加联系人   2 删除联系人-----\n");printf("-----3 修改联系人   4 查找联系人-----\n");printf("-------------0 退出通讯录------------\n");printf("-------------------------------------\n");}int main() {ConList list;ContactInit(&list);//通讯录初始化checkAndCreateFile("contact.dat");//检测contact.dat存不存在,如果不存在就创建一个//从文件中读取通讯录ContactLoad(&list);int input = 0;do {menu();printf("\n");printf("选择操作:>");scanf("%d",&input);switch(input){case 1:ContactAdd(&list);break;case 2:ContactDel(&list);break;case 3:ContactModify(&list);break;case 4:ContactFind(&list);break;default:break;}} while (input);ContactSave(&list);//保存通讯录到文件ContactDestroy(&list);//通讯录销毁return 0;
}

在这里插入图片描述
如果你喜欢这篇文章,点赞👍+评论+关注⭐️哦!
欢迎大家提出疑问,以及不同的见解。

相关文章:

【数据结构】顺序表实现通讯录

前言 在上一节中我们实现了顺序表&#xff0c;现在我们将使用顺序表完成通讯录的实现。&#xff08;注&#xff1a;本人水平有限&#xff0c;“小屎山”有些许bug&#xff0c;代码冗余且语无伦次&#xff0c;望谅解&#xff01;&#x1f605;&#xff09; 文章目录 一、数据结构…...

JMeter 随机数生成器简介:使用 Random 和 UUID 算法

在压力测试中&#xff0c;经常需要生成随机值来模拟用户行为。JMeter 提供了多种方式来生成随机值&#xff0c;本文来具体介绍一下。 随机数函数 JMeter 提供了多个用于生成随机数的函数&#xff0c;其中最常用的是 __Random 函数。该函数可以生成一个指定范围内的随机整数或…...

vue3 更换 elemnt-ui / element-plus 版本npm命令

1. 安装 / 更换 element-ui 版本 [ 在 后面指定想要安装的版本 ] //卸载当前版本 npm uninstall element-ui //安装指定版本 npm i element-ui2.4.8 -S --legacy-peer-deps 2. 安装 / 更换 element-plus 版本 [ 在 后面指定想要安装的版本 ] npm install element-plus2.3…...

react.js 手写响应式 reactive

Redux 太繁琐&#xff0c;Mbox 很酷但我们可能没必要引入新的包&#xff0c;那就让我们亲自在 react.js 中通过代理实现一套钩子来达到类似 vue 的响应式状态&#xff1a; 实现 reactive hooks 代理类声明 代理状态的类应当提供可访问的状态&#xff0c;和订阅变化的接口。 …...

代码随想录打卡第四十六天|完全背包 ● 518. 零钱兑换 II ● 377. 组合总和 Ⅳ

完全背包理论 有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品都有无限个&#xff08;也就是可以放入背包多次&#xff09;&#xff0c;求解将哪些物品装入背包里物品价值总和最大。 完全背包和01背包问题唯一…...

【BP-Adaboost预测】基于BP神经网络的Adaboost的单维时间序列预测研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

Origami Studio for Mac:塑造未来,掌握原型设计之巅

在当今高度竞争的设计领域&#xff0c;原型设计的重要性不言而喻。它不仅是沟通想法&#xff0c;也是测试和改进设计的关键环节。而现在&#xff0c;一款强大的原型设计工具——Origami Studio for Mac&#xff0c;正在席卷设计界&#xff0c;以其独特的功能和卓越的性能&#…...

UML类图中各箭头表示总结

UML类图中各箭头表示总结 1、泛化2、实现3、依赖4、关联5、聚合6、组合 在UML类图中&#xff0c;箭头关系是用来表示类之间的关系的。箭头关系的种类有以下几种&#xff1a; 1、泛化 泛化&#xff1a;表示类之间的继承关系。箭头从子类指向父类。箭头&#xff1a;实线空心三角…...

神经网络量化----为了部署而特别设计

引言:一般神经网络量化有两个目的: 为了加速,在某些平台上浮点数计算比较耗费时间,替换为整形可以加快运算为了部署,某些平台上只支持整形运算,比如在芯片中如果是第1个目的,则使用常规的量化手段就可以满足,将浮点数运算变成整形运算+较少的浮点运算 但是如果是第2个目…...

代码随想录算法训练营Day60|单调栈01

代码随想录算法训练营Day60|单调栈01 文章目录 代码随想录算法训练营Day60|单调栈01一、739. 每日温度二、496.下一个更大元素 I 一、739. 每日温度 class Solution {public int[] dailyTemperatures(int[] temperatures) {//单调栈int lenstemperatures.length;int result[]n…...

openMP学习笔记 -编程模型

OpenMP模型 gcc编译openmp指令&#xff1a;gcc test.cpp -o test -fopenmp 定积分计算 函数面积 给定一个定积分&#xff0c;计算其面积&#xff1a; ∫ 0 1 4.0 ( 1 x 2 ) d x \int^{1}_{0}{\frac{4.0}{(1x^2)}dx} ∫01​(1x2)4.0​dx omp 概念 并行区域 并行区域用于…...

【Hive SQL 每日一题】环比增长率、环比增长率、复合增长率

文章目录 环比增长率同比增长率复合增长率测试数据需求说明需求实现 环比增长率 环比增长率是指两个相邻时段之间某种指标的增长率。通常来说&#xff0c;环比增长率是比较两个连续时间段内某项数据的增长量大小的百分比。 环比增长率反映了两个相邻时间段内某种经济指标的变…...

Java设计模式之外观模式(Facade Pattern)

外观模式&#xff08;Facade Pattern&#xff09;是一种结构型设计模式&#xff0c;它提供了一个统一的接口&#xff0c;用于访问子系统中的一组接口。外观模式通过隐藏子系统的复杂性&#xff0c;简化了客户端与子系统之间的交互&#xff0c;提供了一个更简单、更直观的接口。…...

【大疆智图】大疆智图(DJI Terra 3.0.0)安装及使用教程

大疆智图是一款以二维正射影像与三维模型重建为主的软件,同时提供二维多光谱重建、激光雷达点云处理、精细化巡检等功能。它能够将无人机采集的数据可视化,实时生成高精度、高质量三维模型,满足事故现场、工程监测、电力巡线等场景的展示与精确测量需求。 文章目录 1. 安装D…...

腾讯地图基本使用(撒点位,点位点击,弹框等...功能) 搭配Vue3

腾讯地图的基础注册账号 展示地图等基础功能在专栏的上一篇内容 大家有兴趣可以去看一看 今天说的是腾讯地图的在稍微一点的基础操作 话不多说 直接上代码 var marker ref(null) var map var center ref(null) // 地图初始化 const initMap () > {//定义地图中心点坐标…...

散列表:Word文档中的单词拼写检查功能是如何实现的?

文章来源于极客时间前google工程师−王争专栏。 一旦我们在Word里输入一个错误的英文单词&#xff0c;它就会用标红的方式提示“编写错误”。Word的这个单词拼写检查功能&#xff0c;虽然很小但却非常实用。这个功能是如何实现的&#xff1f; 散列别&#xff08;Hash Table&am…...

智慧公厕蜕变多功能城市智慧驿站公厕的创新

随着城市发展的不断推进&#xff0c;对公共设施的便利性和智能化要求也日益提高。为满足市民对高品质、便捷、舒适的公共厕所的需求&#xff0c;智慧公厕行业的领航厂家广州中期科技有限公司&#xff0c;全新推出了一体化智慧公厕驿站。凭借着“高科技碳中和物联网创意设计新经…...

R语言清洗与处理数据常用代码段

去掉数据框df的某一列&#xff1a; # 删除不必要的变量 data$unnecessary_var <- NULL 选择需要的列进行读入数据框&#xff1a; # 选择需要的列 selected_cols <- c("col1", "col2", "col3") data <- fread("data.csv", s…...

centos 7.9 安装python 3.10的tls问题,

本地开发升级成了py3.10.6,服务器测试时安装py3.10.4 发现无法正常使用pip3 pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available. 印象中py3的高版本依赖高版本的openssl,centos 7下默认的openssl为1.0.x, 问题很简…...

pytorch,tf维度理解RNN

input_t input_t.squeeze(1) 这行代码用于从 input_t 中去除尺寸为1的维度。在深度学习中&#xff0c;经常会出现具有额外尺寸为1的维度&#xff0c;这些维度通常是为了匹配模型的期望输入维度而添加的。 在这里&#xff0c;input_t可能具有形状 (batch_size, 1, feature_dim…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架&#xff0c;专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用&#xff0c;其中包含三个使用通用基本模板的页面。在此…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

python如何将word的doc另存为docx

将 DOCX 文件另存为 DOCX 格式&#xff08;Python 实现&#xff09; 在 Python 中&#xff0c;你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是&#xff0c;.doc 是旧的 Word 格式&#xff0c;而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况&#xff0c;可以通过以下几种方式模拟或触发&#xff1a; 1. 增加CPU负载 运行大量计算密集型任务&#xff0c;例如&#xff1a; 使用多线程循环执行复杂计算&#xff08;如数学运算、加密解密等&#xff09;。运行图…...

浅谈不同二分算法的查找情况

二分算法原理比较简单&#xff0c;但是实际的算法模板却有很多&#xff0c;这一切都源于二分查找问题中的复杂情况和二分算法的边界处理&#xff0c;以下是博主对一些二分算法查找的情况分析。 需要说明的是&#xff0c;以下二分算法都是基于有序序列为升序有序的情况&#xf…...

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...