基本想法

为什么要写 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. springboot FilterRegistrationBean 拦截器的使用

    1.创建一个filter package com.ruoyi.weixin.user.interator; import com.ruoyi.common.utils.SecurityUtils; i ...

  2. 本地python环境安装kylin项目依赖时报认证错误信息

    问题描述:项目需要连接kylin数据库查询数据,本地安装kylin项目的依赖环境后报认证错误 python版本3.7 32位 pycharm版本 2022版 成功方法: 更换解释器选择无解释器,创建虚 ...

  3. Python装饰器实例讲解(三)

    Python装饰器实例讲解(三) 本文多参考<流畅的python>,在此基础上增加了一些实例便于理解 姊妹篇 Python装饰器实例讲解(一),让你简单的会用 Python装饰器实例讲解( ...

  4. voxel体素网络滤波器

    1.简介 在进行建图的时候,由于多个视角内存在视野重叠,即多个摄像头看到同样的像素点,这样在重叠区域内会存在大量的位置十分相近的点,这会占用很多内存空间.体素网络滤波保证了在某个一定大小的立方体内只有 ...

  5. 使用NAT网络模式搭建内网,修改IP地址

    使用NAT网络模式搭建内网,修改IP地址 首先说明一下虚拟机的三种联网方式: 桥接模式: 简单来说就是使这台虚拟机成为一台在互联网中的有独立IP的一台新设备和Mac地址(不够都是虚拟的) NAT模式: ...

  6. 【KAWAKO】将conda虚拟环境设置进jupyter-notebook

    目录 进入虚拟环境 安装ipykernel 将虚拟环境加入notebook的kernel 打开jupyter-notebook并使用 进入虚拟环境 conda activate audio 安装ipy ...

  7. 欧拉函数和遗忘自动机 SX 的故逝

    欧拉函数 \(\varphi(n)\) 定义为小于 \(n\) 与 \(n\) 互质的数字,炒个例子,\(\varphi(10) = 4\),因为 \(1,3,7,9\) 与 \(10\) 互质. 怎 ...

  8. dotnet总结——类型系统

    包括2种大的类型: 引用类型和值类型, 放一张图说明继承层次: 一 值类型: 内置的值类型,如下 用户自定义值类型就是用户定义的枚举或者结构类型. 可空类型(Nullable<T>)属于 ...

  9. Linux:touch 修改文件的时间

    修改本文件的时间 参数 描述 例子 -a 只修改访问时间(Access Time) touch -a hello.txt -m 只更新修改时间(Modify Time) touch -m hello. ...

  10. Vue props配置项(属性)

    功能:让组件接收外部传过来的数据 1.传递数据: <Demo name="XXX"/> 2.接收数据: (1)第一种方式(只接收): props:['name'] (2 ...