由成幻OnlineJudge学习如何做自己的Acm-Icpc在线评判系统-5.在线编译与测试系统代码粗解

简介: 由于近来很忙,加之此类文章少有人问津.所以少有时间写这一系列的文章的续篇 所以先把核心在线编译的代码发出来,细的部分大家可以查资料,或者留言问我^^ 部分类库可以查我以前的文章using System;using System.
由于近来很忙,加之此类文章少有人问津.所以少有时间写这一系列的文章的续篇
所以先把核心在线编译的代码发出来,细的部分大家可以查资料,或者留言问我^^
部分类库可以查我以前的文章
using  System;
using  System.Text;
using  System.Data;
using  System.Diagnostics;
using  System.Threading;
using  System.IO;

namespace  ChswordOJ {
    
///   <summary>
    
///  DoFile 进行在线编译与测试
    
///  Builder:邹健 2007 4 28
    
///  V1.0 2007 6 12
    
///   </summary>
     public   class  DoFile {
        StringBuilder _output 
=   new  StringBuilder();
        StringBuilder _TestOutput 
=   new  StringBuilder();
        StringBuilder _TestFile_Output 
=   new  StringBuilder();
        String _Test;
        String _CompilerName;
        StringBuilder _CompilerText 
=   new  StringBuilder();
        
private  Int64 _Memory, _myMemory;
        
private  Int32 _Time; // , _myTime;
         private  Option.AnswerStatus _TestResult;
        
private  String _ExePath;
        
private  String _CodePath;
        
private  String _TextPath;
        
private  String _TestPath;
        
private  Int64 _AnswerId;
        
private  String _Sign;
        
private  Boolean _TestEnd;
        Process _process;
        
///   <summary>
        
///  构造函数,对DoFile类进行初始化
        
///   </summary>
         public  DoFile() {
            _Memory 
=   23768 ;
            _Time 
=   3 ;
        }
        
///   <summary>
        
///  进行编译及测试代码。
        
///   </summary>
        
///   <param name="code"> 要编译的代码。 </param>
        
///   <param name="UserName"> 编译的用户名。 </param>
        
///   <param name="PassWord"> 用户密码。 </param>
        
///   <param name="QNum"> 代码的问题ID。 </param>
        
///   <param name="CompilerName"> 编译器。 </param>
         public   void  GetResult(String code, String UserName, String PassWord, String QNum, String CompilerName) {
            Option cp 
=   new  Option();
            DataSet ds 
=  cp.GetLimit(QNum);
            User u 
=   new  User(UserName, CompilerName.Split( ' , ' )[ 0 ], CompilerName.Split( ' , ' )[ 1 ]);
            _Memory 
=   int .Parse(ds.Tables[ 0 ].Rows[ 0 ][ 0 ].ToString()); // 从数据库读取当前的程序 要求的Memory
            _Time  =   int .Parse(ds.Tables[ 0 ].Rows[ 0 ][ 1 ].ToString()); // 从数据库读取当前的程序 要求的Time limit
            _Test  =  ds.Tables[ 0 ].Rows[ 0 ][ " test " ].ToString(); // 读取测试文件
            _CompilerName  =  CompilerName; // 编译器名称
            _Sign  =  u.Sign;
            _CodePath 
=  u.CodePath; // 源代码文件保存的路径
            _TextPath  =  u.TextPath; // 生成文本文件保存的路径
            _ExePath  =  u.ExePath; // EXE文件保存的路径
            _myMemory  =   0 ; // 对我当前耗费的内存进行初始化
            _TestPath  =  u.GetTestPath(QNum); // 得到当前测试路径
            _AnswerId  =  cp.AddAnswer(UserName, Int64.Parse(QNum), CompilerName); // 将当前数据作为一条回答存入数据库(创建一条数据库记录)
            Code cc  =   new  Code(CompilerName, code); // 创建Code实例
             if  (cc.Check()) { // 调用配置文件中的正则表达式,测试代码中有无危险代码,有,则此回答为危险代码

                SaveTextFile(u.CodePath, code);
// 将源代码保存为相应格式文件
                _CompilerText.AppendLine(u.CompilerString); //
                DoCmd(u.CompilerString); // 用u生成编译字符串,执行编译操作
                IsTempExists(u.TextPath, u.CompilerString); // 是否编译完成
                 if  ( 0   ==  _AnswerId)
                    
return ;
                cp.SetAnswerStatus(_AnswerId, Option.AnswerStatus.编译中);
                
// 编译完成
                 if  (IsCompilerSucess(u.TextPath, u.CodePath, u.ExePath,  0 )) { // 编译产生EXE则编译成功
                    
// 编译成功
                    cp.SetAnswerStatus(_AnswerId, Option.AnswerStatus.测试中);
                    ThreadStart thr_start_func 
=   new  ThreadStart(Test); // 异步调用Test进行测试
                    Thread fThread  =   new  Thread(thr_start_func);
                    fThread.Name 
=   " Test " ;
                    fThread.Start();
                    Thread.Sleep(_Time 
*   2000 ); // 初始化最大超时时间(规定时间的2倍)
                     if  (Option.AnswerStatus.测试通过  ==  _TestResult) {
                        
// cp.SetAnswerStatus(_AnswerId, Compiler.AnswerStatus.测试通过);
                    }
                    
else  {
                        
if  (_TestResult  ==   0 ) {
                            
try  {
                            
// 对进程查看是否结束,未结束则进行操作
                                 if  ( ! _process.HasExited) {
                                    
if  ( ! _process.CloseMainWindow())
                                        _process.Kill();
                                    
if  (_TestFile_Output.ToString().StartsWith(_TestOutput.ToString()))
                                        _TestResult 
=  Option.AnswerStatus.超时;
                                    
else
                                        _TestResult 
=  Option.AnswerStatus.测试失败;
                                }
                            }
                            
catch  {
                                _TestResult 
=  Option.AnswerStatus.测试失败;
                            }

                        }
                        
if  (fThread.IsAlive) fThread.Abort(); // 最终的强制结束进程
                    }
                }
                
else  {
                    _TestResult 
=  Option.AnswerStatus.编译失败;
                    cp.SetAnswerText(_AnswerId, ReplaceFileName(_CompilerText.ToString()));
                }

                
try  {
                    
if  (_TestResult  ==  Option.AnswerStatus.测试中  ||  _TestResult  ==  Option.AnswerStatus.测试失败) {
                        Process[] p 
=  Process.GetProcessesByName(_Sign);
                        
if  (p.Length  >   0 ) {
                            
if  ( ! p[ 0 ].HasExited) {
                                
if  (p[ 0 ].Responding) {
                                    p[
0 ].CloseMainWindow();
                                    p[
0 ].Kill();
                                }
                                
else  {
                                    p[
0 ].Kill();
                                }
                            }
                            
if  (_TestFile_Output.ToString().StartsWith(_TestOutput.ToString()))
                                _TestResult 
=  Option.AnswerStatus.超时;
                            
else
                                _TestResult 
=  Option.AnswerStatus.测试失败;
                        }
                    }
                }
                
catch  { }
            }
            
else  {
                _TestResult 
=  Option.AnswerStatus.危险代码;
            }

            cp.SetAnswerStatus(_AnswerId, _TestResult);
// 写入测试结果
            cp.SaveAnswerCode(_AnswerId, code); // 写入提交的源代码
             /* try {
                if (_TestResult == Option.AnswerStatus.测试通过) {
                    using (StreamReader sr = File.OpenText(_CodePath)) {
                        cp.SaveAnswerCode(_AnswerId, sr.ReadToEnd());
                    }
                }
            }
            catch { }
*/
            DeleteTempFile();
// 删除临时文件
        }

        
private   void  DeleteTempFile() { // 删除临时文件
            Byte b  =   0 ;
            
try  {
                Thread.Sleep(
1000 ); // 每一秒试删除一次
                 if  (File.Exists(_ExePath)) File.Delete(_ExePath);  else  b ++ ;
                
if  (File.Exists(_CodePath)) File.Delete(_CodePath);  else  b ++ ;
                
if  (File.Exists(_TextPath)) File.Delete(_TextPath);  else  b ++ ;
            }
            
catch  { }
            
if  (b  !=   3 ) DeleteTempFile(); // 递归调用
             return ;
        }
        
private   bool  IsCompilerSucess( string  TextPath,  string  CppPath, String ExePath,  int  count) {
            
try  { // 看是否编译成功的函数
                 using  (StreamReader sr  =   new  StreamReader(TextPath, Encoding.Default)) {
                    String input;
                    
bool  f  =   true ;
                    
while  ((input  =  sr.ReadLine())  !=   null ) {
                        _CompilerText.AppendLine(input);
                        
if  (input.Contains( " : error: " )) {

                            _output.AppendLine(input);
                        }
                        
else  {
                            
if  (f  &&   ! input.StartsWith(CppPath))
                                _output.AppendLine(input);
                            f 
=   false ;
                        }
                    }
                    sr.Close();
                    
if  (File.Exists(ExePath)) {
                        
return   true ;
                    }
                    
else  {
                        _output.Insert(
0 " 编译出错:\r\n " );
                        
return   false ;
                    }
                }
            }
            
catch  {
            }
            Thread.Sleep(
1000 );
            
if  (count  >=   300 ) {
                _CompilerText.Insert(
0 " 服务器响应超时或您选择的编译器不正确 " );
                
return   false ;
            }
            
return  IsCompilerSucess(TextPath, CppPath, ExePath, count  +   1 );
        }
        
private   string  ReplaceFileName( string  input) {
            input 
=  System.Text.RegularExpressions.Regex.Replace(input,  @" ([A-Z]:[\\|\/][^:\*\?<>\|]+\.(txt|cs|cpp|c|vb|jsl|js|exe))|(\\{2}[^/:\*\?<>\|]+\.(txt|cs|cpp|c|vb|jsl|js|exe)) " " > " , System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            
return  input;
        }
        
private   void  Process_Exited( object  sender, EventArgs e) { // 测试程序是否超时的判断
             if  (_process.TotalProcessorTime.Milliseconds  >  _Time * 1000 ) {
                
if  (_TestFile_Output.ToString().StartsWith(_TestOutput.ToString()))
                    _TestResult 
=  Option.AnswerStatus.超时;
                
else
                    _TestResult 
=  Option.AnswerStatus.测试失败;
            }
        }
        
private   void  Test() { // 进行测试
             string  ExePath  =  _ExePath;
            
string  TestPath  =  _TestPath;
            String input;
            
bool  f  =   true ;
            _TestEnd 
=   false ;
            _process 
=   new  Process();
            _process.StartInfo.WindowStyle 
=  ProcessWindowStyle.Hidden;
            _process.StartInfo.UseShellExecute 
=   false ;
            _process.StartInfo.CreateNoWindow 
=   true ;
            _process.StartInfo.RedirectStandardInput 
=   true ;
            _process.StartInfo.RedirectStandardOutput 
=   true ;
            _process.StartInfo.RedirectStandardError 
=   true ;
            _process.StartInfo.FileName 
=  ExePath;
            _process.Exited 
+=   new  EventHandler(Process_Exited);
            _process.OutputDataReceived 
+=   new  DataReceivedEventHandler(TestOutputHandler);
            _process.Start();
            _process.BeginOutputReadLine();
            _myMemory 
=  (_process.PeakWorkingSet64  >>   10 ); // 获取内存大小
            StreamWriter sortStreamWriter  =  _process.StandardInput; // 设置异步读取流
             try  {
                
using  (StringReader sr  =   new  StringReader(_Test)) {
                    
while  (((input  =  sr.ReadLine())  !=   null )) {
                        
if  (input.StartsWith( " EOF " )) // C/C++程序的结束(CTRL+Z)方式
                             if  (_CompilerName.ToLower()  ==   " c "   ||  _CompilerName.ToLower()  ==   " cpp " )
                                sortStreamWriter.WriteLine(((
char ) 26 ).ToString());
                            
else // .net程序的结束(CTRL+Z)方式
                                _process.CloseMainWindow();
                        
if  (input.StartsWith( " > " )) // 测试的写操作
                            sortStreamWriter.WriteLine(input.Substring( 1 ));
                        
if  (input.StartsWith( " < " )) // 测试的读操作
                            _TestFile_Output.AppendLine(input.Substring( 1 ));
                    }
                }
                sortStreamWriter.Close();
                _process.WaitForExit();
                _TestEnd 
=   true ;
            }
            
catch  {
                _TestEnd 
=   true ;
            }

            
if  (_TestOutput.ToString()  ==  _TestFile_Output.ToString())
                f 
=   true ;
            
else
                f 
=   false ;
            
if  (_TestEnd  &&  f)
                _TestResult 
=  Option.AnswerStatus.测试通过;
            
else  {

            }
            
if  (_TestEnd  &&  (_myMemory  >  _Memory)) // 内存消耗太大
            {
                _TestResult 
=  Option.AnswerStatus.内存超量;
            }
            _process.Close();
            _process.Dispose();
            
if  (f  &&  _TestEnd) {
                _TestResult 
=  Option.AnswerStatus.测试通过;
            }
            
return ;

        }
        
void  SaveTextFile( string  Path,  string  text) {
            
using  (StreamWriter sw  =   new  StreamWriter(Path)) { sw.Write(text); }
        }
        
void  DoCmd( string  cmd) { // 执行一条CMD命令的函数
            Process process  =   new  Process();
            process.StartInfo.WindowStyle 
=  ProcessWindowStyle.Hidden;
            process.StartInfo.UseShellExecute 
=   false ;
            process.StartInfo.CreateNoWindow 
=   true ;
            process.StartInfo.RedirectStandardInput 
=   true ;
            process.StartInfo.RedirectStandardError 
=   true ;
            process.StartInfo.FileName 
=   " cmd.exe " ;
            process.Start();
            process.StandardInput.WriteLine(cmd);
            process.StandardInput.WriteLine(
" \r\nexit " );
            process.Close();
            process.Dispose();
        }
        
bool  IsTempExists(String TextPath, String CompilerString) {
            
int  i  =   0 ;
            
while  ( ! File.Exists(TextPath)) {
                Thread.Sleep(
1000 );
                i
++ ;
                
if  (i  >   178 return   false ;
                
if  (i  %   30   ==   0   &&  i  >   10 ) {
                    DoCmd(CompilerString);
                }
            }
            
return   true ;
        }
        
private   void  TestOutputHandler( object  sendingProcess,
            DataReceivedEventArgs outLine) {
            
int  numOutputLines  =   0 ;
            
if  ( ! String.IsNullOrEmpty(outLine.Data)) {
                numOutputLines
++ ;
                
// Environment.NewLine +"[" + numOutputLines.ToString() + "] - " + 
                _TestOutput.AppendLine(outLine.Data);
            }
        }
    }

}

上篇:由成幻OnlineJudge学习如何做自己的Acm-Icpc在线评判系统-4.建立基本的网站类库
目录
打赏
0
0
0
0
1
分享
相关文章
Potpie.ai:比Copilot更狠!这个AI直接接管项目代码,自动Debug+测试+开发全搞定
Potpie.ai 是一个基于 AI 技术的开源平台,能够为代码库创建定制化的工程代理,自动化代码分析、测试和开发任务。
139 19
Potpie.ai:比Copilot更狠!这个AI直接接管项目代码,自动Debug+测试+开发全搞定
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
49 5
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
使用ChatGPT生成登录产品代码的测试用例和测试脚本
使用ChatGPT生成登录产品代码的测试用例和测试脚本
91 35
使用ChatGPT生成关于登录产品代码的单元测试代码
使用ChatGPT生成关于登录产品代码的单元测试代码
45 16
基于SpringBoot+Vue实现的大学生体质测试管理系统设计与实现(系统源码+文档+数据库+部署)
面向大学生毕业选题、开题、任务书、程序设计开发、论文辅导提供一站式服务。主要服务:程序设计开发、代码修改、成品部署、支持定制、论文辅导,助力毕设!
47 2
Kali Linux系统Metasploit框架利用 HTA 文件进行渗透测试实验
本指南介绍如何利用 HTA 文件和 Metasploit 框架进行渗透测试。通过创建反向 shell、生成 HTA 文件、设置 HTTP 服务器和发送文件,最终实现对目标系统的控制。适用于教育目的,需合法授权。
98 9
Kali Linux系统Metasploit框架利用 HTA 文件进行渗透测试实验
使用 BenchmarkDotNet 对 .NET 代码进行性能基准测试
使用 BenchmarkDotNet 对 .NET 代码进行性能基准测试
68 13
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
102 1
接口测试新选择:Postman替代方案全解析
在软件开发中,接口测试工具至关重要。Postman长期占据主导地位,但随着国产工具的崛起,越来越多开发者转向更适合中国市场的替代方案——Apifox。它不仅支持中英文切换、完全免费不限人数,还具备强大的可视化操作、自动生成文档和API调试功能,极大简化了开发流程。
大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡
大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡
89 10
大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡

热门文章

最新文章

  • 1
    小鱼深度评测 | 通义灵码2.0,不仅可跨语言编码,自动生成单元测试,更炸裂的是集成DeepSeek模型且免费使用,太炸裂了。
    120756
  • 2
    3天功能开发→3小时:通义灵码2.0+DEEPSEEK实测报告,单元测试生成准确率92%的秘密
    73
  • 3
    Potpie.ai:比Copilot更狠!这个AI直接接管项目代码,自动Debug+测试+开发全搞定
    20
  • 4
    基于FPGA的图像双线性插值算法verilog实现,包括tb测试文件和MATLAB辅助验证
    9
  • 5
    【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
    67
  • 6
    大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡
    18
  • 7
    「ximagine」业余爱好者的非专业显示器测试流程规范,同时也是本账号输出内容的数据来源!如何测试显示器?荒岛整理总结出多种测试方法和注意事项,以及粗浅的原理解析!
    12
  • 8
    用户说 | 通义灵码2.0,跨语言编码+自动生成单元测试+集成DeepSeek模型且免费使用
    64
  • 9
    以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
    12
  • 10
    AxBench:斯坦福大学推出评估语言模型控制方法的基准测试框架
    2
  • AI助理

    你好,我是AI助理

    可以解答问题、推荐解决方案等