【问题标题】:Replace any line with another string用另一个字符串替换任何行
【发布时间】:2021-12-27 13:13:50
【问题描述】:

我想替换特定行的一部分。我以为我可以:

  1. 找线
  2. 为此行分配一个临时行(如 target_line)
  3. 在临时线路上更改我想要的部分
  4. 删除原始行并重写我的文本文件中的临时行

我的一行包含:姓名、姓氏、职位、年龄、表演和球衣号码。的一个球员。如果用户愿意,我想更改“执行”编号。

所以我写了这段代码:

void TeamSetFuncChangePerform(string nickname, int jersey) {
ifstream readForChanging;

readForChanging.open("formedteam.txt", ios::app);

string target_team = nickname;
int    target_player = jersey;
int jerseyno;
string line;
size_t isFound{};
string target_line;
string perform;
int answer;


if (readForChanging.is_open()) {
    while (!(readForChanging.eof())) {
        getline(readForChanging, line);
        isFound = (line.find(target_team));
        if (isFound != string::npos) {
            isFound = 1;
            break;
        }
        else {
            isFound = 0;
        }
    }

我用上面的代码在文件中找到了目标球队,我试着用下面的代码找到了目标球员:

if (isFound == 1) {
    for (int i = 0; i < 11; i++) {
        getline(readForChanging, line);
        isFound = (line.find(target_player));
        if (isFound != string::npos) {
            target_line = line;
            cout << "enter performans value between 30-100";
            cin >> perform;
            target_line[61] = perform[0];
            target_line[62] = perform[1];

            cout << "changed the performance value of player #" << target_player << endl;

如果找到了目标玩家,那么我将获得新“执行”值的输入。现在我必须用旧的替换新的“执行”值。我也搜索了replace() 方法,但我不明白我怎么能用replace() 做到这一点。那么,问题是如何更改特定的子字符串并将其重写到文件中?

这是我的文本文件的示例。例如,如何将 Benjamin Blanchet 的“表现”值更改为新的?

name surname             position                 age       perform    jersey no
team: tr-trabzonspor
Leon Schmidt             santrafor                31        55         88        
Leon Schmidt             kanat forvet             32        81         96        
Robin Perez              kanat forvet             29        40         2         
Robin Perez              ofansif ortasaha         20        69         68        
Howl Pendragon           ofansif ortasaha         27        95         57        
Benjamin Blanchet        ortasaha                 19        78         54        
Yves Russo               ortasaha                 24        87         40        
Robin Perez              sagbek                   23        79         4         
Hans Weber               solbek                   36        57         89        
Hans Weber               defans                   18        43         21        
William Dupont           kaleci                   35        83         83        

【问题讨论】:

  • 替换文本通常归结为读取整个文件,替换内存中的字符串。重命名旧文件,写入新文件,删除旧文件(或其他文件名交换机制)
  • This 解释了您的要求。基本上,涉及3个步骤。 1 写入临时文件。 2 重命名原始文件。 3 将临时文件重命名为原始文件。
  • sed怎么样?
  • 我建议重新格式化这段代码(适当的缩进)。乍一看,我没有意识到函数声明后写的代码在函数中,直到我发现打开大括号。

标签: c++


【解决方案1】:

考虑一下您是否想要一个快速而肮脏的解决方案,或者一个适用于任何类型数据的可重复使用的解决方案。

我会选择第二个选项,将代码拆分为子问题:

  1. 如果少于 1000000 行,则将文件读入内存。
  2. 解码标题,我有哪些列以及每个列的宽度
  3. 解码文件的其余部分,每一行的语法是否正确?使用标题行的语法。也许为此找到一个正则表达式库(regex)以避免困难的空格/制表符,大写/小写。
  4. 对数据运行查询,替换任何你想要的。
  5. 将数据写回(相同的)文件。仅当至少更改一个时。

【讨论】:

    【解决方案2】:

    我想建议的是一个通常应该避免的肮脏技巧。 只有当您的文件非常大时,才值得一看。但是这个技巧有一个前提:

    文件中所有行的长度应该相似,这意味着您可能需要用额外的空格填充每一行以达到前缀大小。另外,线的每一部分都需要有一个最大的固定尺寸。

    假设您已将文件行设计为 80 个字符,如下所示:

    |----    25 chars   ----||----    25 chars   ----||-- 10 --||--  10  --||--  10 --|
    Leon Schmidt             santrafor                31        55         88         \n
    

    但是如果你有这样的文件,你可以手动计算每一行的起始字节数。因此,如果要更改第 10 行,起始字节将为 (10+2)*80=960(为 2 行标题添加 2)。然后您可以以 binary 的形式打开文件,使用fseek() 转到第 960 个字节,然后更新该行中的 80 个字节。在这种情况下,您可以以最小的开销更改文件。

    但正如我所说,这是一个肮脏的伎俩,除非完全必要,否则应该避免。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-14
      • 2013-12-03
      • 2019-05-14
      • 2021-07-19
      • 1970-01-01
      • 2017-01-28
      • 2017-03-07
      相关资源
      最近更新 更多