Znajdowanie i podmiana danych w pliku na inne

0

Cześć,

Chcę napisać program, który w lini poleceń dostaje 2 argumenty. Nazwę pliku i wyraz który ma w pliku w odpowiednim miejscu umieścić. Np.

Cześć, mam na imię * .
program.exe plik.txt Zenon

Cześć, mam na imię Zenon .

Czyli z grubsza widać, w miejscu * wstawia podany wyraz.
Teraz tak, domyślam się, że trzeba wczytywać dane z pliku znak po znaku i porównywać z naszą "*".
Jak znajdę gwiazdkę to jak odczytać jej położenie?
Czy od razu przy wczytywaniu istnienie metoda która po znalezieniu * podmieni mi ją na inne dane czy muszę przechować gdzieś jej położenie, później otworzyć plik do zapisu i wtedy wstawić to co chcę?

Ok, skleiłem na szybko taki kod:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main(int argc, char **argv){
	
	string text = argv[1];
	fstream fin(argv[2], ios_base::in|ios_base::out);
	
	if(fin.is_open()){
		
		char ch;
		streampos pos;
		
		while(fin >> noskipws >> ch){
			if(ch == '*'){
				//cout << "jest gwiazdka na pozycji: " << fin.tellp() << endl;
				pos = fin.tellp();
				fin.seekp(pos);
				fin.write("Zenon", 5);
			}
		}	
		
	}else{
		cout << "Can't to open file \n";
	}

	fin.close();
	
	return 0;
}

Tylko tellp() zwraca mi nie to położenie którego oczekuję :/.

0

Nie podmienia Ci w locie podczas wczytywania, ale za to proste i łatwo parametryzować tekst do podmiany:

#include <sstream>
#include <fstream>
#include <string>

using namespace std;

int main(int argc, char *argv[])
{
    string newtext = argv[1];
    
    ifstream input(argv[2]);
    stringstream buf;
    buf << input.rdbuf();
    input.close();

    string fileData = buf.str();
    unsigned replacePosition = fileData.find("*");
    fileData.erase(replacePosition, 1);         // ogolnie wypadaloby sprawdzic czy pozycja < npos
    fileData.insert(replacePosition, newtext);

    ofstream output(argv[2]);
    output << fileData;
    output.close();

	return 0;
}
1

Samą podmianę w trywialny sposób możesz zrealizować za pomocą std::regex:

	string sub = "Zenon";

	string data = u8"Cześć, mam na imię * .";

	auto replaced = regex_replace(data,regex{R"(\*)"},sub);

http://melpon.org/wandbox/permlink/8Nyi8gxNm6bFR9ub

0

Dzięki za wskazówki :).

0

Podepnę się pod temat bo ostatnio męczyłem się nad czymś podobnym i poradziłem sobie z użyciem tych wszystkich udogodnień jakie dają różne gotowe funkcje w C++, wstawiania, usuwania itd.
Natomiast mam pytanie jak by się chciało samemu osiągnąć taki efekt to w jaki sposób osiągnąć coś takiego, że np mając kilka * do zamiany na słowa w większym pliku, z akapitami itd, poprzesuwać tekst za wstawianym słowem by nie został nadpisany? Bo zawsze jak zamiast np. * albo jakiegoś innego znaku wstawiałęm słowo, to dane za nim były nadpisywane, nie przesuwały się? Dodam, że próbowałem używać funkcji seekp w drugim wariancie czyli:
ostream& seekp (streamoff off, ios_base::seekdir way);
jako offset podając pobraną pozycję tellg() danego znaku do zamiany w tym wypadku *, a jako drugi argument ios_base::cur, lecz niestety dało to taki sam efekt jak w przypadku 1 wariantu czyli:
ostream& seekp (streampos pos);

Żeby bardziej rozjaśnić o co mi chodzi to taki przykład, np zamiast * wstawiamy imię Tomasz.

Witaj *,

Bla bla bla bla bla *.

Bla bla * bla bla bla.

No i kończy się to tak:

Witaj Tomasza bla bla bla bla Tomasza bla Tomaszbla bla.

Wiem, że nie ma sensu się męczyć ale chciałbym wiedzieć to dla samego siebie? W jaki sposób coś takiego osiągnąć?
Będę wdzięczny jak ktoś mnie nakieruje, niekoniecznie da gotowy kod ;).

1

Masz rozwiązanie z regex_replace 2 posty wyżej.

0

Czytaj z jednego pliku pisz do drugiego. Po zakończeniu usuń stary, przemianuj nowy. Nie mam możliwości wstawienia czegokolwiek w środek pliku.

1 użytkowników online, w tym zalogowanych: 0, gości: 1