基本想法

为什么要写 CPPRUN:

  1. 如果要开警告开关,敲完整的编译代码还挺麻烦的
  2. 想要编译与运行一次性完成
  3. Windows 的控制台本来是 cmd,后来有了 Powershell,但是后者不能用 < 指定输入文件,比较麻烦

所以可以直接用 C++ 写一个类似于脚本的命令行程序。

功能

  1. 编译单个源代码。
  2. 默认情况下若编译成功,则运行程序,可以指定输入输出文件。
  3. 毫秒级计算实际运行时间。

基本用法:

.\run <源程序文件名,不包括.cpp扩展> <其他指令>

指令列表:

  • \i <文件名> 指定输入文件
  • \o <文件名> 指定输出文件
  • \f <文件名,不带扩展名> 指定exe文件名,默认与源文件相同
  • \std <c++/c++11/c++14> 设置C++版本,默认 C++14
  • \u 取消警告,默认开启 -Wall -Wextra -Wconversion -Wshadow
  • \cmd 回显编译命令,默认不开启
  • \comp 只编译不运行,默认编译后立即运行

代码实现

命令行程序添加参数

以 CPPRUN 为例,.\run <...> 中的 <...> 就是参数。在 C++ 中 main 函数其实是有两个参数的(只是竞赛的时候从来不会用到,也可以不写),即

// 参数随便命名,这里举个例子
int main(int argc, char** argv) {
}

其中 argc 是 ”参数数量“ + 1,注意命令行中不同参数用若干空格隔开;argv[1 ~ argc - 1] 是字符串形式的参数。

在程序中形成编译命令并执行

C风格字符串的拼接还挺麻烦,可以直接用 iostream 中的 string,通过 +, += 可以完成字符串与字符、字符串与字符串的拼接。

执行需要用到 system 函数,但是 system 的参数是C风格字符串,string 类型需要用到内置的 c_str() 转化。另外一提,在 system 中是可以使用 <, > 指定输入输出文件的,因为其本质是在 cmd 中执行了指令。相当于免去了在 Powershell 中打开 cmd 执行指令再关闭 cmd 的这种繁琐的操作。

system 函数是有返回值的,就是执行的该条指令的返回值。这样可以获取程序的返回值判断程序是否正常结束,也可以通过 g++ 的返回值判断是否有编译错误。

Tab. g++ 返回 0 是编译成功(包括有编译警告),其余返回值是有编译错误。

其他的小细节

如果想要在命令行中输出中文,一定保证你的源文件是在 GBK(或者其他中文) 的编码下编写并保存的!

源代码

/* Lucky_Glass */
// 2022-6-21 modified
#include <windows.h>
#include <ctime>
#include <cstdio>
#include <cstring>
#include <iostream> int getOption(char *_str) {
std::string str(_str);
if (str == "\\i") return 1;
if (str == "\\o") return 2;
if (str == "\\f") return 3;
if (str == "\\std") return 4;
if (str == "\\u") return 5;
if (str == "\\cmd") return 6;
if (str == "\\comp") return 7;
return 0;
}
void somethingError() {
std::cerr << "<fail> CPPRUN发生了未知错误" << std::endl;
exit(1);
} bool isopt[50];
int main(int num, char *opt[]) {
std::string cmd("g++ ");
if (num == 1) {
std::cerr << "<fail> 请指定编译文件" << std::endl;
return 0;
}
std::string fil(opt[1]), inp, oup, gver("c++14");
cmd += fil, cmd += ".cpp";
for (int i = 2; i < num; ++i) {
int optid = getOption(opt[i]);
isopt[optid] = true;
if (optid <= 4) {
std::string ext(opt[++i]);
switch (optid) {
case 1: inp = ext; break;
case 2: oup = ext; break;
case 3: fil = ext; break;
case 4: gver = ext; break;
default: somethingError();
}
}
} cmd += " -o ", cmd += fil;
if (gver == "c++14") cmd += " -std=c++14";
else if (gver == "c++11") cmd += " -std=c++11";
else if (gver != "c++") {
std::cerr << "<fail> C++版本只能为 c++/c++11/c++14" << std::endl;
return 0;
} if (!isopt[5])
cmd += " -Wall -Wextra -Wconversion -Wshadow"; if (isopt[6])
std::cerr << cmd << std::endl; if(!system(cmd.c_str()))
std::cerr << "<success> 编译完成" << std::endl;
else {
std::cerr << "<fail> 编译失败" << std::endl;
return 0;
} if (!isopt[7]) {
cmd = ".\\", cmd += fil, cmd += ".exe";
if (isopt[1]) cmd += " < ", cmd += inp;
if (isopt[2]) cmd += " > ", cmd += oup;
DWORD stt, edt;
stt = GetTickCount();
int ret = system(cmd.c_str());
edt = GetTickCount();
std::cerr.precision(3);
std::cerr << "<success> 运行结束,返回值 " << ret
<< ",运行时间 " << (edt - stt) / 1000.0
<< std::endl;
}
return 0;
}

THE END

手写g++编译命令行工具笔记的更多相关文章

  1. 通过npm写一个cli命令行工具

    前言 如果你想写一个npm插件,如果你想通过命令行来简化自己的操作,如果你也是个懒惰的人,那么这篇文章值得一看. po主的上一篇文章介绍了定制自己的模版,但这样po主还是不满足啊,项目中我们频繁的需要 ...

  2. 如何用Node编写命令行工具

    0. 命令行工具 当全局安装模块之后,我们可以在控制台下执行指定的命令来运行操作,如果npm一样.我把这样的模块称之为命令行工具模块(如理解有偏颇,欢迎指正) 1.用Node编写命令行工具 在Node ...

  3. 吻逗死(windows)系统下自动部署脚本(for java spring*)及linux命令行工具

    转载请注明出处:https://www.cnblogs.com/funnyzpc/p/10051647.html (^^)(^^)自動部署腳本原本在上個公司就在使用,由於近期同事需要手動部署一個Spr ...

  4. 如何创建一个基于命令行工具的跨平台的 NuGet 工具包

    命令行可是跨进程通信的一种非常方便的手段呢,只需启动一个进程传入一些参数即可完成一些很复杂的任务.NuGet 为我们提供了一种自动导入 .props 和 .targets 的方法,同时还是一个 .NE ...

  5. Windows 编程,程序编译使用的命令行工具。

    Windows 编程,程序编译使用的命令行工具. 1.cl.exe文件是Visual C\C++的编译器,它将程序源代码文件编译为obj文件. 2.rc.exe文件是资源编译器.工程项目中的.rc文件 ...

  6. 用 nodejs 写一个命令行工具 :创建 react 组件的命令行工具

    用 nodejs 写一个命令行工具 :创建 react 组件的命令行工具 前言 上周,同事抱怨说 react 怎么不能像 angular 那样,使用命令行工具来生成一个组件.对呀,平时工作时,想要创建 ...

  7. python笔记42-http请求命令行工具(httpie)

    前言 通常我们需要快速的测试某个接口通不通,一般linux上用curl去发http请求,但是这个命令行工具语法有点复杂了,不够直观. python有一个给人类使用的requests库,非常的简单方便. ...

  8. Gitbook 命令行工具

    1.Gitbook 简介 1.1 Gitbook GitBook 是一个基于 Node.js 开发的命令行工具,使用它可以很方便的管理电子书,GitBook 是目前最流行的开源书籍写作方案. 使用 G ...

  9. react.js 之 create-react-app 命令行工具系统讲解

    react.js 教程之 create-react-app 命令行工具系统讲解 快速开始 npm install -g create-react-app create-react-app my-app ...

  10. FFmpeg命令行工具和批处理脚本进行简单的音视频文件编辑

    FFmpeg_Tutorial FFmpeg工具和sdk库的使用demo 一.使用FFmpeg命令行工具和批处理脚本进行简单的音视频文件编辑 1.基本介绍 对于每一个从事音视频技术开发的工程师,想必没 ...

随机推荐

  1. 提供给用户使用的表格样式自定义工具,适用于elementUI表格

    介绍 给用户提供了可以自定义修改elementUI表格的能力,通过混入(mixins)使用,必须先安装element-ui. 通过npm安装: npm i el-table-customizer 使用 ...

  2. Python装饰器实例讲解(一)

    Python装饰器实例讲解(一) 多种角度讲述这个知识,这是个系列文章 但前后未必有一定的顺承关系 部分参考网络 本文以一个小案例引出装饰器的一些特点,不涉及理论,后面再谈 案例 写一个代码来求一个数 ...

  3. saas架构之druid解析表名

    public void preHandle(BoundSql boundSql, RequestEntity requestEntity) { System.out.println("要执行 ...

  4. 基于 Ubuntu 服务器配置原生的 Socks5 网关代理服务器

    常见的代理协议有 http.https.socks4/5 这三种,http协议的代理搭建方案最简单,但是http代理无法访问https网站,https代理无法实现调用远端dns,所以我个人推荐使用Sc ...

  5. IIS服务器SSL证书安装 (pfx文件不能直接运行时)

    在证书控制台下载IIS版本证书,下载到本地的是一个压缩文件,解压后里面包含.pfx文件是证书文件,pfx_password.txt是证书文件的密码. 友情提示: 每次下载都会产生新密码,该密码仅匹配本 ...

  6. 多重背包问题 II

    有 NN 种物品和一个容量是 VV 的背包. 第 ii 种物品最多有 sisi 件,每件体积是 vivi,价值是 wiwi. 求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大.输 ...

  7. ORACLE数据库起不来

    由于意外导致数据库无法启动 首先切换到oracle用户,查看profile文件. su - oracle cat .bash_profile 然后进入数据库,查看挂载上 sqlplus "/ ...

  8. JAVA 进阶 69-79

    10/20 1. 创建 媒体类型 了解父类与子类 import java.util.ArrayList; //导入包 public class sfgda { //定义容器 容器类型是DGSD这个类型 ...

  9. jmeter常见错误(持续更新)

    1. jmeter java.net.NoRouteToHostException: Cannot assign requested address (Address not available) 压 ...

  10. 【NOI2014】随机数生成器

    代码 #include<cstdio> using namespace std; typedef long long LL; const int N = 5000; int n , m , ...