БлогNot. Про вектор из строк string и быструю замену строк методами класса string

Про вектор из строк string и быструю замену строк методами класса string

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

while ((ch = file.get()) != EOF)

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

while (ch = (file.get() != EOF))

так как у операций отношения (равно, не равно) приоритет выше, чем у присваивания (табл. 3.3) и, в результате, в переменную ch будут записаны не очередные символы, прочитанные из файла, а "единички" для всех символов, не равных концу файла :)

Так как была задача ещё и осуществить в прочитанном из файла (посимвольным или построчным чтением) векторе строк замену одной подстроки на другую (длины строк необязательно совпадают), в показанном листинге есть простейшее решение и этой задачки.

Нужно понимать, что любая операция со строкой, требующая по ней больше одного прохода, не есть хорошо. Культурней, но и обычно более трудоёмко, написать какой-то вот такой классический код. Кроме того, есть стандартный алгоритм replace, который можно приспособить и для строк, а есть отличные возможности класса string по поиску и замене:

#include <iostream> 
#include <string> 
#include <clocale> 
using namespace std;

int main() {
 setlocale(LC_ALL,"Rus");

 int pos = 0;
 int match_pos;
 string target = "Около колокола околачивались колокольчики.";
 string oldVal = "ко"; //что заменяем
 string newVal = "кококо"; //на что

 cout << endl << "Target:";
 cout << endl << target;

 string::size_type n = 0;
 while ((n = target.find(oldVal, n)) != string::npos) {
  target.replace(n, oldVal.size(), newVal);
  n += newVal.size();
 }

 cout << endl << "Result:";
 cout << endl << target;
 cin.get(); return 0;
}
Target:
Около колокола околачивались колокольчики.
Result:
Окококоло кококолокококола окококолачивались кококолокококольчики.

Так как здесь поиск нового вхождения начинается с места, где закончилось предыдущее вхождение, можно считать, что делаем один проход :)

Также обратите внимание, что здесь искомая строка изменяется "на месте" и оказывается с заменами по завершении цикла while.

И вот наш начальный листинг, файл для примера формируется тоже программно в текущей папке.

Коды заметки проверены в консоли Visual Studio 2015.

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <clocale>
using namespace std;
int main() {
 setlocale(LC_ALL, "Rus");
 vector <string> v;
 //Создаем файл с данными для теста
 ofstream w("data.txt");
 string data("I'm software engineer,\n\
Get\n\
  me\n\
  out\n\
  of here!\n\
  Прагма #абырвалг\n\
  here is ere of something");
 w << data;
 w.close();
 //Читаем его посимвольно, но в вектор строк
 ifstream f("data.txt");
 string s;
 int ch = 0;
 while ((ch = f.get()) != EOF) {
  if ((char)ch != '\n') s += (char)ch;
  else { v.push_back(s); s.clear(); }
 }
 if (!s.empty()) v.push_back(s);
 f.close();
 //Теперь строки файла в векторе v, делаем поиск и замену
 string search = "er"; //строка для поиска
 string repl = "!!!"; //строка для замены
 for (unsigned int i = 0; i < v.size(); i++) {
  unsigned int n = 0; //начальная позиция поиска
  do {
   n = v[i].find(search, n);
   if (n != string::npos) {
    v[i].replace(n, search.size(), repl);
   }
   else break;
  } while (1);
  cout << (i + 1) << ") " << v[i] << endl;
 }
 cin.get(); return 0;
}

23.04.2019, 16:08 [1483 просмотра]


теги: textprocessing c++ учебное алгоритм

К этой статье пока нет комментариев, Ваш будет первым