基本想法

为什么要写 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. Task记录3 :ContinueWith ,CancellationToken,的结合

    static void Main(string[] args) { //1.创建取消令牌数据 CancellationTokenSource tokenSource = new Cancellatio ...

  2. http八股 跨域的本质 请求行 请求头 请求体 xss

    1小八股 介绍 http 请求分为三个部分,请求行,请求头,请求体 还有状态码的含义 https://juejin.cn/post/7096317903200321544 2tips Content- ...

  3. springboot框架返回日期值少一天

    1 问题 一个请求,返回一个对象,对象里面有日期,返回的对象的日期却比实际的日期少了一天 如下图:在return返回的时候查看返回的对象的日期的值 postman返回的结果如下图,几个日期都少了一天 ...

  4. 函数式编程:Flutter&Dart中的组合

    本文翻译自: Composition in Flutter & Dart 在 Flutter & Dart 中使用组合创建模块化应用程序. 什么是组合? 在dictionary.com ...

  5. python导入和导出excel,以文件流形式返回前端

    一.导入excel 1. 安装依赖包 pip install xlrd 2. 读取excel getColIndex(colList:list,colName:str): try: return co ...

  6. 【Raspberry Pi / 树莓派】小小工控机担起大大责任

    CM4 Nano是一款基于Raspberry Pi / 树莓派 Compute Module 4(简称CM4),由EDATEC面向工业应用设计的嵌入式计算机, 充分利用CM4在结构上灵活性解决CPU, ...

  7. python 合并目标文件夹中多个txt文件到指定文件中

    # coding = 'utf-8' # description: 合并目标文件夹中多个txt文件,到指定文件中. import os def file_merge_to_one(dirpath): ...

  8. Mybatis连接数据库

    从零开始Mybatis连接数据库 创建Maven文件 File-->new-->project-->maven,点击next 配置 在出现的pom.xml文件中<project ...

  9. GPS地图生成02之经典算法体验

    经典的利用轨迹生成地图的算法与数据集可寻找于:Mapconstruction by pfoser Mapconstruction by pfoser数据集中,雅典数据集投影坐标系为(UTM, GGRS ...

  10. 在Github的fork项目中切换分支来提交PR

    在Github的fork项目中切换分支来提交PR 查看远程所有分支 git branch不带参数,列出本地已经存在的分支,并且在当前分支的前面用*标记,加上-a参数可以查看所有分支列表,包括本地和远程 ...