主頁 > 後端開發 > c++實作檔案復制并修改相應屬性

c++實作檔案復制并修改相應屬性

2020-09-19 15:04:35 後端開發

問題描述

完成一個目錄復制命令mycp,包括目錄下的檔案和子目錄, 運行結果如下:

[email protected] [~/]# ls –la sem

total 56

drwxr-xr-x  3 beta beta 4096 Dec 19 02:53 ./

drwxr-xr-x  8 beta beta 4096 Nov 27 08:49 ../

-rw-r--r--  1 beta beta  128 Nov 27 09:31 Makefile

-rwxr-xr-x  1 beta beta 5705 Nov 27 08:50 consumer*

-rw-r--r--  1 beta beta  349 Nov 27 09:30 consumer.c

drwxr-xr-x  2 beta beta 4096 Dec 19 02:53 subdir/

[email protected] [~/]# mycp sem target

[email protected] [~/]# ls –la target

total 56

drwxr-xr-x  3 beta beta 4096 Dec 19 02:53 ./

drwxr-xr-x  8 beta beta 4096 Nov 27 08:49 ../

-rw-r--r--  1 beta beta  128 Nov 27 09:31 Makefile

-rwxr-xr-x  1 beta beta 5705 Nov 27 08:50 consumer*

-rw-r--r--  1 beta beta  349 Nov 27 09:30 consumer.c

drwxr-xr-x  2 beta beta 4096 Dec 19 02:53 subdir/

思路

這道題目主要涉及檔案讀寫操作和屬性修改,需要支持檔案夾復制、檔案復制,在Linux下還要支持軟鏈接的復制,

思路如下:

  • 獲取待復制目錄的絕對路徑
  • 根據絕對路徑進行dfs或者bfs搜索所有子目錄項
  • 判斷子目錄是屬于什么型別:檔案夾、普通檔案、軟鏈接
  • 分別對三種(Windows下只有檔案夾和檔案)進行復制操作
  • 修改目標檔案屬性與源檔案保持一致

使用到的函式主要有:

Linux

判斷檔案型別

  1. int lstat(const char *pathname, struct stat *statbuf);

    • const char *pathname 需要判斷的檔案的路徑
    • struct stat *statbuf 用于保存檔案屬性
    • return int 0成功,-1失敗
  2. 判斷

    檔案型別 說明 判斷函式 例子
    普通檔案 一般意義上的檔案 S_ISREG() hello.c
    目錄檔案 可包含其他檔案或者目錄 S_ISDIR() /etc/
    字符設備檔案 以無緩沖方式,提供對于設備的可變長度訪問 S_ISCHR() /dev/tty
    塊設備檔案 以帶緩沖方式,提供對于設備的固定長度訪問 S_ISBLK() /dev/sda
    符號鏈接檔案 指向另一個檔案 S_ISLNK() /dev/cdrom
    命名管道檔案 用于行程間通信 S_ISFIFO() /dev/inictl
    網路套接字檔案 用于行程間的網路通信 S_ISSOCK() /dev/log

    值得注意的是,需要先判斷是不是符號鏈接檔案,對符號鏈接檔案進行S_ISREG()判斷時會出現將其判斷為普通檔案的情況,可能是由于他判斷的是鏈接檔案所指向的檔案的型別,因此需要先判斷是不是鏈接檔案,

遍歷檔案目錄

  1. DIR *opendir(const char *name);

    • const char *name 待打開的目錄路徑
    • return DIR 回傳目錄資料結構
  2. struct dirent *readdir(DIR *dirp);

    • ``````DIR *dirp``` 待讀取的目錄

    • return struct dirent* 回傳順序讀取的該目錄下的目錄項

      注意,第一個目錄項是., 第二個目錄項是..

復制檔案

  1. int open(const char *pathname, int flags, mode_t mode);
    • const char* pathname 待打開的檔案路徑
    • int flags O_RDONLY, O_WRONLY, or O_RDWR
    • mode_t mode
    • return int 回傳值是打開的檔案描述符
  2. int creat(const char *pathname, mode_t mode);
    • const char* pathname 待創建的檔案名(可以包含路徑)
    • mode_t mode 創建屬性
    • return int 待創建檔案描述符
  3. ssize_t read(int fd, void *buf, size_t count);
    • int fd 待讀取的檔案的描述符
    • void* buf 讀取的內容存放緩沖區,盡管這里是void*buf在創建的時候應該是```char*``````
    • ? ``````size_t count 要讀取的內容的大小,如果大于fd```中的數目,則讀取相應大小內容
    • return ssize_t 回傳實際讀取的內容的數目,失敗回傳-1
  4. ssize_t write(int fd, const void *buf, size_t count);
    • int fd 要寫入的檔案的描述符
    • const void *buf 要寫入的內容,
    • size_t count 要寫入的內容大小
    • return ssize_t 成功回傳實際寫入的數目,失敗回傳-1

復制檔案夾

復制檔案夾就是創建同名檔案夾

  1. int mkdir(const char *pathname, mode_t mode);
    • const char* pathname 待創建的目錄項的地址
    • mode_t mode 創建目錄項的屬性
    • return int 如果成功回傳為0,否則回傳-1

復制軟鏈接

  1. ssize_t readlink(const char *pathname, char *buf, size_t bufsiz);
    • const cha* pathname 待讀取軟鏈接的路徑
    • char* buf 軟鏈接中的內容保存到buf
    • size_t bufsiz buf緩沖區的大小
    • return ssize_t 回傳值是軟鏈接指向路徑的長度
  2. int symlink(const char *target, const char *linkpath);
    • const char* target 待創建的軟鏈接的路徑
    • const char* linkpath 待創建的軟鏈接所指向的路徑
    • return int 成功回傳0,否則回傳-1

獲取屬性

  1. int lstat(const char *pathname, struct stat *statbuf);

    • const char *pathname 需要提取屬性的檔案或者檔案夾的路徑
    • struct stat *statbuf 獲取到的屬性存盤緩沖區
    • return int 成功回傳0,否則-1
  2. int chmod(const char *pathname, mode_t mode);

    • const char *pathname 待修改屬性的檔案的路徑
    • mode_t mode 將待修改檔案修改改為該屬性
    • return int 若成功回傳0,否則回傳-1
  3. int chown(const char *pathname, uid_t owner, gid_t group);

    • const char* pathname 待更改的目錄路徑
    • uid_t owner 如果是-1則不改變屬性
    • gid_t group 如果是-1則不改變屬性
  4. int lutimes(const char *filename, const struct timeval tv[2]);

    這個命令用于修改目標檔案的access_time modify_timelutimes可以修改軟鏈接的屬性,

    • const char *filename 待修改的檔案路徑
    • const struct timeval tv[2] tv[0]access_timetv[1]modify_time
    • return int 如果成功回傳0,否則回傳-1

Windows

這里主要列出所用到的函式,有需要的話可以詳細去查相關的函式說明:

FindFirstFile

FindNextFile

CreateFile

GetFileSize

ReadFile

WriteFile

_wmkdir

GetFileAttributes

SetFileAttributes

GetFileTime

FileTimeToSystemTime

SetFileTime

源代碼實作

Linux

#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <utime.h>
#include <time.h> 
#include <sys/time.h>
//檔案夾復制采用dfs或者bfs進行搜索是等價的
void search_dfs(char *src_path, char *dest_path);
//復制檔案
void copy_file(const char *src_file, const char *dst_file);
//復制檔案夾
void copy_dir(const char *src_dir, const char *dst_dir);
//復制軟鏈接
void copy_sln(const char *src_file, const char *dst_file);
//修改檔案屬性與源檔案保持一致
void changeAttr(const char *src, const char *dst);
//修改路徑
void change_path(char *src, char *cat)
{
    strcat(src, (char *)"/");
    strcat(src, cat);
}

int main(int argc, char const *argv[])
{
    if (argc < 3)
    {
        printf("No file or directory specified\n");
        exit(-1);
    }
    if (argc > 3)
    {
        printf("Too many arguments\n");
        exit(-1);
    }

    char src[1024], dest[1024];
    char *current_dir = getcwd(NULL, 0);

    struct stat state_of_entry;
    lstat(argv[1], &state_of_entry);
    if (S_ISDIR(state_of_entry.st_mode)) //目錄
    {
        if (chdir(argv[1])) //目錄錯誤
        {
            perror("chdir");
            exit(-1);
        }
        strcpy(src, getcwd(NULL, 0)); //獲取源檔案夾絕對路徑
        chdir(current_dir);
        lstat(argv[2], &state_of_entry);
        if (S_ISDIR(state_of_entry.st_mode)) //目錄
        {
            if (chdir(argv[2])) //目錄錯誤
            {
                perror("chdir");
                exit(-1);
            }
            strcpy(dest, getcwd(NULL, 0)); //獲取目標檔案夾絕對路徑
            chdir(current_dir);
            chdir(dest);
            // printf("SRC: %s\n", src);
            // printf("DEST: %s\n", dest);
            chdir(src);
            search_dfs(src, dest);
        }
        else
        {
            printf("error. No destination directory.\n");
            exit(-1);
        }
    }

    else //檔案直接復制
    {
        char dest[1024];
        lstat(argv[2], &state_of_entry);
        if (S_ISDIR(state_of_entry.st_mode)) //目錄
        {
            strcpy(dest, getcwd(NULL, 0)); //獲取目標檔案夾絕對路徑
        }
        else
        {
            strcpy(dest, "./");
            strcat(dest, argv[2]);
        }
        copy_file(argv[1], argv[2]);
    }

    return 0;
}

void search_dfs(char *src_path, char *dest_path)
{
    // printf("Searching directory:    %s\n", getcwd(NULL, 0));
    DIR *src_dir = opendir(src_path);
    DIR *dest_dir = opendir(dest_path);
    struct dirent *entry = NULL;
    struct stat state_of_entry;
    while ((entry = readdir(src_dir)) != NULL)
    {
        lstat(entry->d_name, &state_of_entry);
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
            continue;
        // printf("entry->d_name: %s\n", entry->d_name);
        if (S_ISLNK(state_of_entry.st_mode)) //符號鏈接
        {
            char src_file[1024];
            char dest_file[1024];
            strcpy(src_file, src_path);
            change_path(src_file, entry->d_name);
            strcpy(dest_file, dest_path);
            change_path(dest_file, entry->d_name);
            // printf("src file: %s\n", src_file);
            // printf("dest file: %s\n", dest_file);
            copy_sln(src_file, dest_file);
        }
        else if (S_ISREG(state_of_entry.st_mode)) //普通檔案
        {
            char src_file[1024];
            char dest_file[1024];
            strcpy(src_file, src_path);
            change_path(src_file, entry->d_name);
            strcpy(dest_file, dest_path);
            change_path(dest_file, entry->d_name);
            // printf("src file: %s\n", src_file);
            // printf("dest file: %s\n", dest_file);
            copy_file(src_file, dest_file);
        }
        else if (S_ISDIR(state_of_entry.st_mode)) //目錄
        {
            char src[1024];
            char dest[1024];
            strcpy(src, src_path);
            change_path(src, entry->d_name);
            strcpy(dest, dest_path);
            change_path(dest, entry->d_name);
            // printf("src dir: %s\n", src);
            // printf("dest dir: %s\n", dest);
            copy_dir(src, dest);
            search_dfs(src, dest);
        }
    }
}

void copy_file(const char *src_file, const char *dest_file)
{
    int src_fd = open(src_file, O_RDONLY);
    int dest_fd = creat(dest_file, O_WRONLY);

    unsigned char buf[1024];
    while (read(src_fd, buf, sizeof(buf)) > 0)
    {
        write(dest_fd, buf, sizeof(buf));
    }

    changeAttr(src_file, dest_file);

    close(src_fd);
    close(dest_fd);
}

void copy_dir(const char *src_dir, const char *dst_dir)
{
    mkdir(dst_dir, 0777);
    changeAttr(src_dir, dst_dir);
}

void copy_sln(const char *src_file, const char *dst_file)
{
    char buf[1024];
    memset(buf, 0, sizeof(buf));
    int len = 0;
    if ((len = readlink(src_file, buf, sizeof(buf))) > 0)
    {
        printf("%s\n", buf);
        if (symlink(buf, dst_file) == -1)
        {
            perror("symlink");
        }
    }
    changeAttr(src_file, dst_file);
}

void changeAttr(const char *src, const char *dst)
{
    struct stat attr_of_src;
    lstat(src, &attr_of_src);
    //修改檔案屬性
    chmod(dst, attr_of_src.st_mode);
    //修改檔案用戶組
    chown(dst, attr_of_src.st_uid, attr_of_src.st_gid);

    //修改檔案訪問、修改時間
    struct timeval time_buf[2];
    time_buf[1].tv_sec = attr_of_src.st_mtime;
    time_buf[0].tv_sec = attr_of_src.st_atime;
    if(lutimes(dst, time_buf) == -1)
    {
        printf("%s\n", dst);
        perror("lutimes");
    }

    struct utimbuf tbuf;
    tbuf.actime = attr_of_src.st_atime;
    tbuf.modtime = attr_of_src.st_mtime;
    utime(dst, &tbuf);

    struct stat dst_attr_of_src;
    lstat(dst, &dst_attr_of_src);
    if (dst_attr_of_src.st_mtime != attr_of_src.st_mtime)
        printf("%s : %d\n", dst, attr_of_src.st_mtime);
}

Windows

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <Windows.h>
#include <cstring>
#define BUF_SIZE 1024
using namespace std;

//檔案夾復制采用dfs或者bfs進行搜索是等價的
void search_dfs(wchar_t* src_path, wchar_t* dest_path);
//復制檔案
void copy_file(const wchar_t* src_file, const wchar_t* dst_file);
//復制檔案夾
void copy_dir(const wchar_t* src_dir, const wchar_t* dst_dir);
//修改檔案屬性與源檔案保持一致
void change_attr(const wchar_t* src_name, const wchar_t* dst_name, HANDLE h_src, HANDLE h_dst);

int wmain(int argc, wchar_t* argv[])
{
	setlocale(LC_ALL, "");
	wchar_t* src_path = new wchar_t[BUF_SIZE];
	wchar_t* dst_path = new wchar_t[BUF_SIZE];
	ZeroMemory(src_path, BUF_SIZE);
	ZeroMemory(dst_path, BUF_SIZE);
	wcscpy(src_path, argv[1]);
	wcscat(src_path, L"\\*");
	wcscpy(dst_path, argv[2]);
	wcout << L"src_path" << src_path << endl;
	wcout << L"dst_path" << dst_path << endl;
	//wcscpy(src_path, L"E:\\薪火培訓\\*");
	//wcscpy(dst_path, L"E:\\2333");
	search_dfs(src_path, dst_path);
	delete[] src_path;
	delete[] dst_path;
	return 0;
}

//復制檔案
void copy_file(const wchar_t* src_file, const wchar_t* dst_file)
{
	HANDLE h_src = https://www.cnblogs.com/harrypotterjackson/p/::CreateFile(
			src_file, 
			GENERIC_READ | GENERIC_WRITE, 
			0, 
			NULL, 
			OPEN_EXISTING,
		    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 
			NULL);
	HANDLE h_dst = ::CreateFile(
			dst_file,
			GENERIC_WRITE | GENERIC_READ,
			0,
			NULL,
			CREATE_ALWAYS,
			FILE_ATTRIBUTE_NORMAL,
			NULL);
	if (h_src == INVALID_HANDLE_VALUE || h_dst == INVALID_HANDLE_VALUE)
	{
		printf("Open file error!/n");
		CloseHandle(h_src);
		CloseHandle(h_dst);
		exit(-1);
	}
	DWORD all_bytes = GetFileSize(h_src, NULL);
	char* buffer = new char[all_bytes + 1];
	ZeroMemory(buffer, all_bytes + 1);

	DWORD bytes = 0;
	ReadFile(h_src, buffer, all_bytes, &bytes, NULL);
	WriteFile(h_dst, buffer, all_bytes, &bytes, NULL);

	change_attr(src_file, dst_file, h_src, h_dst);

	CloseHandle(h_src);
	CloseHandle(h_dst);
	delete[] buffer;
	return;
}

//復制檔案夾
void copy_dir(const wchar_t* src_dirr, const wchar_t* dst_dir)
{
	wchar_t* src_dir = new wchar_t[BUF_SIZE];
	wcscpy(src_dir, src_dirr);
	src_dir[wcslen(src_dir) - 2] ='\0';
	_wmkdir(dst_dir);
	HANDLE h_src = https://www.cnblogs.com/harrypotterjackson/p/CreateFile(
		src_dir,
		GENERIC_READ | GENERIC_WRITE,
		FILE_SHARE_READ | FILE_SHARE_DELETE,
		NULL,
		OPEN_EXISTING,
		FILE_FLAG_BACKUP_SEMANTICS,
		NULL
	);
	if (h_src == INVALID_HANDLE_VALUE)
	{
		printf("Open src directory error!/n");
		CloseHandle(h_src);
		exit(-1);
	}
	HANDLE h_dst = CreateFile(
		dst_dir,
		GENERIC_READ | GENERIC_WRITE,
		FILE_SHARE_READ | FILE_SHARE_DELETE,
		NULL,
		OPEN_EXISTING,
		FILE_FLAG_BACKUP_SEMANTICS,
		NULL
	);
	
	if (h_dst == INVALID_HANDLE_VALUE)
	{
		printf("Open dst directory error!/n");
		CloseHandle(h_dst);
		exit(-1);
	}
	change_attr(src_dir, dst_dir, h_src, h_dst);
	CloseHandle(h_src);
	CloseHandle(h_dst);
	return;
}


void search_dfs(wchar_t* src_path, wchar_t* dst_path)
{
	HANDLE h_find;
	WIN32_FIND_DATA find_data;
	LARGE_INTEGER size;
	h_find = FindFirstFile(src_path, &find_data);
	if (h_find == INVALID_HANDLE_VALUE)
	{
		cout << "Fail to find first file" << endl;
		return;
	}
	copy_dir(src_path, dst_path);
	do
	{
		wcout << find_data.cFileName << endl;
		if (wcscmp(find_data.cFileName, L".") == 0 || wcscmp(find_data.cFileName, L"..") == 0)
		{
			continue;
		}
		if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)//是目錄
		{
			wchar_t n_src_path[BUF_SIZE];
			wcscpy(n_src_path, src_path);
			n_src_path[wcslen(n_src_path) - 1] ='\0';
			wcscat(n_src_path, find_data.cFileName);
			wcscat(n_src_path, L"\\*");

			wchar_t n_dst_path[BUF_SIZE];
			wcscpy(n_dst_path, dst_path);
			wcscat(n_dst_path, L"\\");
			wcscat(n_dst_path, find_data.cFileName);

			copy_dir(n_src_path, n_dst_path);
			search_dfs(n_src_path, n_dst_path);
		}
		else
		{
			//size.LowPart = find_data.nFileSizeLow;
			//size.HighPart = find_data.nFileSizeHigh;
			//wcout << find_data.cFileName << "\t" << size.QuadPart << " bytes" << endl;
			
			wchar_t n_src_path[BUF_SIZE];
			wcscpy(n_src_path, src_path);
			n_src_path[wcslen(n_src_path) - 1] = '\0';
			wcscat(n_src_path, find_data.cFileName);

			wchar_t n_dst_path[BUF_SIZE];
			wcscpy(n_dst_path, dst_path);
			wcscat(n_dst_path, L"\\");
			wcscat(n_dst_path, find_data.cFileName);

			copy_file(n_src_path, n_dst_path);
		}

	} while (FindNextFile(h_find, &find_data));
	return;
}

//修改檔案屬性與源檔案保持一致
void change_attr(const wchar_t* src_name, const wchar_t* dst_name, HANDLE h_src, HANDLE h_dst)
{
	DWORD attr = GetFileAttributes(src_name);
	SetFileAttributes(dst_name, attr);
	FILETIME t_create, t_access, t_write;
	SYSTEMTIME syst_create, syst_access, syst_write;
	GetFileTime(h_src, &t_create, &t_access, &t_write);

	FileTimeToSystemTime(&t_create, &syst_create);
	//cout << syst_create.wDay << endl;

	SetFileTime(h_dst, &t_create, &t_access, &t_write);

	GetFileTime(h_dst, &t_create, &t_access, &t_write);
	FileTimeToSystemTime(&t_create, &syst_create);
	//cout << syst_create.wDay << endl;
}

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/82053.html

標籤:C++

上一篇:Ubuntu18.04安裝openCV4.1.2

下一篇:畢業就在小公司躺了3年,面試大廠發現,發現不會分布式沒人要…

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more