【问题标题】:Formatting text data with C++ or any windows scripting language使用 C++ 或任何 Windows 脚本语言格式化文本数据
【发布时间】:2012-07-14 07:56:26
【问题描述】:

这可能是一项简单的任务,但目前我真的不知道如何以简单的方式做到这一点。 我有以下情况,我有一个用 COFFEE 编写的脚本,COFFEE 是 3D 程序 Cinema 4D 的脚本语言。 现在此脚本正在将以下格式的位置数据写入文本文件(在这种情况下为 rtf,但也可以是 .txt)。

0  0.0  471.2  0.0
1  0.0  470.5  0.0
2  0.0  468.8  0.0
3  0.0  465.9  0.0
4  0.0  461.9  0.0
5  0.0  456.8  0.0
6  0.0  450.5  0.0
7  0.0  443.2  0.0
8  0.0  434.8  0.0
9  0.0  425.2  0.0

框架、X、Y、Z。

现在我需要做的是把这个位置数据转换成这种格式:

Transform   Position
    Frame   X pixels    Y pixels    Z pixels    
    0   0.0    471.2    0.0 
    1   0.0    470.5    0.0 
    2   0.0    468.8    0.0 


End of Keyframe Data

这里看不到,但这里没有空格,所有内容都用制表符隔开(也许将其复制到记事本以真正看到制表符)。重要的是我在每个数字之间都有制表符,可以有空格,但我每次都需要一个制表符。 所以最重要的部分是,我如何从第一个数据集中获取这些数字,并让程序在每个数字之间添加一个 \t?

我尝试在脚本中执行此操作,但如果我使用制表符而不是位置之间的多个空格,则脚本会失败。 我搜索了很多,但找不到任何好的解决方案。 我熟悉 C++ 和一个小批处理脚本,但我对每个解决方案都很满意,即使我必须学习另一种语言的基础知识。

我试图在 C++ 中找到一种方法,但我想出的方法无法格式化 n 行,而且每一行都非常复杂。帧数/行数每次都不同,所以我从来没有固定的行数。

【问题讨论】:

  • 第一组数据如何转化为第二组数据?现在看起来您正在使用刚刚制作的东西作为示例,因为这两个集合似乎代表的不是同一件事。
  • 不,它们是脚本生成的实际数据。第二组是手动制作的,但格式是我需要它在另一个程序中处理它的格式。不要对 4.00002 帧数感到困惑,这与我选择的帧速率有关。我需要的只是每行的 4 个数字,以便在实际数字之前有一个制表符。含义: Tab 1 Tab 2 Tab 3 Tab 4 与第二个数据集中位置数据之前的文本相同。没有空格,所有内容都只有制表符。
  • 我编辑了第二组,现在应该更清楚了:)

标签: c++ windows file text formatting


【解决方案1】:

这样的事情可能会奏效。我没有对数字进行任何特殊格式化,所以如果你需要,你需要添加它。如果您担心输入文件格式不正确,例如一行中没有足够的数字,那么您可能需要添加一些额外的错误检查来防范它。

#include <fstream>
#include <iostream>
#include <vector>

bool Convert(const char* InputFilename, const char* OutputFilename)
{
    std::ifstream InFile(InputFilename);
    if(!InFile)
    {
        std::cout << "Could not open  input file '" << InputFilename << "'" << std::endl;
        return false;
    }

    struct PositionData
    {
        double FrameNum;
        double X;
        double Y;
        double Z;
    };
    typedef std::vector<PositionData> PositionVec;

    PositionVec Positions;
    PositionData Pos;
    while(InFile)
    {
        InFile >> Pos.FrameNum >> Pos.X >> Pos.Y >> Pos.Z;
        Positions.push_back(Pos);
    }

    std::ofstream OutFile(OutputFilename);
    if(!OutFile)
    {
        std::cout << "Could not open output file '" << OutputFilename << "'" << std::endl;
        return false;
    }

    OutFile << "Transform\tPosition\n\tFrame\tX pixels\tY pixels\tZ pixels" << std::endl;
    for(PositionVec::iterator it = Positions.begin(); it != Positions.end(); ++it)
    {
        const PositionData& p(*it);
        OutFile << "\t" << p.FrameNum << "\t" << p.X << "\t" << p.Y << "\t" << p.Z << std::endl;
    }
    OutFile << "End of Keyframe Data" << std::endl;
    return true;
}

int main(int argc, char* argv[])
{
    if(argc < 3)
    {
        std::cout << "Usage: convert <input filename> <output filename>" << std::endl;
        return 0;
    }
    bool Success = Convert(argv[1], argv[2]);

    return Success;
}

【讨论】:

  • 这看起来很有希望,谢谢!我只有一个问题,可能有点傻,但是我在哪里实际设置输入文件和输出文件?到目前为止我还没有使用过vector.h
  • Meh 早早地按下了Entet。我只需要添加ofstream InFile ("example.txt"); 吗?
  • 您在命令行上提供它们,所以convert input.txt output.txt 假设您将程序命名为转换。
  • 等等,这真的让我很困惑 :D 以前没见过这种用法。我在字符串中指定文件名而不删除“”?因为无论哪种方式,它似乎都不起作用:/因为它是一个字符串,所以我只打印了 cout,文件没有受到影响。当我只有convert &lt;input.txt&gt; &lt;output.txt&gt; 时,我得到一个编译错误。当然,convert 没有在任何地方指定。
  • 我接受了答案,根据我对代码的理解,它绝对应该做我想做的事。到目前为止,我还不清楚我是如何指定和输出的。我猜这与我的业余 C++ 技能有关 :)
【解决方案2】:

另一个使用正则表达式的例子

#include <fstream>
#include <iostream>
#include <regex>
#include <algorithm>
int main()
{
    using namespace std;

    ifstream inf("TextFile1.txt");
    string data((istreambuf_iterator<char>(inf)), (istreambuf_iterator<char>()));

    regex reg("([\\d|\.]+)\\s+([\\d|\.]+)\\s+([\\d|\.]+)\\s+([\\d|\.]+)");  
    sregex_iterator beg(data.cbegin(), data.cend(), reg), end;

    cout << "Transform\tPosition" << endl;
    cout << "\tFrame\tX pixels\tY pixels\tZ pixels" << endl;
    for_each(beg, end, [](const smatch& m) {
        std::cout << "\t" << m.str(1) << "\t" << m.str(2) << "\t" << m.str(3) << "\t" << m.str(4) << std::endl;
    });
    cout << "End of Keyframe Data" << endl;
}

【讨论】:

    【解决方案3】:

    如果有兴趣,可以提供一个示例 Python 脚本。

    #!c:/Python/python.exe -u
    # Or point it at your desired Python path
    # Or on Unix something like: !/usr/bin/python
    
    # Function to reformat the data as requested.
    def reformat_data(input_file, output_file):
    
        # Define the comment lines you'll write.
        header_str = "Transform\tPosition\n"
        column_str = "\tFrame\tX pixels\tY pixels\tZ pixels\n"
        closer_str = "End of Keyframe Data\n"
    
        # Open the file for reading and close after getting lines.
        try:
            infile = open(input_file)
        except IOError:
            print "Invalid input file name..."
            exit()
    
        lines = infile.readlines()
        infile.close()
    
        # Open the output for writing. Write data then close.
        try:
            outfile = open(output_file,'w')
        except IOError:
            print "Invalid output file name..."
            exit()
    
        outfile.write(header_str)
        outfile.write(column_str)
    
        # Reformat each line to be tab-separated.
        for line in lines:
            line_data = line.split()
            if not (len(line_data) == 4):
                # This skips bad data lines, modify behavior if skipping not desired.
                pass 
            else:
                outfile.write("\t".join(line_data)+"\n")
    
        outfile.write(closer_str)
        outfile.close()
    
    #####
    # This below gets executed if you call
    # python <name_of_this_script>.py
    # from the Powershell/Cygwin/other terminal.
    #####
    if __name__ == "__main__":
        reformat_data("/path/to/input.txt", "/path/to/output.txt")
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-31
      • 2010-12-22
      • 2014-04-25
      • 2016-04-15
      • 1970-01-01
      相关资源
      最近更新 更多