4.编写compile_run模块|认识jsoncpp|基础框架|编译(C++)

compile_run

适配用户请求, 定制通信协议字段
正确的调用compile and run
形成唯一文件名

文件关系
![[Pasted image 20250221170844.png]]

认识jsoncpp功能

安装jsoncpp

sudo yum install jsoncpp-devel

找到json.h

find /usr/ -name json.h

![[Pasted image 20250221171842.png]]

测试

#include <iostream>

#include <json/json.h>
  
int main()
{
  
    //序列化的工作
    //将结构化数据转化成为一个字符串
    //Value是一个Json的中间类,可以填充KV值
    Json::Value root;
    root["code"] = "mycode";
    root["user"] = "zzz";
    root["age"] = "24";
  
    Json::StyledWriter writer;
    std::string str = writer.write(root);
    std::cout << str << std::endl;
}

编译

g++ test.cc -std=c++11 -ljsoncpp

运行

./a.out

![[Pasted image 20250221171950.png]]

#include <iostream>
#include <json/json.h>
  
int main()
{
  
    //序列化的工作
    //将结构化数据转化成为一个字符串
    //Value是一个Json的中间类,可以填充KV值
    Json::Value root;
    root["code"] = "mycode";
    root["user"] = "zzz";
    root["age"] = "24";
  
    //Json::StyledWriter writer;
    Json::FastWriter writer;
    std::string str = writer.write(root);
    std::cout << str << std::endl;
}

![[Pasted image 20250221172418.png]]

基础框架

compile_run.hpp

#pragma once
  
#include "compiler.hpp"
#include "runner.hpp"
#include "../comm/log.hpp"
#include "../comm/util.hpp"
#include <json/json.h>
  
namespace ns_compile_and_run
{
    using namespace ns_log;
    using namespace ns_util;
    using namespace ns_compiler;
    using namespace ns_runner;
  
    class CompileAndRun
    {
    public:
        /******************************
         输入:
         code:用户提交的代码
         input:用户给自己提交的代码对应的输入,不做处理
         cpu_limit:时间要求
         mem_limit:空间要求
  
         输出:
         必填
         status:状态码
         reason:请求结果
         选填
         stdout:程序运行完的结果
         stderr:程序运行完的错误结果
  
         参数:
         in_json: {"code": "#include...", "input": "","cpu_limit":1, "mem_limit":10240}
         out_json: {"status":"0", "reason":"","stdout":"","stderr":"",}
        *****************************/
        static void Start(const std::string &in_json, std::string *out_json)
        {
            Json::Value in_value;
            Json::Reader reader;
            reader.parse(in_json, in_value);
            std::string code = in_value["code"].asString();
            std::string input = in_value["input"].asString();
            int cpu_limit = in_value["cpu_limit"].asInt();
            int mem_limit = in_value["men_limit"].asInt();
  
            if(code.size() == 0){
                //处理差错问题
  
            }
  
            //形成的文件名只具有唯一性,没有目录,没有后缀
            std::string file_name = FileUtil::UniqFileName();
  
            FileUtil::WriteFile(PathUtil::src(file_name), code); //形成临时src文件
  
            Compiler::Compile(file_name);
  
            Runner::Run(file_name, cpu_limit, mem_limit);
        }
    };
}

util.hpp

class FileUtil {
	public:
	static bool IsFileExists(const std::string &path_name)
	{
		struct stat st;
		if(stat(path_name.c_str(), &st) == 0){
			//获取属性成功,文件已经存在
			return true;
		}
		return false;
	}
	static std::string UniqFileName()
	{

		return "";
	}
	static bool WriteFile(const std::string &target, const std::string &code)
	{
	}
};
出错处理
v1

compile_run.hpp

#pragma once
  
#include "compiler.hpp"
#include "runner.hpp"
#include "../comm/log.hpp"
#include "../comm/util.hpp"
#include <json/json.h>
  
namespace ns_compile_and_run
{
    using namespace ns_log;
    using namespace ns_util;
    using namespace ns_compiler;
    using namespace ns_runner;
  
    class CompileAndRun
    {
    public:
        static std::string SignoToDesc(int signo)
        {
  
        }
        /******************************
         输入:
         code:用户提交的代码
         input:用户给自己提交的代码对应的输入,不做处理
         cpu_limit:时间要求
         mem_limit:空间要求
  
         输出:
         必填
         status:状态码
         reason:请求结果
         选填
         stdout:程序运行完的结果
         stderr:程序运行完的错误结果

         参数:
         in_json: {"code": "#include...", "input": "","cpu_limit":1, "mem_limit":10240}
         out_json: {"status":"0", "reason":"","stdout":"","stderr":"",}
        *****************************/
        static void Start(const std::string &in_json, std::string *out_json)
        {
            Json::Value in_value;
            Json::Reader reader;
            reader.parse(in_json, in_value);
            std::string code = in_value["code"].asString();
            std::string input = in_value["input"].asString();
            int cpu_limit = in_value["cpu_limit"].asInt();
            int mem_limit = in_value["men_limit"].asInt();
  
            int status_code = 0;
            Json::Value out_value;
  
            if(code.size() == 0){
                //处理差错问题
                out_value["status"] = -1;//代码为空
                out_value["reason"] = "用户提交的代码时空的";
                //序列化过程
                return;
            }
  
            //形成的文件名只具有唯一性,没有目录,没有后缀
            //毫秒级时间戳+原子性递增唯一值:来保证唯一性
            std::string file_name = FileUtil::UniqFileName();
            //形成临时src文件
            if(!FileUtil::WriteFile(PathUtil::src(file_name), code))
            {
                out_value["status"] = -2;//未知错误
                out_value["reason"] = "代码发生了未知错误";
                //序列化过程
                return;
            }
  
            if(!Compiler::Compile(file_name))
            {
                //编译失败
                out_value["status"] = -3; //代码编译的时候发生了错误
                out_value["reason"] = FileUtil::ReadFile(PathUtil::CompilerError(file_name));
                //序列化过程
                return;
            }
  
            int code = Runner::Run(file_name, cpu_limit, mem_limit);
            if (code < 0)
            {
                out_value["status"] = -2;//未知错误
                out_value["reason"] = "代码发生了未知错误";
                //序列化过程
                return;  
            }
            else if(code > 0)
            {
                out_value["status"] = code;//运行报错了
                out_value["reason"] = SignoToDesc(code); //将信号报错转化为报错的原因
                //序列化过程
  
            }
            else
            {
                //运行成功
  
            }
        }
    };
}

util.hpp

    class FileUtil {
        public:
        static bool IsFileExists(const std::string &path_name)
        {
            struct stat st;
            if(stat(path_name.c_str(), &st) == 0){
                //获取属性成功,文件已经存在
                return true;
            }
            return false;
        }
        static std::string UniqFileName()
        {
  
            return "";
        }
        static bool WriteFile(const std::string &target, const std::string &code)
        {
  
        }
        static std::string ReadFile(const std::string &target, )
        {
  
        }
    };
v2

compile_run.hpp

#pragma once

#include "compiler.hpp"
#include "runner.hpp"
#include "../comm/log.hpp"
#include "../comm/util.hpp"
  
#include <signal.h>
#include <json/json.h>
  
namespace ns_compile_and_run
{
    using namespace ns_log;
    using namespace ns_util;
    using namespace ns_compiler;
    using namespace ns_runner;
  
    class CompileAndRun
    {
    public:
        // code > 0 : 进程收到了信号导致异常奔溃
        // code < 0 : 整个过程非运行报错(代码为空,编译报错等)
        // code = 0 : 整个过程全部完成
        static std::string CodeToDesc(int code, const std::string &file_name)
        {
            std::string desc;
            switch (code)
            {
            case 0:
                desc = "编译运行成功";
                break;
            case -1:
                desc = "提交的代码是空";
                break;
            case -2:
                desc = "未知错误";
                break;
            case -3:
                // desc = "代码编译的时候发生了错误";
                FileUtil::ReadFile(PathUtil::CompilerError(file_name), &desc, true);
                break;
            case SIGABRT: // 6
                desc = "内存超过范围";
                break;
            case SIGXCPU: // 24
                desc = "CPU使用超时";
                break;
            case SIGFPE: // 8
                desc = "浮点数溢出";
                break;
            default:
                desc = "未知: " + std::to_string(code);
                break;
            }
  
            return desc;
        }
        /******************************
         输入:
         code:用户提交的代码
         input:用户给自己提交的代码对应的输入,不做处理
         cpu_limit:时间要求
         mem_limit:空间要求
  
         输出:
         必填
         status:状态码
         reason:请求结果
         选填
         stdout:程序运行完的结果
         stderr:程序运行完的错误结果
  
         参数:
         in_json: {"code": "#include...", "input": "","cpu_limit":1, "mem_limit":10240}
         out_json: {"status":"0", "reason":"","stdout":"","stderr":"",}
        *****************************/
        static void Start(const std::string &in_json, std::string *out_json)
        {
            Json::Value in_value;
            Json::Reader reader;
            reader.parse(in_json, in_value);
            std::string code = in_value["code"].asString();
            std::string input = in_value["input"].asString();
            int cpu_limit = in_value["cpu_limit"].asInt();
            int mem_limit = in_value["men_limit"].asInt();
  
            int status_code = 0;
            Json::Value out_value;
            int run_result = 0;
            std::string file_name;//需要内部形成的唯一文件名
  
            if(code.size() == 0){
                status_code = -1;//代码为空
                goto END;
            }
  
            //形成的文件名只具有唯一性,没有目录,没有后缀
            //毫秒级时间戳+原子性递增唯一值:来保证唯一性
            file_name = FileUtil::UniqFileName();
            //形成临时src文件
            if(!FileUtil::WriteFile(PathUtil::Src(file_name), code))
            {
                status_code = -2;//未知错误
                goto END;
            }
  
            if(!Compiler::Compile(file_name))
            {
                status_code = -3;//编译失败
                goto END;
            }
  
            run_result = Runner::Run(file_name, cpu_limit, mem_limit);
            if (run_result < 0)
            {
                status_code = -2;//未知错误
            }
            else if(run_result > 0)
            {
                //程序运行崩溃
                status_code = run_result;
            }
            else
            {
                //运行成功
                status_code = 0;
            }
            END:
            out_value["status"] = status_code;
            out_value["reason"] = CodeToDesc(status_code, file_name);
            if(status_code == 0){
                //整个过程全部成功
                std::string _stdout;
                FileUtil::ReadFile(PathUtil::Stdout(file_name), &_stdout, true);
                out_value["stdout"] = _stdout;
  
                std::string _stderr;
                FileUtil::ReadFile(PathUtil::Stderr(file_name), &_stderr, true);
                out_value["stderr"] = _stderr;
            }
  
            Json::StyledWriter writer;
            *out_json = writer.write(out_value);
        }
    };
}

util.hpp

#pragma once
  
#include <iostream>
#include <string>
#include <atomic>
#include <fstream>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/unistd.h>
#include <sys/time.h>

namespace ns_util
{
    class TimeUtil
    {
    public:
        static std::string GetTimeStamp()
        {
            struct timeval _time;
            gettimeofday(&_time, nullptr);
            return std::to_string(_time.tv_sec);
        }
        //获得毫秒时间戳
        static std::string GetTimeMs()
        {
            struct timeval _time;
            gettimeofday(&_time, nullptr);
            return std::to_string(_time.tv_sec * 1000 + _time.tv_usec / 1000);
        }
    };
    class FileUtil {
        public:
        static bool IsFileExists(const std::string &path_name)
        {
            struct stat st;
            if(stat(path_name.c_str(), &st) == 0){
                //获取属性成功,文件已经存在
                return true;
            }
            return false;
        }
        static std::string UniqFileName()
        {
            static std::atomic_uint id(0);
            id++;
            // 毫秒级时间戳+原子性递增唯一值: 来保证唯一性
            std::string ms = TimeUtil::GetTimeMs();
            std::string uniq_id = std::to_string(id);
            return ms + "_" + uniq_id;
        }
        static bool WriteFile(const std::string &target, const std::string &content)
        {
            std::ofstream out(target);
            if (!out.is_open())
            {
                return false;
            }
            out.write(content.c_str(), content.size());
            out.close();
            return true;
        }
        static bool ReadFile(const std::string &target, std::string *content, bool keep = false)
        {
            (*content).clear();
  
            std::ifstream in(target);
            if (!in.is_open())
            {
                return false;
            }
            std::string line;
            // getline:不保存行分割符,有些时候需要保留\n,
            // getline内部重载了强制类型转化
            while (std::getline(in, line))
            {
                (*content) += line;
                (*content) += (keep ? "\n" : "");
            }
            in.close();
            return true;
        }
    };
}

编译通过
![[Pasted image 20250222102227.png]]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值