[00:00.00]
[00:54.25]1
[00:57.14]2
[01:01.04]3
[01:05.78]4
[01:08.03]5
[01:11.02]6
[01:14.21]7
[01:19.64]8
[01:21.83]9
[01:28.68]a
[01:33.34]b
[01:36.65]c
[01:40.58]d
考虑到文本文件中的以下文本,对于每个空白行,我想采用下一行的时间戳,将其减去0.8,并将其放在该空白行中。
[00:00.00]
[00:54.25]1
[00:57.14]2
[01:01.04]3
[01:05.78]4
[01:08.03]5
[01:11.02]6
[01:14.21]7
[01:19.64]8
[01:21.03]
[01:21.83]9
[01:28.68]a
[01:33.34]b
[01:35.85]
[01:36.65]c
[01:40.58]d
这是我目前的思路:
1)将文本文件复制到char的向量中,附加char' \ n'在每一行的末尾。
2)循环通过所有' \ n'直到它连续发现其中的两个。
3)一旦完成,它会查看接下来的9个字符(排除最后一个字符的时间戳']'),并将其存储到变量中。
4)删除不必要的字符' ['并且':',取前两个数字,乘以60(使它们成为秒数),并将其添加到接下来的两个数字并将其存储到一个int中。
5)将int减去0.8并将秒转换为分钟,将其转换为char,然后重新添加字符' ['和':'
6)添加时间戳和字符']'两者之间' \ n'
7)循环到下一个' \ n'。
到目前为止,我只将文件推入向量并尝试查找2个新行:
using namespace std;
int main() {
ifstream inFile("file.txt");
vector<char> lineArray;
string line;
char newLine = '\n';
ofstream outFile("newfile.txt");
while (getline(inFile, line)) {
copy(line.begin(), line.end(), back_inserter(lineArray));
lineArray.push_back(newLine);
}
for (std::vector<char>::const_iterator i = lineArray.begin(); i != lineArray.end(); ++i)
if (*i != '\n\n') {
std::cout << *i;
}
system("pause");
}
以下是我的以下问题:
1)如果(* i!=&#39; \ n \ n&#39;)没有奏效。如何检查* i是否等于2个换行符?
2)你如何偷看&#34;在新的几个字符没有迭代并将其存储到变量中?
3)如何在向量中间添加新计算的时间戳,同时进行迭代?
提前谢谢。
答案 0 :(得分:0)
你的方法还可以,但你可能想得太辛苦了。而不是阅读所有数据然后再尝试处理它,而不是在你去的时候更容易处理它。
要阅读时间戳,请不要担心展望未来。只需使用std::regex
分离当前行上的部分,然后转换为整数(允许您决定是否需要插值或偏移)。
任何与时间戳模式不匹配的非空行都可以被视为错误,但可以认为不匹配的模式实际上是空行。所以我的例子会完全忽略任何无效的行。
#include <iomanip>
#include <iostream>
#include <regex>
#include <string>
#include <vector>
int main()
{
const std::regex timestamp_regex( "^\\[(\\d+):([0-5]\\d).(\\d\\d)\\]");
std::smatch match;
std::string line;
std::vector<std::string> lines;
int last_timestamp = 0;
bool empty_line = false;
while( std::getline( std::cin, line ) )
{
// Consider non-matching regex to be empty line, instead of line.empty()
if( std::regex_search( line, match, timestamp_regex ) )
{
int timestamp = std::stoi( match[1] ) * 6000
+ std::stoi( match[2] ) * 100
+ std::stoi( match[3] );
// Offset or interpolate timestamp for single empty line
if( empty_line )
{
empty_line = false;
int t = timestamp - 80;
if( t < last_timestamp ) t = (last_timestamp + timestamp) / 2;
std::ostringstream oss;
oss << std::setfill('0') << '['
<< std::setw(2) << (t/6000) << ':'
<< std::setw(2) << (t/100%60) << '.'
<< std::setw(2) << (t % 100) << ']';
lines.emplace_back( oss.str() );
}
last_timestamp = timestamp;
lines.push_back( line );
}
else
{
empty_line = true;
}
}
// Display all the lines
for( auto & line : lines )
{
std::cout << line << std::endl;
}
return 0;
}
这是working example的链接 - 我应该指出编译器应该至少支持C ++ 11。
请注意,这些行都存储为字符串向量。但是如果你坚持使用单个连续的字节向量,那么这是一个微不足道的修改。
此外,如果您的时间戳不是按时间顺序排列,则会产生意外结果。
如果你真的想要回答你的3个问题,我想这可以在一个单独的答案中解决。但是你的问题来自凌乱的方法,需要凌乱的解决方案。也许你只是不想去那里。
答案 1 :(得分:0)
这是另一种方法,它使用Howard Hinnant's free, open source, header-only date library来解析和格式化时间戳,<chrono>
用于时间戳计算。它需要C ++ 11,C ++ 14或C ++ 17,因为它基于<chrono>
,直到C ++ 11才引入。它可以在Windows,gcc和clang(以及可能的其他)上移植。
#include "date.h"
#include <cassert>
#include <fstream>
#include <string>
int
main()
{
using namespace std;
ifstream inFile{"file.txt"};
ofstream outFile{"newfile.txt"};
string linenumber;
istringstream in;
using centiseconds = chrono::duration<int, centi>;
centiseconds last_ts{0};
constexpr centiseconds ts80{80};
constexpr auto fmt = "[%M:%S]";
while (inFile)
{
// Try to parse a time stamp
centiseconds ts;
inFile >> date::parse(fmt, ts);
if (inFile.fail())
{
// Didn't work. End of file?
if (inFile.eof())
break;
// Ok, assume a blank line and consume it
inFile.clear();
inFile.ignore(1, '\n');
// parse next line and assume it is a valid time stamp
inFile >> date::parse(fmt, ts);
assert(!inFile.fail());
// Create and format the interpolated time stamp
auto its = ts - last_ts < ts80 ? (ts + last_ts) / 2 : ts - ts80;
outFile << date::format(fmt, its) << '\n';
}
getline(inFile, linenumber); // parse optional line number
// Format current time stamp, unchanged.
outFile << date::format(fmt, ts) << linenumber << '\n';
last_ts = ts;
}
}
要做的第一件事就是为所需的精度创建自定义chrono::duration
:centiseconds
。
接下来设置一些常量。 fmt = "[%M:%S]"
字符串用于解析和格式化时间戳。
虽然输入文件很好:
一个。尝试解析时间戳。
B中。如果解析失败,并且我们没有命中文件结尾,请使用空白行。
℃。在空行后解析时间戳。
d。计算插值时间戳并将其格式化。
电子。解析当前时间戳的可选行号,然后将所有内容格式化。
F。记住下一次迭代的时间戳,以便在需要时可以进行平均。
此公式不需要vector
来存储整个输入文件。您只需逐行输出即可。
您无法(轻松)使用strptime
/ strftime
/ get_time
/ put_time
进行解析和格式化,因为它们不会处理亚秒级精度。
请注意,缺少手动时间单位转换。这消除了常见的错误来源。