C++:小說閱讀器

寒金發表於2020-08-23

C++:小說閱讀器

這是我自己用 C++ & 減小程式碼長度用的批處理 做的一個用來看小說的程式,使用批處理主要是不太會C++Web程式設計,請求大佬們指教
現在這裡還沒加入什麼小說,有什麼比較好看的請各位推薦

說明

這是用的我自己的伺服器,裡面的小說需要自己處理才可使用,並且程式會自動更新,更新日誌會在這裡釋出。

下載

更新日誌

2020.8.21前的更新日誌忘了

  • 2020.8.21
    新增了學生機功能
    版本&版本號:1.0.6-200821 8
  • 2020.9.12
    修改了更新的批處理,將主介面修改為管理員方式執行
    版本&版本號:1.0.7-200912 9

程式碼

1. 打包版本

簡化程式碼,只留下更新部分

/*
Made In Aichi @2019-2020
Aichi主站: http://aichistudio.space
Aichi百科: http://baike.aichistudio.space

版權歸 愛知工作室 所有
*/
//標頭檔案引入
#include<bits/stdc++.h>
#include<windows.h>
#include<string>
#include<conio.h>
#define _for(i,a,b) for(int i=a;i<b;i++)
//標準輸出控制程式碼
#define handle GetStdHandle(STD_OUTPUT_HANDLE)
//版本號,因為是縮減版,所以將版本號設為-1,這樣一定會啟動更新
#define EDITION_ID -1 
#define EDITION 0.0.0-20190000
using namespace std;
//隱藏與顯示游標函式
void cursor(bool a){
	CONSOLE_CURSOR_INFO CursorInfo;
	GetConsoleCursorInfo(handle, &CursorInfo);
	CursorInfo.bVisible = a;
	SetConsoleCursorInfo(handle, &CursorInfo);
}
//更新函式
void update(){
	system("cls");//清屏
	printf("檢查更新...");
	/*
	Windows有個程式叫bitsadmin,Windows的許多更新就是由它完成的,
	因為不太會C++Web程式設計所以使用這個來下載東西
	*/
	system("bitsadmin /transfer 檢查更新 http://aichistudio.space/novel/api/edition %cd%\\edition.txt");//下載最新版本資訊
	//讀取最新版本號
	ifstream update_input("edition.txt");
	int editionid;
	update_input>>editionid;
	if(editionid>EDITION_ID){//如果最新版本號大於目前版本,則進行更新
		system("start update");
		exit(0);
	}
}
//初始化函式
void init(){
	system("mode con cols=90 lines=30");//初始化視窗大小
	ofstream update_code("update.bat");//輸出更新程式
	//接下來就是批處理了,不做講解
	update_code<<"@echo off\n"\
				<<"cd /d %~dp0"\
				<<"%1 start \"\" mshta vbscript:createobject(\"shell.application\").shellexecute(\"\"\"%~0\"\"\",\"::\",,\"runas\",1)(window.close)&exit"\
				<<"bitsadmin /transfer 檢查更新 http://aichistudio.space/novel/api/update_list %cd%\\update_list.txt\n"\
				<<"for /f \"delims=\" %%i in (update_list.txt) do bitsadmin /transfer 更新檔案%%i http://aichistudio.space/static/file/novel/%%i %cd%\\%%i\n"\
				<<"start main.exe\n"\
				<<"exit";
}
//主函式
int main(){
	init();
	update();
	return 0;
}

2. 最新程式碼

  • main.exe

/*
Made In Aichi @2019-2020
Aichi主站: http://aichistudio.space
Aichi百科: http://baike.aichistudio.space

版權歸 愛知工作室 所有
*/
#include<bits/stdc++.h>
#include<windows.h>
#include<string>
#include<conio.h>
#define _for(i,a,b) for(int i=a;i<b;i++)
#define handle GetStdHandle(STD_OUTPUT_HANDLE)
#define EDITION_ID 9 
#define EDITION 1.0.7-200912
using namespace std;
void main_interface();
void cursor(bool a){
	CONSOLE_CURSOR_INFO CursorInfo;
	GetConsoleCursorInfo(handle, &CursorInfo);
	CursorInfo.bVisible = a;
	SetConsoleCursorInfo(handle, &CursorInfo);
}
void update(){
	system("cls&del edition.txt");
	system("title 檢查更新...");//設定標題
	printf("檢查更新...");
	system("bitsadmin /transfer 檢查更新 http://aichistudio.space/novel/api/edition %cd%\\edition.txt");
	ifstream update_input("edition.txt");
	int editionid;
	update_input>>editionid;
	if(editionid>EDITION_ID){
		system("start update");
		exit(0);
	}
}
//本地小說
void local_novels(){
	system("cls&title 本地小說");//設定標題
	system("dir %cd%\\novels\\* /B > list.txt");//用批處理獲得已有小說列表
	char novels[500][200]={};//定義小說名稱陣列
	int n=0;//小說數量
	//讀取
	ifstream local_novel_list("list.txt");
	while(local_novel_list.getline(novels[n++],200));
	if(strlen(novels[0])==0){//如果沒有讀取到小說
		printf("沒有小說");
		system("pause");
		return;
	}
	n--;//最後一個名稱為空,所以要減回來
	/*
	模擬while
	W:
	...
	goto W;
	可以理解為while(1)
	*/
	W:
	system("cls");//清屏
	//列印螢幕
	printf("輸入0來返回\n");
	_for(i,0,n){
		printf("%d. %s\n",i+1,novels[i]);
	}
	printf("id: ");
	//使用者輸入id
	int k=0;
	scanf("%d",&k);
	if(k==0)return;//id==0則返回主介面
	if(k>0&&k<=n){//如果id在列表內
		freopen("novel.txt","w",stdout);//對novel.exe更新正在看的小說
		printf(novels[k-1]);//選中的小說名稱
		system("start novel.exe");//啟動
		exit(0);
	}else{//否則
		printf("id錯誤!");
		Sleep(2000);//等待2s
		goto W;//返回到 W:
	}
}
//下載新的
void download_novels(){
	system("cls");
	system("title 獲取小說列表...");
	system("bitsadmin /transfer 獲取小說列表 http://aichistudio.space/novel/api/list %cd%\\weblist.txt");//批處理獲得已有的小說列表
	//讀取
	char novels[500][200]={};
	int n=0;
	ifstream local_novel_list("weblist.txt");
	while(local_novel_list.getline(novels[n++],200));
	n--;
	W:
	system("cls&title 下載新小說");
	//列印
	_for(i,0,n){
		printf("%d. %s\n",i+1,novels[i]);
	}
	printf("id: ");
	int k=0;
	scanf("%d",&k);
	if(k>0&&k<=n){//id在列表內
		//執行下載,利用string來生成批處理程式碼
		string download_code="download ";
		download_code.append(novels[k-1]);
		system(download_code.data());
		return;//返回主介面
	}else{//否則
		printf("id錯誤!");
		Sleep(2000);
		goto W; 
	}
}
//主介面
void main_interface(){
	R: //外層迴圈
	system("cls&title 主介面");
	//列印介面
	printf("1.本地小說    2.下載新的");
	W: //不會重新列印介面
	char k=getch();//鍵盤讀取
	if(k=='1')local_novels();//按下 1 
	else if(k=='2')download_novels();//按下 2
	else goto W;//都不是這返回,不重新列印介面
	goto R;//執行完則重新列印
}
//初始化
void init(){
	system("mode con cols=90 lines=30");
	cursor(0);
	system("md novels");
	ofstream update_code("update.bat");
	update_code<<"@echo off\n"\
				<<"cd /d %~dp0"\
				<<"%1 start \"\" mshta vbscript:createobject(\"shell.application\").shellexecute(\"\"\"%~0\"\"\",\"::\",,\"runas\",1)(window.close)&exit"\
				<<"bitsadmin /transfer 檢查更新 http://aichistudio.space/novel/api/update_list %cd%\\update_list.txt\n"\
				<<"for /f \"delims=\" %%i in (update_list.txt) do bitsadmin /transfer 更新檔案%%i http://aichistudio.space/static/file/novel/%%i %cd%\\%%i\n"\
				<<"start main.exe\n"\
				<<"exit";
	//下載小說的批處理
	ofstream download_code("download.bat");
	download_code<<"bitsadmin /transfer 下載《%1》 http://aichistudio.space/static/file/novel/%1.txt %cd%\\novels\\%1";
}
VOID ManagerRun(LPCSTR exe,LPCSTR param,INT nShow=SW_SHOW){//以管理員狀態執行 
 	SHELLEXECUTEINFO ShExecInfo; 
 	ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);  
 	ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS ;  
 	ShExecInfo.hwnd = NULL;  
 	ShExecInfo.lpVerb = "runas";  
 	ShExecInfo.lpFile = exe; 
 	ShExecInfo.lpParameters = param;   
 	ShExecInfo.lpDirectory = NULL;  
 	ShExecInfo.nShow = nShow;  
 	ShExecInfo.hInstApp = NULL;   
 	BOOL ret = ShellExecuteEx(&ShExecInfo);  
 	CloseHandle(ShExecInfo.hProcess);
 	return;
}
int main(int argc,char *argv[]){
    if(argc==1){
    	ShowWindow(GetConsoleWindow(),SW_HIDE);
       	ManagerRun(argv[0],"2");
       	return 1;
    }else if(argc==2){
		init();
		update();
		main_interface();
	}
	return 0;
}
  • novel.exe

/*
Made In Aichi @2019-2020
Aichi主站: http://aichistudio.space
Aichi百科: http://baike.aichistudio.space

版權歸 愛知工作室 所有
*/
#include<bits/stdc++.h>
#include<windows.h>
#include<conio.h>
#define _for(i,a,b) for(int i=a;i<b;i++)
#define handle GetStdHandle(STD_OUTPUT_HANDLE)
using namespace std;
char name[500];
int id,line,n;
bool SCM;//學生機模式bool值
string novels[100000];//小說內容
ifstream novel;//讀取檔案的變數
HWND hWnd=GetForegroundWindow();//視窗控制程式碼
void gotoxy(double x,int y){//游標定位函式
	COORD pos;
	pos.X=2*x;
	pos.Y=y;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
}
void cursor(bool a){
	CONSOLE_CURSOR_INFO CursorInfo;
	GetConsoleCursorInfo(handle, &CursorInfo);
	CursorInfo.bVisible = a;
	SetConsoleCursorInfo(handle, &CursorInfo);
}
void init(){//初始化
	system("mode con cols=90 lines=9999");
	cursor(0);
}
void input(){//讀取資料
	{//讀取閱讀的小說名稱
		ifstream tttt("novel.txt");
		tttt>>name;
	}
	{//讀取已看到的章節
		ifstream temp(name);
		temp>>id;
	}
	//開啟小說
	string code="novels/";
	code.append(name);
	novel.open(code.data());
	_for(i,0,id+1){//讀取到正在閱讀的章節
		getline(novel,novels[i],'|');//章與章之間以“|”分割
	}
	n=id;//最大讀取到的章節數
	string title_code="title ";//用string生成標題指令
	title_code.append(name);
	title_code.append("(按下 Q 啟動學生機模式)");
	system(title_code.data());
}
void keep(){//儲存閱讀進度
	ofstream keeping(name);
	keeping<<id;
}
void read(){//閱讀
	W: //外層迴圈
	system("cls");
	//列印當前小說章節
	cout<<novels[id];
	gotoxy(0,0);//定位游標到第一行
	line=0;//閱讀到的函式
	while(1){//迴圈讀取鍵盤事件
		cursor(0);//隱藏游標
		if(_kbhit()){//有鍵盤被按下
			char k=_getch();//獲取鍵值
			if(k==72||k=='w'||k=='W'){//按下 ↑ 或 W
				if(line>=5){//如果閱讀的行>=5則往上5行
					line-=5;
					gotoxy(0,line);
				}
			}
			if(k==80||k=='s'||k=='S'){//按下 ↓ 或 S
				line+=5;//往下5行
				gotoxy(0,line);
			}
			if(k==75||k=='a'||k=='A'){//按下 ← 或 A
				if(id>0){//不是第一章
					id--;//往前一張
					keep();//儲存進度
					goto W;//返回,並重新列印
				}
			}
			if(k==77||k=='d'||k=='D'){//按下 → 或 D
				id++;//章節到下一張
				if(id>n){//如果超出已讀取的範圍,則讀取新的一章
					n=id;
					getline(novel,novels[id],'|');
				}
				keep();//儲存進度
				goto W;
			}
			if(k=='q'||k=='Q'){//如果按下 Q
				if(!SCM){//沒有啟動學生機模式
					string title_code="title ";
					title_code.append(name);
					title_code.append("_學生機模式(按下Q來關閉)");
					system(title_code.data());//設定新標題
				}else{//否則
					string title_code="title ";
					title_code.append(name);
					title_code.append("(按下 Q 啟動學生機模式)");
					system(title_code.data());
					//取消置頂
					SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); 
				}
				SCM=!SCM;
			}
		}
		if(SCM)//如果啟動了學生機模式,則迴圈置頂
			SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
		if(!SCM)Sleep(10);//沒有啟動學生機模式才有等待,啟動學生機模式就不等待
	}
}
int main(){
	init();
	input();
	read();
	return 0;
}

製作:

From AichiStudio愛知工作室,
網站:http://aichistudio.space
QQ交流群:1032103456

相關文章