漫畫C語言 做個聊天軟件你不懂也得懂

學完C語言做不出東西?不存在的,咱們做一個最“隱私”的聊天器,就倆人,你和我。咱們聊天的信息你知我知沒別人知。

對了,本文評論區點贊、收藏抽獎。
社區也有抽獎,本周社區抽獎帖子 :https://bbs.csdn.net/topics/603458199
以上兩個抽獎都是周日開獎,名額十個,然后書、日歷等獎品都有。.
沒學過C語言的,覺得難的看這里:https://blog.csdn.net/a757291228/category_11468001.html

我們直接開始寫代碼,只要你會基礎的C語言,不要擔心看不懂,不懂的我幫你刨根問底,把根都挖出來嚼爛,絕對懂。
在這里插入圖片描述

一、一個聊天軟件的基礎模型是怎么樣的?

你是個新手的話你可能就會問,什么是模型?!聽不懂,我在騙你學習。放心,我現在就告訴你什么是基礎“模型”。

我們可以簡單的理解“模型”指這個聊天軟件基本是怎么進行通信的,常規形式是怎樣的,只要清楚了這個形式流程,然后在這個流程中添加一些代碼就ok了,啥都不用想。如果你還是不懂什么是“流程”,那我就跟你說這個是一個步驟,只需要懂這個步驟,我們使用代碼編寫這個步驟就可以完成了。

好了,現在沒啥問題了吧?現在開始,第一步在一個通信中,一般有一個服務端。那什么是服務端?

1.1 什么是服務端

服務端就簡單了,曾經…曾經…你去例如移動或者聯通的營業挺,客服小姐姐就會對你提供服務,例如業務辦理,辦個卡,銷個號等,那我們的服務端是用來通信的,所以這個服務端就是指等待跟我聊天的人,只要你上線了,開電腦打開軟件了,連接上我的服務端了,咱們就可以聊天了。

服務端一般就是一直在這里等你上線的那個,風里雨里我在這里等你。

1.2 又不懂什么是客戶端了?

不懂沒關系,打游戲懂吧?你下載到你電腦你手機的就是客戶端,你打個游戲如果沒有服務端就不能跟人匹配,這個懂了吧?

1.3 基本的工具要拿過來吧?

還知道頭文件吧?
頭文件就等于是一個工具箱,需要干啥就可以使用拿頭文件過來,這樣就可以用里面的工具了。
那咱們做一個聊天的軟件就需要一個工具箱吧,這個工具箱叫做“winsock2.h”,那怎么拿呢?都知道#include<> 吧?
那就直接把這個頭文件拿過來就好了,代碼就可以寫成:#include<winsock2.h>
常規的輸入輸出工具箱也要拿吧?所以就第一步把 stdio.h 也拿過來,所以這個服務端的第一行第二行代碼就寫成:

#include<stdio.h>
#include<WinSock2.h>

1.4 開始 socket 編程

不會了不會了!是不是一說 socket 你就說這是個什么鬼?
我先說一句讓你懵逼的定義“socket 就是應用之間通信的端點”。懂不懂?
不懂呀,那我繼續說。
socket 就是兩個通信軟件之間的接口,你可以當成服務端是“插座”,客戶端是“插頭”,一插,歐了!這樣不就通電了,這樣說你明白了吧?
當然這樣解釋比較片面,但用“抽象”的方式講又不一定能讓大家聽得懂,所以你就理解成插頭肯定沒問題。
在這里插入圖片描述

1.5 開始抬杠我拿三座插兩座插不進!


咱們用的插頭都是有標準的,你想想,沒有標準怎么那么多電器都可以用常規的插頭?
像這個 socket 這個通信端口,是有基于一些標準的。例如 TCP/IP這些通信協議。
好了,我說了TCP/IP可能就會有同學問,這又是什么鬼!沒關系,你只需要知道這個是一個通信協議,咱們現在是用 socket 進行通信就好,知道 socket 怎么用就行,協議咱們可不需要現在搞懂,咱們只需要知道 socket 如何運用即可。

二、開始敲服務端代碼

2.1 搞清楚使用 socket 進行通信的步驟

編寫C語言Windows下的socket需要經過幾個步驟:首先對WSAStartup 進行初始化,初始化對socket 套接字(socket也叫套接字)進行創建,隨后配合綁定信息,接著進行配置信息的bind 綁定;綁定了信息后,通過該信息進行isten 監聽,監聽后若有鏈接則connect 連接,再接下來開始使用accept 接收請求,得到請求后可以選擇接受recv或者send發送數據,最后closesocket 關閉 socket,WSACleanup 最終關閉。

簡單點就是下面的這個流程:

不懂了?不懂就慢慢來嘛。

這是進行 socket 編程的步驟,如果你要問為什么要這樣做…我只能回答你規定的流程就這樣,因為你要進行通信,那肯定需要創建一個 socket ,創建完畢后那么肯定要綁定你要通信的信息,如果你不綁定你怎么知道你要跟誰說話呢?急著我收到了一個信息后就等于跟我請求通話,我同意了,咱們就開始通信了,通信肯定要發送信息,那就用send這些方法發送了,最后面說完話我就關閉這個 socket了,那你說不是嗎?

還不懂?那你看下面。

請添加圖片描述

2.1 第一步初始化

既然第一步是初始化,那我要初始化什么東西?
我們需要初始化一個 WSADATA 類型數據的對象。
什么鬼?又是 WSADATA 又是對象的,聽不懂啊!
沒關系的拉,WSADATA 其實就是一個結構體,咱們在把使用socket的工具箱 WinSock2 拿過來的時候這個 WSADATA 結構體就已經創建好了,直接使用這個結構體創建一個結構體變量就好了。

WSADATA 的作用就是用來存儲初始化信息的,就像你打個游戲初始化創建一個人,這個人總得有信息吧,光頭、小眼睛、腿短…對吧?

那么我們的代碼就可以寫成以下:

#include<stdio.h>
#include<WinSock2.h>
#include <stdlib.h>
int main(){WSADATA wsaData;
}

接下來就可以開始初始化了,初始化 socket 有一個函數叫做 WSAStartup,既然是函數一般都有參數吧,參數有哪些呢?
這個 WSAStartup 方法需要傳入一個 版本號,還有一個用于存儲信息的 WSADATA 結構體。現在我們已經知道 WSADATA 的結構體就是上面這個代碼創建的 wsaData 結構體變量,那么版本號又是什么?

這個版本號是說明我們使用哪個 Winsock 版本,Winsock 有一個 1.1 版本還有一個 2.2 版本。兩個版本有不同,1.1 版本只支持 TCP/IP 協議,還有一個版本 2.2 支持多個協議,這個時候你懂用哪個了吧?

什么?! 還不懂? 那肯定是全都要呀!
2.2 版本兼容性之類的更好,兼容啥我們不管,反正用多的。
那直接寫成 WSAStartup(2, 2, &wsaData)

不不不,我們寫法有一些不同,需要用一個函數 MAKEWORD 對版本進行生成,就像這樣 WSAStartup(MAKEWORD(2, 2), &wsadata);,規定咱們使用 MAKEWORD 告訴 WSAStartup 初始化調用什么版本。

那么整個初始化的代碼就如下所示咯:

#include<stdio.h>
#include<WinSock2.h>
#include <stdlib.h>
int main(){WSADATA wsaData;WSAStartup(MAKEWORD(2, 2), &wsadata);
}

什么?不懂 &wsadata ?來來來,我們的漫畫同學告訴你是啥意思:


懂了吧?傳個地址方便信息存儲。

2.2 第二步創建 socket

這一步超級簡單,代碼就是這個:

SOCKET serverSock = socket(PF_INET, SOCK_STREAM, 0);

我知道你要罵我,寫什么是什么鬼。
好了好了,首先 SOCKET 是一個socket的類型,還記得 int a 吧?int 是一個類型,那么 SOCKET 肯定就是一個類型了,說明創建一個 SOCKET 類型的變量,然后 socket() 是創建 socket 的函數,這個沒毛病吧?

你說是里面的參數不懂?

小問題了,第一個 PF_INET 就表示指定 IPV4 ,也就是說先給個網絡協議,那么多的網絡協議你總要選一個吧。那為什么要用 IPv4 呢?我只能說用這個東西計算更快,畢竟咱們做個聊天軟件是局域網通信,你就理解為,咱們做的東西是個“小東西”,沒必要那么大“體量”,迷你更好用,那就用那個 IPV4 了,你想不開你也可以用 IPV6 試試。

那 SOCK_STREAM 是什么?SOCK_STREAM 表示咱們進行的通信是 TCP 通信,穩定可靠。在這里使用 SOCK_STREAM 也表示向我們的系統,或者你理解成“計算機”申請一個通信的端口,不然系統不給你“開個口子”,我的數據怎么傳出去對吧,不然就是叫破喉嚨都沒人理我。

那最后一個參數 0 又是什么呢?
這里就是一個編號,說仔細點這個是 socket 所使用的傳輸協議編號,是不是不明白?其實這就是一個編號,不做設置,但是要給一個值,所以就給一個 0 咯。

2.3 第三步綁定信息

綁定信息這一步就有點玄了。在這里咱們要了解兩個結構體,一個是 sockaddr_in,還有一個是 SOCKADDR。需要注意的是,這兩個結構體包含的數據都是一樣的,是一樣的…

主要是使用上有區別。有啥區別?
sockaddr 是個系統用,而 sockaddr 是用來強制轉換 sockaddr_in 結構體給系統調用的函數用。是不是迷茫?不要迷茫,一般都是這樣做,那就這樣做吧。你只需要記住,sockaddr 保存信息然后就別管了,而sockaddr 咱們就用來給參數給函數用。

在 socket 中,咱們使用 sockaddr_in 結構體綁定監聽的 IP 信息,首先需要創建這個結構體:

struct sockaddr_in sockAddr;

接下來始綁定端口、IP類型,其中 127.0.0.1 表示本機、1234 表示監聽端口:

sockAddr.sin_family = PF_INET; //IPv4
sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //服務器的IP
sockAddr.sin_port = htons(1234); //端口

這個懂沒懂?
sockAddr.sin_family 是表示這個結構體中用于存儲IP協議的結構體變量,PF_INET 之前說了是 ipV4,表示在這里設置 ipV4類型。

sockAddr.sin_addr.s_addr 這里是表示需要綁定的 ip 地址,在這里使用 inet_addr(“127.0.0.1”) 進行指定。那為什么指定個 ip 還需要 inet_addr?
inet_addr 的作用是將一個字符串格式的ip地址轉換成一個uint32_t數字格式。為什么要轉換?那肯定是因為 sockAddr.sin_addr.s_addr 是一個 uint32_t 這個類型了。

最后的 sockAddr.sin_port 是表示要指定某一個端口,在這里指定 1234 這個端口。

所以該部分的代碼就寫成這樣了:

#include<stdio.h>
#include<WinSock2.h>
#include <stdlib.h>
int main(){WSADATA wsaData;WSAStartup(MAKEWORD(2, 2), &wsadata);SOCKET serverSock = socket(PF_INET, SOCK_STREAM, 0);struct sockaddr_in sockAddr;sockAddr.sin_family = PF_INET; //IPv4sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //服務器的IPsockAddr.sin_port = htons(1234); //端口
}

最后就是綁定一下了:

bind(serverSock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));

在這里 bind() 方法就是表示綁定信息了,第一個參數是 serverSock 就是表示要綁定的 socket,然后 (SOCKADDR*)&sockAddr 就是需要綁定的地址,最后一個就是一個地址長度。

(SOCKADDR*)&sockAddr 我們講過,SOCKADDR 就是給函數使用的,sockAddr 就是給系統使用的,所以就這樣寫就沒毛病了。

2.4 監聽端口

先讓你懵一下,下面是代碼:

listen(serverSock, 20);

簡單吧?listen 就是表示監聽,第一個參數就是要監聽的 socket 第二個就是表示 同時能處理的最大連接。終于簡單了這一步,你爽我也爽,還不懂就看下面漫畫。

2.5 有人請求聊天?設置個接待員

接下來就是有人請求給你聊天了,那怎么辦呢?一個人忙不過來呢,那就設置個接待員。

SOCKADDR cIntAddr; 
int nSize = sizeof(SOCKADDR);
SOCKET cIntSock = accept(serverSock, (SOCKADDR*)&cIntAddr, &nSize);

accept 函數就是一個接待員,有人連接來敲門了,就需要去接待,換句比較專業的話就是 accept 接收一個套接字中已建立的連接。

傳入的參數第一個 serverSock 就是一個已連接的套接字,(SOCKADDR*)&cIntAddr 是一個按照規定的指向struct sockaddr的指針,所以我猜在前面創建,最后一個就是所指向這個指針的長度咯。

設置完后就等于創建了一個接待員 cIntSock 。
不過要注意,accept 沒有連接的時候就會一直在等待,不然不會執行下面的代碼的。


這一部分的代碼如下:

#include<stdio.h>
#include<WinSock2.h>
#include <stdlib.h>
int main(){WSADATA wsaData;WSAStartup(MAKEWORD(2, 2), &wsadata);SOCKET serverSock = socket(PF_INET, SOCK_STREAM, 0);struct sockaddr_in sockAddr;sockAddr.sin_family = PF_INET; //IPv4sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //服務器的IPsockAddr.sin_port = htons(1234); //端口listen(serverSock, 20);SOCKADDR cIntAddr; int nSize = sizeof(SOCKADDR);SOCKET cIntSock = accept(serverSock, (SOCKADDR*)&cIntAddr, &nSize);
}

2.6 開始循環聊天

在聊天的時候肯定是需要一個循環,不用循環只能發一次信息就完成了,所以肯定有一個 while:

while (1) {


那循環里面寫啥?
當然是寫你接收信息和發送信息的代碼了,我一次性貼上,簡簡單單:

while (1) {char sendBuf[50]={"Hello client"};char recvBuf[50];recv(cIntSock, recvBuf, 50, 0);printf("來自客戶端:");printf("%s\n", recvBuf);printf_s("請輸入內容:");scanf("%s",sendBuf);//sendBuf="s";//gets_s(sendBuf);send(cIntSock, sendBuf, strlen(sendBuf) + 1, 0);}

sendBuf就是一個字符數組,用來輸入自己的要輸入的內容。

主要看recv,recv 接收4個參數,第一個參數是建立的通信、第二個參數是是一個數組,接收數據存放的地方、之后會緩存大小,最后一個參數是指定調用方式,不用管一般設置為0。

cIntSock 就是剛剛從套接字里接受的那個接待員,現在就用接待員和他說話了。

接著就使用printf顯示接待員聽到的話,簡簡單單。

然后就到我們輸入信息,使用scanf夠簡單了吧?
接著使用 send函數發送信息就可以了,第一個就是告訴接待員 cIntSock 要傳達話了,sendBuf 就是咱們要說的話,第三個參數就是咱們說的話的長度,最后一個依舊是0,不用管。

這樣就還差最后一步就完成服務端了,此時咱們只需要關閉套接字就可以了,最后還需要清理一下,完整代碼如下了:

#include<stdio.h>
#include<WinSock2.h>
#include <stdlib.h>int main()
{WSADATA wsadata;WSAStartup(MAKEWORD(2, 2), &wsadata);SOCKET serverSock = socket(PF_INET, SOCK_STREAM, 0);struct sockaddr_in sockAddr;sockAddr.sin_family = PF_INET;sockAddr.sin_addr.s_addr = htons(INADDR_ANY);sockAddr.sin_port = htons(1234);bind(serverSock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));listen(serverSock, 20);SOCKADDR cIntAddr; int nSize = sizeof(SOCKADDR);SOCKET cIntSock = accept(serverSock, (SOCKADDR*)&cIntAddr, &nSize);while (1) {char sendBuf[50]={"Hello client"};char recvBuf[50];recv(cIntSock, recvBuf, 50, 0);printf("來自客戶端:");printf("%s\n", recvBuf);printf_s("請輸入內容:");scanf("%s",sendBuf);send(cIntSock, sendBuf, strlen(sendBuf) + 1, 0);}//關閉closesocket(cIntSock);closesocket(serverSock);WSACleanup();return 0;
}

三、客戶端編寫

客戶端和服務端是一樣的你信嗎?
下面是代碼:

#include<stdio.h>
#include<winsock2.h>int main()
{WSADATA wsadata;int nRes = WSAStartup(MAKEWORD(2, 2), &wsadata);SOCKET sock = socket(PF_INET, SOCK_STREAM, 0);struct sockaddr_in sockAddr;sockAddr.sin_family = PF_INET; sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //只需要在這里指向服務器 ip 就可以了 sockAddr.sin_port = htons(1234);//連接服務器connect(sock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));while (1) {char recvBuf[50];char sendBuf[50]={"Hello server"};printf("跟服務端說: ");scanf("%s",sendBuf);send(sock, sendBuf, strlen(sendBuf) + 1, 0);recv(sock, recvBuf, 50, 0);printf("服務端跟你說: ");printf("%s\n", recvBuf);}closesocket(sock);WSACleanup();system("pause");
}

不同的幾個點只有使用了 connect 連接服務器就沒了,難道你說不是嗎?
簡簡單單對吧?那就行,解決。

下面是演示示例:

注意 若使用devc復制代碼都報錯,則點擊編譯->編譯選項:
在這里插入圖片描述
隨后在出現的窗口中添加如下參數:

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

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

相關文章

【Microstation】第一章:Microstation三維模型構建概述

MicroStation 是國際上和AutoCAD齊名的二維和三維CAD設計軟件&#xff0c;第一個版本由Bentley兄弟在1986年開發完成。其專用格式是DGN&#xff0c;并兼容AutoCAD的DWG/DXF等格式。 MicroStation是Bentley 工程軟件系統有限公司在建筑、土木工程、交通運輸、加工工廠、離散制造…

libgdx游戲引擎開發筆記(十)SuperJumper游戲例子的講解(篇四)---- 主游戲界面內部框架編寫...

上一講&#xff0c;我們已經實現了點擊play進入游戲界面但僅僅是個黑屏 今天&#xff0c;我們就試著編寫代碼讓它出現游戲的一些簡單場景。還是在上一講的代碼基礎上&#xff0c;我們創建兩個類&#xff1a;World 和 WorldRenderer 1.Word類&#xff1a; 12345678910111213141…

看看《System.CommandLine》

記得之前出過幾篇.net tool工具的文章&#xff0c;當時的做法是所有工具的語法分析全部自己解釋&#xff0c;自己執行&#xff0c;語法的解釋占了大部分時間&#xff0c;反而工具的功能被弱化了。其實微軟有一個CommandLine框架在緩慢的發展著&#xff0c;至今都沒有正式發布&a…

Sublime Text 3 import Anaconda 無法正常補全模塊名解決辦法

Sublime Text 3 Anaconda配置 在安裝Sublime Text3之后我們總會安裝一些插件&#xff0c;比如Python的Anaconda自動補全插件。但是&#xff0c;裝好之后發現import 時無法像別的IDE里面那樣自動補全模塊名&#xff0c;就像圖中一樣&#xff1a; 解決辦法在Sublime Text的git…

hdu - 2586 How far away ?(最短路共同祖先問題)

題目鏈接&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid2586 最近公共祖先問題~~LAC離散算法 題目大意&#xff1a;一個村子里有n個房子&#xff0c;這n個房子用n-1條路連接起來&#xff0c;接下了有m次詢問&#xff0c;每次詢問兩個房子a,b之間的距離是多少。 很明顯…

Android之添加固定圖標到桌面

我的QQ群 1 需求 Android之添加固定圖標到桌面 2 部分實現 在AndroidManifest.xml里面添加如下權限 <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" /><uses-permission android:name="com.android.launcher.perm…

想做程序員?不同方向入門路線全解

學習計算機編程有很多方向如果你沒有一個正確的路線&#xff0c;那么就會&#xff1a; 就會跟上面所說的那樣&#xff0c;被迫成為一個全棧&#xff0c;這是比較尷尬的。 若你想比較準確的針對某個方向學習&#xff0c;那就繼續往下看吧。 一、程序員分為哪幾個方向 隨著…

【轉】OpenGL超級寶典筆記——紋理映射Mipmap

原文地址 http://my.oschina.net/sweetdark/blog/177812 , 感謝作者&#xff0c;若非法轉載請聯系本人。 目錄[-] MipmappingMipmap過濾構建Mip層Mipmaps 硬件生成LOD&#xff08;多細節層次&#xff09;偏好紋理對象管理多個紋理常駐紋理紋理優先級回顧Mipmapping Mipmap是一個…

【Microstation】第二章:Microstation三維建模基礎知識

本章的主要內容包括模型的顯示樣式(線框、光滑)、三維定位(V、T、S、F)、Microstation常見的坐標系統(世界坐標系、ACS輔助坐標系、精確繪圖坐標系、)和Microstation的工作區域(2D和3D)。 一、顯示樣式 二、三維定位 三維定位在Microstation中顯得尤為重要,常見…

xtrabackup對MySQL數據庫的備份及恢復教程

xtrabackup xtrabackup 是 percona 的一個開源項目&#xff0c;可以熱備份innodb &#xff0c;XtraDB,和MyISAM&#xff08;會鎖表&#xff09;。對MyISAM存儲引擎會鎖表&#xff0c;也是很郁悶的因為線上使用的是Innodb和MyISAM兩種存儲引擎&#xff0c;比較 頭疼&#xff01;…

實現 EF Core 6 自定義查詢標記

前言在《EF Core使用Simple Logging輸出日志》中&#xff0c;我們介紹了查詢標記 TagWith&#xff0c;它可以幫助我們快速定位到需要的日志&#xff1a;而在 .NET 6 中&#xff0c;新增了另外一個查詢標記 TagWithCallSite&#xff0c;它可以標記出代碼的位置&#xff1a;var u…

LeetCode: 14. Longest Common Prefix

Write a function to find the longest common prefix string amongst an array of strings. 大意就是&#xff0c;寫一個函數可以找到一個數組字符串中的最長前綴。 分析&#xff1a; 最長前綴的最大值為數組字符串中長度最短的字符&#xff0c;由最短字符串由后向前遞減可以得…

jQuery選擇器和選取方法

我們已經使用了帶有簡單Css選擇器的jQuery選取函數:$()。現在是時候深入了解jQuery選擇器語法&#xff0c;以及一些提取和擴充選中元素集的方法了。 一、jQuery選擇器 在CSS3選擇器標淮草案定義的選擇器語法中&#xff0c;jQuery支持相當完整的一套子集&#xff0c;同時還添加了…

0運維?微信小程序云開發增刪查改【05】

在創建小程序時&#xff0c;選擇云開發&#xff1a; 隨后進入項目之后&#xff0c;此時整個目錄如下&#xff1a; 此時我們如圖目錄即可找到首頁位置&#xff1a; 接著咱們清除 index.wxml 代碼內容&#xff1a; 在 index.wxml 中加入如下代碼&#xff1a; <view> …

Android之解決卸載app后再次安裝提示room數據庫錯誤

1、問題 目前只有一個google手機之前安裝了app,里面有room寫的數據庫&#xff0c;后面把app卸載了&#xff0c;再次安裝新的app(修改了數據庫里面的字段)&#xff0c;啟動奔潰。 2、分析 提示數據庫錯誤&#xff0c;很明顯就像以前的app里面的數據庫沒有刪除一樣&#xff0c;…

【Microstation】第三章:Microstation三維模型構建與編輯

本章主要講述三維基本實體繪制、三維構造元素繪制、三維模型編輯。 一、三維基本體素繪制 對于立方體、圓柱、球、圓錐等這些基本立體單位,MS提供了專門的繪圖工具。 基本體素繪制有兩種方式: (1)精確繪圖工具 (2&

文件系統管理相關命令

查看文件系統相關屬性的命令&#xff1a;blkidblkid是一個查看磁盤設備屬性相關信息的命令行工具blkid -L LABEL | UUID :根據UUID查看對應的設備是哪個blkid [-ghlv] [-c file] [-w file] [-o format][-s tag] [-t NAMEvalue] device [device ...]-i&#xff1a;顯示io限制lsb…

CSharpFunctionalExtensions -函數式編程C#的功能擴展

簡介該庫有助于以更實用的方式編寫代碼安裝在NuGet上可用dotnet add package CSharpFunctionalExtensions或者PM> Install-Package CSharpFunctionalExtensions例子Maybe創建一個值Maybe<string> apple Maybe<string>.From("apple");// orMaybe<s…

Android之實現夸克瀏覽器書簽和歷史頁面滑動時候右上角圖標切換效果

1 需求 實現夸克瀏覽器書簽和歷史頁面滑動時候右上角圖標切換效果,頁面滑動的時候,圖標也左右滑動,但是只是顯示其中的一個 https://www.captainai.net/st/ 2 代碼實現 xml布局實現 <LinearLayoutandroid:id="@+id/mainLl"android:layout_width="24d…

ArcGIS 10.6字段計算器(Field Calculator)字段任意填充編碼序列(奇數、偶數序列、自定義間隔)

有關ArcGIS 10.x中屬性數據采集和字段計算器(Field Calculator)的文章,需要的讀者可以參照: 《ArcGIS實驗教程——實驗四:數字化屬性數據的采集》,文章中就屬性數據采集的多種方式做了說明,其中就有字段計算器的詳細說明;《【ArcGIS風暴】ArcGIS 10.2字段計算器(Field…