编写一个C++程序,可以在Linux中从命令行合并文件

Writing a C++ program that can merge files from the command line in Linux

本文关键字:Linux 文件 合并 命令行 程序 C++ 一个      更新时间:2023-10-16

我编写了一个C++程序,该程序应该打开两个文本文件(prog2a.datprog2b.datutfile.dat)(从第一个文件中提取行5-15,从第二个文件中获取行4-12,并将它们合并到输出文件中)非常有效。然而,在向我的教授要求澄清作业的另一部分后,我发现我做得不对。我已经编写了代码,这样它将始终输出我前面提到的行范围,但该程序实际上应该允许用户通过键入以下命令,使用他们想要的任何范围从命令行合并文件:

prog2 in1 5-15 in2 4-12 outfile

但我不知道如何调整我目前的程序,以允许这样做。

以下是我写的代码,请记住,这对于它的编写方式来说是正确的,但对于命令行来说不是应该如何工作的(希望这是有意义的):

#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
int main() {
    // Create output file
    std::ofstream outFile("outfile.dat", ios::out);
    // Open input file 1, if can't be opened, exit
    ifstream in1;
    in1.open("prog2a.dat");
    std::string line;
    int count = 1;
    if (!in1) {
        cerr << "Open Failure" << endl;
        exit(1);
    } // end if
    else {
        while (std::getline(in1, line)) {
            if (count >= 5 && count <= 15) {
                outFile << line << "n"; /*writes the contents of
                lines 5-15 to outfile.dat*/
            }
            ++count;
        } // end while
    } // end else
    in1.close(); // close in1 (prog2a.dat)
    outFile << "n"; // add a blank line after the output from prog2a.dat
    count = 1; // reset the line count to 1 before opening next file.
    // Open input file 2, if can't be opened, exit
    ifstream in2;
    in2.open("prog2b.dat");
    if (!in2) {
        cerr << "Open Failure" << endl;
        exit(1);
    } // end if
    else {
        while (std::getline(in2, line)) {
            if (count >= 4 && count <= 12) {
                outFile << line << "n"; /*writes the contents of the
                lines 4-12 to outfile*/
            }
            ++count;
        } // end while
    } // end else
    in2.close(); // close in2 (prog2b.dat)
} // end main

有什么简单的方法可以像我所描述的那样使用命令行来实现这一点吗?此外,我应该将其分解为三个文件,一个头文件、程序文件和一个测试文件(测试文件包含main(),应该关闭3个打开的文件并显示任何错误消息),但我真的很困惑头文件中应该包含什么。我知道头文件应该包含类定义和构造函数,但不知道如何使其适用于这个特定的程序?我对此非常陌生,所以任何建议都将不胜感激。

问题是行号和文件名在主函数中是硬编码的。如注释中所述,您需要处理主要函数参数。此外,您的代码包含重复,可以很容易地移动到单独的函数(读取输入文件并将所需的字符串复制到输出)。我通过将相关代码转移到单独的函数中,消除了一些重复。您仍然需要检查错误:查看代码中的//TODO注释:

#include <iostream>
#include <string>
#include <fstream>
using namespace std;

bool lineNumbersFromString(const std::string& aString, int& startPos, int& endPos)
{
    std::size_t pos = aString.find('-');
    if (pos < 0 || pos >= aString.length())
    {
        return false;
    }

    std::string start = aString.substr(0, pos);
    std::string end = aString.substr(pos + 1, aString.length()-1);
    if (start.length() == 0 || end.length() == 0)
    {
        return false;
    }
    startPos = atoi(start.c_str());
    endPos = atoi(end.c_str());
    return true;
}
bool copyLinesToOutFile(std::string& inputFileName, int startLine, int endLine, std::ofstream& outFileStream)
{
    ifstream inputFileStream;
    inputFileStream.open(inputFileName.c_str());
    if (!inputFileStream)
    {
        cerr << "Cannot open file: " << inputFileName << endl;
        return false;  
    } 
    int lineCount = 0;
    std::string line;
    while (std::getline(inputFileStream, line))
    {
        if (lineCount >= startLine && lineCount <= endLine)
        {
            outFileStream << line << "n";
        }
        ++lineCount;
    }
    inputFileStream.close();
}
int main(int argc, char** argv)
{
    if (argc != 6)
    {
        //Invalid number of arguments
        //TODO: report error
        return -1;
    }
    std::string firstFileName = argv[1];
    std::string firstFileRange = argv[2];
    std::string secondFileName = argv[3];
    std::string secondFileRange = argv[4];
    std::string outFileName = argv[5];
    int firstStartPos = 0;
    int firstEndPos = 0;
    bool ok = false;
    ok = lineNumbersFromString(firstFileRange, firstStartPos, firstEndPos);
    //TODO: check error
    // Create output file
    std::ofstream outFile(outFileName.c_str(), ios::out);
    ok = copyLinesToOutFile(firstFileName, firstStartPos, firstEndPos, outFile);
    //TODO: check error
    int secondStartPos = 0;
    int secondEndPos = 0;
    ok = lineNumbersFromString(secondFileRange, secondStartPos, secondEndPos);
    //TODO: check error
    ok = copyLinesToOutFile(secondFileName, secondStartPos, secondEndPos, outFile);
    //TODO: check error
    outFile.close();
    return 0;
}

附言:希望这能有所帮助。将其拆分为单独的文件应该不是什么大问题。