1

我正在制作一个统计收集器,它读取音乐播放器的日志并让用户显示播放次数最多的前十名等。作为一个新手项目。

日志中的一行如下所示:“20:42:03 start E:\ROTATION\A\Håkan Lidbo - Dammlunga.mp3”

我已使用 ifstream 和 getline 将其放入字符串中。

然后使用创建字符串的字符数组

const char *charveqtur = newline.c_str();

然后我尝试用 sscanf 对 i 进行排序:

sscanf (charveqtur, "%d:%d:%d\tstart\t%s", &this->hour, &this->minute, &this->second, &this->filename);

问题是文件名在第一个空格处被剪切。我也尝试过使用 istringstream,但到目前为止还没有突破。

哪种方法最方便?谢谢。

4

2 回答 2

2

您可以使用一些输入流来读取第一个整数和冒号,并且由于文件名是最后一个实体,因此您可以使用std::getline. 但是,即使您的文件名不是最后一部分,请注意这std::getline是一个非常通用的函数,可以接受任何分隔符。

一种更高级的方法是为文件名定义自己的类型并operator>>(std::istream &, T const &)对其进行重载。

std::getline这是一个使用基本诊断和stringstream一些重新格式化的完整示例:

#include <sstream>  // for istringstream
#include <iostream> // for cout and cerr
#include <iomanip>  // for setprecision
#include <cmath> 

bool read (std::string const &line) {
    char c = 0;
    double length;
    double rating;
    std::string title;

    std::istringstream ss;
    ss.str (line);
    ss >> length;        
    if (!ss.good())    { std::cerr << "invalid length\n"; return false; }
    if (ss.get()!=':') { std::cerr << "expected colon\n"; return false; }
    ss >> rating;
    if (!ss.good())    { std::cerr << "invalid rating\n"; return false; }
    if (ss.get()!=':') { std::cerr << "expected colon\n"; return false; }
    std::getline (ss, title);


    double sink;
    std::cout << title << " (" 
              << int(length) << ':' << 60*std::modf (length,&sink)
              << " min), your rating: " << rating << '\n';

    return true;
}

int main () {
    read ("30.25:5:Vivaldi - The four seasons.ogg");
    read ("3.5:5:Cannibal Corpse - Evisceration Plague.ogg");
    read ("meh");

    return 0;
}

输出:

Vivaldi - The four seasons.ogg (30:15 min), your rating: 5
Cannibal Corpse - Evisceration Plague.ogg (3:30 min), your rating: 5
invalid length

重要提示:解析时,您正在接近安全风险。始终保持清醒和明智,并尽可能尝试使用经过测试和验证的库。这也意味着您不要使用sscanf,这不是类型安全的,容易出错,有时很难正确

如果您有 C++,请不要使用 C,并且使用正确,iostreams 比 printf/scanf+co 更方便。

于 2011-11-21T14:23:33.453 回答
0

你也许可以做类似的事情

int lastpos = 0;
if sscanf (charveqtur, "%d:%d:%d\tstart\t%n", &this->hour, 
           &this->minute, &this->second,
           &lastpos) > 3 && lastpos >0) {
    std::string filename = newline.substr(lastpos);
    /* do something with filename */
}
于 2011-11-21T14:24:10.097 回答