Как заменить строки в текстовом файле? C ++ - PullRequest
0 голосов
/ 07 августа 2020

При использовании метода замены строки возникает исключение std::out_of_range. Я не знаю, как это исправить. Я знаю, что исключение возникает, когда pos > length(), но я не уверен, как изменить текстовый файл, чтобы этого не произошло. Я пытаюсь заменить delLine на replaceLine в текстовом файле. Любая помощь приветствуется, спасибо!

unsigned int start;
start = 0;
unsigned int len;
unsigned int end;
std::string line;
std::ifstream fin;
fin.open("test.txt");
std::ofstream temp;
temp.open("temp.txt");
std::string delLine = "   color = vec4";
std::string replaceString = "   color = vec4("+red+", "+ green + ", " + blue +",1.0)";

while (getline(fin, line))
{
    start = start + line.length();
    len = replaceString.length();
    end = len + start;
    if (line.find(delLine)>start) {
        line.replace(start, end, replaceString);
    }
    temp << line << std::endl;
    line = "";
}

temp.close();
fin.close();
remove("test.txt");
rename("temp.txt", "test.txt");

1 Ответ

2 голосов
/ 07 августа 2020

getline read one line (если возможно), но ваше управление start и end похоже на if line получить полное содержимое файла, из-за управления start и end вы пытаетесь получить доступ из строки.

Из этого вы действительно хотите заменить "something color = vec4somethingelse" на "something color = vec4("+red+", "+ green + ", " + blue +",1.0)somethingelse"? вероятно, нет, поэтому не проверяйте line.find(delLine), а (line == delLine).

Обратите внимание, также достаточно добавить "("+red+", "+ green + ", " + blue +",1.0)" в конце строки, чтобы получить ожидаемый результат, потому что начало не изменилось.

Итак

std::string line;
std::ifstream fin("test.txt");
std::ofstream temp("temp.txt");

if (!fin)) {
  ...manage error...
}
else if (!temp) {
  ...manage error...
}
else {
  std::string lineToModify = "   color = vec4";
  std::string toBeAdded = "("+red+", "+ green + ", " + blue +",1.0)";

  while (getline(fin, line))
  {
    if (line == lineToModify)
      line += toBeAdded;
    temp << line << std::endl;
  }

  temp.close();
  fin.close();
  remove("test.txt"); /* you need to check success */
  rename("temp.txt", "test.txt"); /* you need to check success */
}

Пример:

#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>

int main()
{
  std::string red = "RED";
  std::string green = "GREEN";
  std::string blue = "BLUE";
  
  std::string line;
  std::ifstream fin("test.txt");
  std::ofstream temp("temp.txt");
  
  if (!fin) {
    std::cerr << "cannot open test.txt" << std::endl;
    return -1;
  }
  
  if (!temp) {
    std::cerr << "cannot open temp.txt" << std::endl;
    return -1;
  }

  std::string lineToModify = "   color = vec4";
  std::string toBeAdded = "("+red+", "+ green + ", " + blue +",1.0)";
  
  while (getline(fin, line)) {
    if (line == lineToModify)
      line += toBeAdded;
    temp << line << std::endl;
  }
  
  temp.close();
  fin.close();
  
  if (remove("test.txt") != 0) {
    perror("cannot delete test.txt, result in temp.txt");
    return -1;
  }
  
  if (rename("temp.txt", "test.txt") != 0) {
    perror("cannot rename temp.txt to test.txt, result in temp.txt");
    return -1;
  }
  
  return 0;
}

Компиляция и выполнение:

pi@raspberrypi:/tmp $ g++ -Wall c.cc
pi@raspberrypi:/tmp $ cat test.txt 
something
   color = vec4
   color = vec44
    color = vec4
   color = vec4
end
pi@raspberrypi:/tmp $ ./a.out
pi@raspberrypi:/tmp $ cat test.txt 
something
   color = vec4(RED, GREEN, BLUE,1.0)
   color = vec44
    color = vec4
   color = vec4(RED, GREEN, BLUE,1.0)
end
pi@raspberrypi:/tmp $ 

Я предполагал, что строка поиска может присутствовать несколько раз, иначе если возможно улучшить код.

В случае, если строка поиска может отсутствовать во входном файле, лучше использовать логическое значение, чтобы узнать, было ли сделано хотя бы изменение, и если нет, не удалять / переименовывать но удалите временный файл, чтобы не изменять дату модификации / создания входного файла

...