通訊錄實現【C語言】

目錄

前言

一、整體邏輯分析

二、實現步驟

1、創建菜單和多次操作問題

2、創建通訊錄

3、初始化通訊錄

4、添加聯系人

5、顯示聯系人

6、刪除指定聯系人

?7、查找指定聯系人

8、修改聯系人信息

9、排序聯系人信息

三、全部源碼


前言

我們上期已經詳細的介紹了自定義類型,本期我們來用學過的知識來做個小項目來練習練習。本期我們將用C語言實現通訊錄靜態版!后期介紹了動態內存管理和文件操作我們將會在此版本的基礎上進行優化改進!

一、整體邏輯分析

我們還和以前實現三子棋和掃雷小項目一樣,先對整體工程的邏輯盡可能詳細的梳理,否則一開就是一頓狂敲,最后一走發現全是Bug這樣就不好了!我們一開始盡可能的分析清楚,后面即使出現了問題也能快速確定!本期還是和往期一樣采用多文件編程!OK,我們下面一起來梳理一下這個小項目的基本實現邏輯:

1、創建菜單和多次操作問題

2、創建通訊錄

3、通訊錄的初始化以及增刪查改等操作

二、實現步驟

1、創建菜單和多次操作問題

我們期望當我們進行對通訊錄操作時可以給我們在進行操作前給一個菜單功能我們操作!考慮到后面還要多次操作通訊錄(增刪查改等)我們結合起來很快想到用do..while循環處理最為合理,這里以前寫過兩三遍了我們直接上代碼:

#include"contact.h"void menu()
{printf("*****************************************\n");printf("********* 1. add     2. del    **********\n");printf("********* 3. search  4. modify **********\n");printf("********* 5. show    6. sort   **********\n");printf("********* 0. exit              **********\n");printf("*****************************************\n");
}void test()
{int input = 0;do{menu();printf("請選擇操作數:> ");scanf("%d", &input);switch (input){case 1://addbreak;case 2://delbreak;case 3://searchbreak;case 4://modifybreak;case 5://showbreak;case 6://sortbreak;case 0:printf("退出成功!\n");break;default:printf("選擇數非法!\n");break;}} while (input);
}int main()
{test();return 0;
}

看效果:

2、創建通訊錄

我們在對通訊錄進行各種操作前先得有個通訊錄吧!通訊錄的本質還是描述一個人的屬性例如:姓名、年齡、性別、電話、住址等!這些都是不同的類型,我們很容易想到用結構體就能解決!但這只是描述一個人,你的通訊錄不可能只有一個人吧應該是有很多個!而這些聯系人又是同一類型,因此采用結構體數組來創建通訊錄!

typedef struct PeoInfo
{char name[20];int age;char sex[5];char tele[15];char addr[20];
}PeoInfo;

這就是描述一個人基本屬性的結構體!當創建好了這個結構體后,我們就可以在test.c這個文件中do..while循環那里可以創建結構體數組來作為通訊錄了!

但這樣寫會有個問題就是,當你存入或刪除聯系人后想打印出來看看是此時通訊錄中的聯系人時應該打印多少?我們還想不知道。所以這里我們還得再定義一個變量sz來記錄通訊錄的大小!

其實我們發現,sz不僅是可以記錄通訊錄的大小,而且增加聯系人的時候只需要增加到sz位置即可,增加一個sz++,當刪除一個sz--;這樣其實?sz和通訊錄是綁定在一起的,我們不妨在對通訊錄進行一層封裝,把他也封裝成一個結構體,一個成員是PeoInfo結構體數組,一個是記錄通訊錄大小的sz:

typedef struct PeoInfo
{char name[20];int age;char sex[5];char tele[15];char addr[20];
}PeoInfo;typedef struct Contact
{PeoInfo data[100];int sz;
}Contact;

然后再在test.c文件中創建即可!

OK!這個創建通訊錄記好了!其實這里還可已在稍微優化一下:我們發現兩個結構體中都出現了大量的常數,我們萬一后期需求有變,這些都得改!因此為了后期修改方便,我們把這些都改成#define的常量,后期修改起來容易!這里你可能會說上期不是介紹了枚舉嗎,這里正好是多個常量枚舉不是更好嗎?這里枚舉確實可以達到目的,但枚舉是在沒開始前就能列舉出來所有可能,我們這個可不是!所以,這里不用枚舉!

#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 15
#define ADDR_MAX 20
#define MAX 100typedef struct PeoInfo
{char name[NAME_MAX];int age;char sex[SEX_MAX];char tele[TELE_MAX];char addr[ADDR_MAX];
}PeoInfo;typedef struct Contact
{PeoInfo data[MAX];int sz;
}Contact;

這樣才是當前邏輯下的最優代碼!

3、初始化通訊錄

當我們創建好了通訊錄后我們先對其進行一個初始化!把結構體數組的每個元素都初始化為0,通訊錄大小也置為0!因為我們要改變結構體的內容所以應該傳地址!我們這里采用的是memset這個函數直接初始化為0,也可以用個循環來初始化!不了解memset的點擊memset

void InitContact(Contact* pc)
{assert(pc);memset(pc->data, 0, sizeof(pc->data));pc->sz = 0;
}

4、添加聯系人

我們前面已經說過了,只需要在sz的位置增加即可!但要考慮通訊錄滿的情況!

void AddContact(Contact* pc) 
{assert(pc);//通訊錄已滿if (pc->sz == MAX){printf("通訊錄已滿,無法添加!\n");return;}//添加聯系人printf("請輸入聯系人姓名:> ");scanf("%s", pc->data[pc->sz].name);printf("請輸入聯系人年齡:> ");scanf("%d", &pc->data[pc->sz].age);printf("請輸入聯系人性別:> ");scanf("%s", pc->data[pc->sz].sex);printf("請輸入聯系人電話:> ");scanf("%s", pc->data[pc->sz].tele);printf("請輸入聯系人住址:> ");scanf("%s", pc->data[pc->sz].addr);pc->sz++;printf("添加成功!\n");
}

OK,我們下面先來寫一個顯示聯系人,來驗證一下是否添加成功!

5、顯示聯系人

顯示聯系人就是把通訊錄中的聯系人打印在控制臺!

void ShowContact(Contact* pc)
{assert(pc);printf("%-s\t%-s\t%-5s\t%-15s\t%-20s\n", "姓名", "年齡", "性別", "電話", "住址");for (int i = 0; i < pc->sz; i++){printf("%-s\t%-d\t%-5s\t%-15s\t%-20s\n",pc->data[i].name,pc->data[i].age,pc->data[i].sex,pc->data[i].tele,pc->data[i].addr);}
}

OK,我們來看看是否添加成功以及顯示聯系人!

OK,添加聯系人和顯示聯系人都成功了!說明我們上面邏輯沒有問題!

6、刪除指定聯系人

我們輸入要刪除的人的姓名,進行查找,找到了刪除,否則輸出沒有此聯系人!注意考慮通訊錄為空的情況!這里提到了查找,這個查找和通訊錄的那個查找有點不一樣,這個是查找后返回下標即可,那個是還要打印聯系人信息功能不一樣。因此我們單獨在封裝一個函數!

//查找要刪除的人并返回下標
int FindContact(const Contact* pc, const char* name)
{for (int i = 0; i < pc->sz; i++){if (strcmp(pc->data[i].name, name) == 0){return i;//找到了}}return -1;//沒找到
}//刪除聯系人
void DelContact(Contact* pc)
{assert(pc);//通訊錄為空if (pc->sz == 0){printf("通訊錄為空,無法刪除!\n");return;}char name[NAME_MAX] = { 0 };printf("請輸入要刪除人的姓名:> ");scanf("%s", name);int pos = FindContact(pc, name);if (pos != -1){//刪除for (int i = pos; i < pc->sz - 1; i++){pc->data[i] = pc->data[i + 1];}pc->sz--;printf("成功刪除聯系人!\n");}else{printf("沒有此聯系人!\n");}
}

這里要注意的是比較字符串要用strcmp,不能用 == 這個我們在字符串函數和內存函數那一期詳細介紹過!另外注意刪除的時候那里下標越界問題!

看效果:

?7、查找指定聯系人

查找指定聯系人還是先按指定方式進行查找, 找到了打印,否則輸出沒有此聯系人!這里顯示一個聯系人的這個里后面修改聯系人也可能要用所以我們為了方便把他封裝成一個函數后面直接調用即可!


//顯示單個聯系人信息
void Print(const Contact* pc, int pos)
{assert(pc);printf("%-s\t%-s\t%-5s\t%-15s\t%-20s\n", "姓名", "年齡", "性別", "電話", "住址");printf("%-s\t%-d\t%-5s\t%-15s\t%-20s\n",pc->data[pos].name,pc->data[pos].age,pc->data[pos].sex,pc->data[pos].tele,pc->data[pos].addr);}//查找指定聯系人
void Search(const Contact* pc)
{assert(pc);char name[NAME_MAX] = { 0 };printf("請輸入要查找聯系人姓名:> ");scanf("%s", name);int pos = -1;//初始化為-1表示沒有此聯系人for (int i = 0; i < pc->sz; i++){if (strcmp(pc->data[i].name, name) == 0){pos = i;//找到了break;}}if (pos != -1){Print(pc, pos);}else{printf("沒有此聯系人!\n");}
}

其實還可以在簡潔一點,上面已經實現了FindContact我們可以用一下:

void Search(const Contact* pc)
{assert(pc);char name[NAME_MAX] = { 0 };printf("請輸入要查找聯系人姓名:> ");scanf("%s", name);int pos = FindContact(pc, name);if (pos != -1){Print(pc, pos);}else{printf("沒有此聯系人!\n");}
}

看效果:

8、修改聯系人信息

修改聯系人信息這塊就有很多可能,比如只修改一項例如名字或性別等,也有可能修改多項例如名字、年齡等,也有可能得全部修改這幾種情況。當我們要修改之前群毆我們能還是期望有一個菜單供我們選擇,當修改完一項后我們可能還要繼續修改。基于此我們采用和test.c文件中得do...while循環+菜單!

//修改聯系人信息菜單
void menu1()
{system("cls");printf("*****************************************\n");printf("********* 1. name     2. age   **********\n");printf("********* 3. sex      4. tele  **********\n");printf("********* 5. addr     6. all   **********\n");printf("********* 0. exit              **********\n");printf("*****************************************\n");
}//修改名字
void ModName(Contact* pc, int ret)
{assert(pc);printf("請輸入修改后聯系人姓名:> ");scanf("%s", pc->data[ret].name);printf("修改成功!\n");
}//修改年齡
void ModAge(Contact* pc, int ret)
{assert(pc);printf("請輸入修改后聯系人年齡:> ");scanf("%d", &pc->data[ret].age);printf("修改成功!\n");
}//修改性別
void ModSex(Contact* pc, int ret)
{assert(pc);printf("請輸入修改后聯系人性別:> ");scanf("%s", &pc->data[ret].sex);printf("修改成功!\n");
}//修改電話
void ModTele(Contact* pc, int ret)
{assert(pc);printf("請輸入修改后聯系人電話:> ");scanf("%s", &pc->data[ret].tele);printf("修改成功!\n");
}//修改住址
void ModAddr(Contact* pc, int ret)
{assert(pc);printf("請輸入修改后聯系人住址:> ");scanf("%s", &pc->data[ret].addr);printf("修改成功!\n");
}void ModAll(Contact* pc, int ret)
{assert(pc);printf("請輸入聯系人姓名:> ");scanf("%s", pc->data[ret].name);printf("請輸入聯系人年齡:> ");scanf("%d", &pc->data[ret].age);printf("請輸入聯系人性別:> ");scanf("%s", pc->data[ret].sex);printf("請輸入聯系人電話:> ");scanf("%s", pc->data[ret].tele);printf("請輸入聯系人住址:> ");scanf("%s", pc->data[ret].addr);printf("修改成功!\n");
}//修改聯系人
void ModContact(Contact* pc)
{assert(pc);//判斷是否為空if (pc->sz == 0){printf("通訊錄為空,無法修改!\n");return;}char name[NAME_MAX] = { 0 };printf("請輸入要修改系人姓名:> ");scanf("%s", name);//判斷是否有該聯系人int ret = FindContact(pc, name);//有該聯系人if (ret != -1){int n = 0;do{menu1();printf("請選擇修改內容:> ");scanf("%d", &n);//修改switch (n){case 1:ModName(pc,ret);break;case 2:ModAge(pc, ret);break;case 3:ModSex(pc, ret);break;case 4:ModTele(pc, ret);break;case 5:ModAddr(pc, ret);break;case 6:ModAll(pc, ret);break;case 0:printf("修改結束!\n");break;default:printf("選擇數非法!\n");break;}} while (n);}else{printf("沒有此聯系人!\n");}
}

看效果:(小編做了清屏)

修改前:

?修改后:

OK,還是比較成功的!我們再來進行對他實現一下排序!

9、排序聯系人信息

我們上面已經實現了通訊錄的增刪查改的基本功能!我們想讓他再有一個排序功能,比如按名字排序,或年齡排序!我們在指針進階那塊介紹過回調函數,這里我們用qsort進行對通訊錄排序!我們期望還是和上面一樣一開始有個菜單選擇!


//排序菜單
void menu2()
{system("cls");printf("**********************************\n");printf("***** 1. name    2. age **********\n");printf("**********************************\n");
}//名字比較函數
int cmp_name(const void* str1, const void* str2)
{//return strcmp(((PeoInfo*)str1)->name, ((PeoInfo*)str2)->name);return strcmp((((Contact*)str1)->data)->name, (((Contact*)str2)->data)->name);
}//名字排序
void SortName(Contact* pc)
{qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_name);
}//年齡比較函數
int cmp_age(const void* str1, const void* str2)
{//return ((PeoInfo*)str1)->age - ((PeoInfo*)str2)->age;return (((Contact*)str1)->data)->age - (((Contact*)str2)->data)->age;
}
//年齡排序
void SortAge(Contact* pc)
{qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_age);
}//排序聯系人信息
void SortContact(Contact* pc)
{assert(pc);//判斷為空if (pc->sz == 0){printf("通訊錄為空,無法排序!\n");Sleep(3000);system("cls");return;}menu2();int n = 0;printf("請選擇排序方式:> ");scanf("%d", &n);//排序switch (n){case 1:SortName(pc);system("cls");printf("排序成功!\n");break;case 2:SortAge(pc);system("cls");printf("排序成功!\n");break;default:printf("選擇數非法!\n");Sleep(3000);system("cls");break;}
}

看效果:

排序前(年齡):

?排序后(年齡):

排序前(名字):

?排序后(名字):

OK,實現了排序!

三、全部源碼

?contact.h

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<stdlib.h>
#include<windows.h>#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 15
#define ADDR_MAX 20
#define MAX 100typedef struct PeoInfo
{char name[NAME_MAX];int age;char sex[SEX_MAX];char tele[TELE_MAX];char addr[ADDR_MAX];
}PeoInfo;typedef struct Contact
{PeoInfo data[MAX];int sz;
}Contact;//初始化通訊錄
void InitContact(Contact* pc);//添加聯系人
void AddContact(Contact* pc);//顯示聯系人
void ShowContact(const Contact* pc);//刪除聯系人
void DelContact(Contact* pc);//查找指定聯系人
void Search(const Contact* pc);//修改聯系人
void ModContact(Contact* pc);//排序聯系人信息
void SortContact(Contact* pc);

contact.c

#include"contact.h"//初始化通訊錄
void InitContact(Contact* pc)
{assert(pc);memset(pc->data, 0, sizeof(pc->data));pc->sz = 0;
}//增加聯系人
void AddContact(Contact* pc) 
{assert(pc);//通訊錄已滿if (pc->sz == MAX){printf("通訊錄已滿,無法添加!\n");Sleep(2000);return;}//添加聯系人printf("請輸入聯系人姓名:> ");scanf("%s", pc->data[pc->sz].name);printf("請輸入聯系人年齡:> ");scanf("%d", &pc->data[pc->sz].age);printf("請輸入聯系人性別:> ");scanf("%s", pc->data[pc->sz].sex);printf("請輸入聯系人電話:> ");scanf("%s", pc->data[pc->sz].tele);printf("請輸入聯系人住址:> ");scanf("%s", pc->data[pc->sz].addr);pc->sz++;printf("添加成功!\n");Sleep(1000);
}//顯示聯系人
void ShowContact(const Contact* pc)
{assert(pc);printf("%-s\t%-s\t%-5s\t%-15s\t%-20s\n", "姓名", "年齡", "性別", "電話", "住址");for (int i = 0; i < pc->sz; i++){printf("%-s\t%-d\t%-5s\t%-15s\t%-20s\n",pc->data[i].name,pc->data[i].age,pc->data[i].sex,pc->data[i].tele,pc->data[i].addr);}
}//查找要刪除的人并返回下標
int FindContact(const Contact* pc, const char* name)
{for (int i = 0; i < pc->sz; i++){if (strcmp(pc->data[i].name, name) == 0){return i;//找到了}}return -1;//沒找到
}//刪除聯系人
void DelContact(Contact* pc)
{assert(pc);if (pc->sz == 0){printf("通訊錄為空,無法刪除!\n");Sleep(2000);return;}char name[NAME_MAX] = { 0 };printf("請輸入要刪除人的姓名:> ");scanf("%s", name);int pos = FindContact(pc, name);if (pos != -1){//刪除for (int i = pos; i < pc->sz - 1; i++){pc->data[i] = pc->data[i + 1];}pc->sz--;printf("成功刪除聯系人!\n");Sleep(1000);}else{printf("沒有此聯系人!\n");Sleep(2000);}
}//顯示單個聯系人信息
void Print(const Contact* pc, int pos)
{assert(pc);printf("%-s\t%-s\t%-5s\t%-15s\t%-20s\n", "姓名", "年齡", "性別", "電話", "住址");printf("%-s\t%-d\t%-5s\t%-15s\t%-20s\n",pc->data[pos].name,pc->data[pos].age,pc->data[pos].sex,pc->data[pos].tele,pc->data[pos].addr);}//查找指定聯系人
void Search(const Contact* pc)
{assert(pc);char name[NAME_MAX] = { 0 };printf("請輸入要查找聯系人姓名:> ");scanf("%s", name);int pos = FindContact(pc, name);if (pos != -1){Print(pc, pos);}else{printf("沒有此聯系人!\n");Sleep(2000);system("cls");}
}//修改聯系人信息菜單
void menu1()
{system("cls");printf("*****************************************\n");printf("********* 1. name     2. age   **********\n");printf("********* 3. sex      4. tele  **********\n");printf("********* 5. addr     6. all   **********\n");printf("********* 0. exit              **********\n");printf("*****************************************\n");
}//修改名字
void ModName(Contact* pc, int ret)
{assert(pc);printf("請輸入修改后聯系人姓名:> ");scanf("%s", pc->data[ret].name);
}//修改年齡
void ModAge(Contact* pc, int ret)
{assert(pc);printf("請輸入修改后聯系人年齡:> ");scanf("%d", &pc->data[ret].age);
}//修改性別
void ModSex(Contact* pc, int ret)
{assert(pc);printf("請輸入修改后聯系人性別:> ");scanf("%s", &pc->data[ret].sex);
}//修改電話
void ModTele(Contact* pc, int ret)
{assert(pc);printf("請輸入修改后聯系人電話:> ");scanf("%s", &pc->data[ret].tele);
}//修改住址
void ModAddr(Contact* pc, int ret)
{assert(pc);printf("請輸入修改后聯系人住址:> ");scanf("%s", &pc->data[ret].addr);
}void ModAll(Contact* pc, int ret)
{assert(pc);printf("請輸入聯系人姓名:> ");scanf("%s", pc->data[ret].name);printf("請輸入聯系人年齡:> ");scanf("%d", &pc->data[ret].age);printf("請輸入聯系人性別:> ");scanf("%s", pc->data[ret].sex);printf("請輸入聯系人電話:> ");scanf("%s", pc->data[ret].tele);printf("請輸入聯系人住址:> ");scanf("%s", pc->data[ret].addr);
}//修改聯系人
void ModContact(Contact* pc)
{assert(pc);//判斷是否為空if (pc->sz == 0){printf("通訊錄為空,無法修改!\n");Sleep(2000);system("cls");return;}char name[NAME_MAX] = { 0 };printf("請輸入要修改系人姓名:> ");scanf("%s", name);//判斷是否有該聯系人int ret = FindContact(pc, name);//有該聯系人if (ret != -1){int n = 0;do{menu1();Print(pc, ret);printf("請選擇修改內容:> ");scanf("%d", &n);//修改switch (n){case 1:ModName(pc,ret);break;case 2:ModAge(pc, ret);break;case 3:ModSex(pc, ret);break;case 4:ModTele(pc, ret);break;case 5:ModAddr(pc, ret);break;case 6:ModAll(pc, ret);break;case 0:printf("修改結束!\n");Sleep(2000);system("cls");break;default:printf("選擇數非法!\n");Sleep(2000);system("cls");break;}} while (n);}else{printf("沒有此聯系人!\n");Sleep(2000);system("cls");}
}//排序菜單
void menu2()
{system("cls");printf("**********************************\n");printf("***** 1. name    2. age **********\n");printf("**********************************\n");
}//名字比較函數
int cmp_name(const void* str1, const void* str2)
{//return strcmp(((PeoInfo*)str1)->name, ((PeoInfo*)str2)->name);return strcmp((((Contact*)str1)->data)->name, (((Contact*)str2)->data)->name);
}//名字排序
void SortName(Contact* pc)
{qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_name);
}//年齡比較函數
int cmp_age(const void* str1, const void* str2)
{//return ((PeoInfo*)str1)->age - ((PeoInfo*)str2)->age;return (((Contact*)str1)->data)->age - (((Contact*)str2)->data)->age;
}
//年齡排序
void SortAge(Contact* pc)
{qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_age);
}//排序聯系人信息
void SortContact(Contact* pc)
{assert(pc);//判斷為空if (pc->sz == 0){printf("通訊錄為空,無法排序!\n");Sleep(3000);system("cls");return;}menu2();int n = 0;printf("請選擇排序方式:> ");scanf("%d", &n);//排序switch (n){case 1:SortName(pc);system("cls");printf("排序成功!\n");break;case 2:SortAge(pc);system("cls");printf("排序成功!\n");break;default:printf("選擇數非法!\n");Sleep(3000);system("cls");break;}
}

test.c

#include"contact.h"void menu()
{printf("*****************************************\n");printf("********* 1. add     2. del    **********\n");printf("********* 3. search  4. modify **********\n");printf("********* 5. show    6. sort   **********\n");printf("********* 0. exit              **********\n");printf("*****************************************\n");
}void test()
{int input = 0;Contact con;InitContact(&con);do{menu();printf("請選擇操作數:> ");scanf("%d", &input);switch (input){case 1:AddContact(&con);system("cls");break;case 2:DelContact(&con);system("cls"); break;case 3:system("cls");Search(&con);break;case 4:ModContact(&con);break;case 5:system("cls");ShowContact(&con);break;case 6:SortContact(&con);break;case 0:printf("退出成功!\n");break;default:printf("選擇數非法!\n");break;}} while (input);
}int main()
{test();return 0;
}

OK,本期分享就到這里!好兄弟,我們下期再見!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/43529.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/43529.shtml
英文地址,請注明出處:http://en.pswp.cn/news/43529.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java SpringBoot Vue ERP系統

系統介紹 該ERP系統基于SpringBoot框架和SaaS模式&#xff0c;支持多租戶&#xff0c;專注進銷存財務生產功能。主要模塊有零售管理、采購管理、銷售管理、倉庫管理、財務管理、報表查詢、系統管理等。支持預付款、收入支出、倉庫調撥、組裝拆卸、訂單等特色功能。擁有商品庫存…

ubuntu設置共享文件夾成功后卻不顯示找不到(已解決)

1.首先輸下面命令查看是否真的設置成功共享文件夾 vmware-hgfsclient如果確實已經設置過共享文件夾將輸出window下共享文件夾名字 2.確認自己已設置共享文件夾后輸入下面的命令 //如果之前沒有命令包則先執行sudo apt-get install open-vm-tools sudo vmhgfs-fuse .host:/ /mn…

十六、Spring Cloud Sleuth 分布式請求鏈路追蹤

目錄 一、概述1、為什么出出現這個技術&#xff1f;需要解決哪些問題2、是什么&#xff1f;3、解決 二、搭建鏈路監控步驟1、下載運行zipkin2、服務提供者3、服務調用者4、測試 一、概述 1、為什么出出現這個技術&#xff1f;需要解決哪些問題 2、是什么&#xff1f; 官網&am…

spss---如何使用信度分析以及案例分析

信度分析 問卷調查法是教育研究中廣泛采用的一種調查方法&#xff0c;根據調查目的設計的調查問卷是問卷調查法獲取信息的工具&#xff0c;其質量高低對調查結果的真實性、適用性等具有決定性的作用。 為了保證問卷具有較高的可靠性和有效性&#xff0c;在形成正式問卷之 前&…

CLion:最好用的c/c++編寫工具(最詳細安裝教程)

目錄 一.前言介紹 1.下載安裝 1.1右上角點擊下載 1.2選擇自己操作系統&#xff0c;然后點擊下載 1.3選擇next 1.4 更改路徑 1.5D盤最好 1.6 按照我的選擇配置環境 1.7install安裝 1.8 安裝完成 2、mingw64安裝 2.1下載資源壓縮包 2.2mingw64放入到合適的位置&#xff0c;…

Redis五大基本數據類型及其使用場景

文章目錄 **一 什么是NoSQL&#xff1f;****二 redis是什么&#xff1f;****三 redis五大基本類型**1 String&#xff08;字符串&#xff09;**應用場景** 2 List&#xff08;列表&#xff09;**應用場景** 3 Set&#xff08;集合&#xff09;4 sorted set&#xff08;有序集合…

高級藝術二維碼制作教程

最近不少關于二維碼制作的&#xff0c;而且都是付費。大概就是一個好看的二維碼&#xff0c;掃描后跳轉網址。本篇文章使用Python來實現&#xff0c;這么簡單花啥錢呢&#xff1f;學會&#xff0c;拿去賣便宜點吧。 文章目錄 高級二維碼制作環境安裝普通二維碼藝術二維碼動態 …

【LVS】2、部署LVS-DR群集

LVS-DR數據包的流向分析 1.客戶端發送請求到負載均衡器&#xff0c;請求的數據報文到達內核空間&#xff1b; 2.負載均衡服務器和正式服務器在同一個網絡中&#xff0c;數據通過二層數據鏈路層來傳輸&#xff1b; 3.內核空間判斷數據包的目標IP是本機VIP&#xff0c;此時IP虛…

批量將Excel中的第二列內容從拼音轉換為漢字

要批量將Excel中的第二列內容從拼音轉換為漢字&#xff0c;您可以使用Python的openpyxl庫來實現。下面是一個示例代碼&#xff0c;演示如何讀取Excel文件并將第二列內容進行拼音轉漢字&#xff1a; from openpyxl import load_workbook from xpinyin import Pinyin # 打開Exce…

Android kotlin系列講解(入門篇)使用Intent在Activity之間穿梭

<<返回總目錄 上一篇:Android kotlin系列講解(入門篇)Activity的理解與基本用法 文章目錄 1、使用顯式Intent2、使用隱式Intent3、更多隱式Intent的用法4、向下一個Activity傳遞數據5、返回數據給上一個Activity1、使用顯式Intent 你應該已經對創建Activity的流程比較…

SASS 學習筆記

SASS 學習筆記 總共會寫兩個練手項目&#xff0c;成品在 https://goldenaarcher.com/scss-study 可以看到&#xff0c;代碼在 https://github.com/GoldenaArcher/scss-study。 什么是 SASS SASS 是 CSS 預處理&#xff0c;它提供了變量&#xff08;雖然現在 CSS 也提供了&am…

C++ 面向對象三大特性——繼承

?<1>主頁&#xff1a;我的代碼愛吃辣 &#x1f4c3;<2>知識講解&#xff1a;C 繼承 ??<3>開發環境&#xff1a;Visual Studio 2022 &#x1f4ac;<4>前言&#xff1a;面向對象三大特性的&#xff0c;封裝&#xff0c;繼承&#xff0c;多態&#xff…

【數倉建設系列之一】什么是數據倉庫?

一、什么是數據倉庫&#xff1f; 數據倉庫(Data Warehouse&#xff0c;簡稱DW)簡單來講&#xff0c;它是一個存儲和管理大量結構化和非結構化數據的存儲集合&#xff0c;它以主題為向導&#xff0c;通過整合來自不同數據源下的數據(比如各業務數據&#xff0c;日志文件數據等)…

內網穿透和服務器+IP 實現公網訪問內網的區別

內網穿透和服務器IP 實現公網訪問內網的區別在于實現方式和使用場景。 內網穿透&#xff08;Port Forwarding&#xff09;&#xff1a;內網穿透是一種通過網絡技術將公網用戶的請求通過中轉服務器傳輸到內網設備的方法。通過在路由器或防火墻上進行配置&#xff0c;將公網請求…

MySQL- sql語句基礎

文章目錄 1.select后對表進行修改&#xff08;delete&#xff09;2.函數GROUP_CONCAT()3.使用正則表達式3.DATE_FORMAT()4.count() 加條件 1.select后對表進行修改&#xff08;delete&#xff09; 報錯&#xff1a;You can’t specify target table ‘Person’ for update in …

proteus結合keil-arm編譯器構建STM32單片機項目進行仿真

proteus是可以直接創建設計圖和源碼的&#xff0c;但是源碼編譯它需要借助keil-arm編譯器&#xff0c;也就是我們安裝keil-mdk之后自帶的編譯器。 下面給出一個完整的示例&#xff0c;主要是做一個LED燈閃爍的效果。 新建工程指定路徑&#xff0c;Schematic,PCB layout都選擇默…

【Docker】 使用Docker-Compose 搭建基于 WordPress 的博客網站

引 本文將使用流行的博客搭建工具 WordPress 搭建一個私人博客站點。部署過程中使用到了 Docker 、MySQL 。站點搭建完成后經行了發布文章的體驗。 WordPress WordPress 是一個廣泛使用的開源內容管理系統&#xff08;CMS&#xff09;&#xff0c;用于構建和管理網站、博客和…

單例設計模式精講(餓漢式和懶漢式實現的重要方法)

目錄 什么叫做單例模式&#xff1f; 餓漢式和懶漢式的區別&#xff1f; 餓漢式-方式1&#xff08;靜態變量方式&#xff09; 餓漢式-方式2&#xff08;靜態代碼塊方式&#xff09; 懶漢式-方式1&#xff08;線程不安全&#xff09; 懶漢式-方式2&#xff08;線程安全&…

FifthOne:用于矢量搜索的計算機視覺接口

一、說明 數據太多了。數據湖和數據倉庫;廣闊的像素牧場和充滿文字的海洋。找到正確的數據就像大海撈針一樣&#xff01;如果你喜歡開源機器學習庫 FiftyOne&#xff0c;矢量搜索引擎通過將復雜數據&#xff08;圖像的原始像素值、文本文檔中的字符&#xff09;轉換為稱為嵌入矢…

PHP報錯:未定義常量的解決方法!

PHP報錯&#xff1a;未定義常量的解決方法&#xff01; 在PHP編程中&#xff0c;我們經常會遇到常量未定義的錯誤。這種錯誤通常會在代碼中使用未定義的常量時發生。本文將介紹常量的概念以及如何解決未定義常量的問題。 首先&#xff0c;讓我們來了解什么是常量。在PHP中&am…