Язык Си.Как удалить определенный текст?

Здравствуйте, помогите сделать пожалуйста

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

#include <stdio.h>
#include <stdlib.h>
 
    int main(void)
    {
        int c = 0;
        const unsigned char discard = '!';
        const char *file_name = "ex1.txt";
        FILE *input_file = NULL, *output_file = NULL;
    
        if (!(input_file = fopen(file_name,"r")) || !(output_file = fopen("ex2.txt","w")))
        {
           fprintf(stderr,"error handling"); 
            exit(EXIT_FAILURE);
        }
    
        while ((c = fgetc(input_file)) != EOF)
        {
            if (c != discard)
            {
                fputc(c,output_file);
            }
        }
 
        fclose(input_file);
            
        exit(EXIT_SUCCESS);
    }

Я бы воспользовался std::string.

  1. Считал бы весь файл в одну char[] строку.
  2. Перевел бы ее в std::string
  3. Разбил бы на предложения (с помощью find_first_of)
  4. В зависимости от того чем предложение заканчивается, писал бы (или нет) в выходной файл.
  • Чтобы работало с Русским текстом,
    надо б еще озадачиться Unicod-ом,
    но это наверное уже другой топик.

Код:

#include <iostream>

int main()
{
	const unsigned char discardChar = '!';
	const char* file_name = "C:/CPPtest01/ex1.txt";
	//надо чтобы входной файл находился там же где и exe,
	//или надо указывать полный путь

	FILE* pFile = NULL;
	//открываем входной файл
	fopen_s(&pFile, file_name, "r");
	if (pFile == NULL) {
		fprintf(stderr, "error handling");
		exit(EXIT_FAILURE);
	}
	// извлекаем размер файла:
	fseek(pFile, 0, SEEK_END); //установить пойнтер на конец файла
	int dataSize = ftell(pFile); //считать значение пойнтера
	rewind(pFile); //переустановить пойнтер на начало файла
	// размер файла получен, зарезервировать буфер для данных
	char* pData = new char[dataSize + 1];
	dataSize = fread(pData, 1, dataSize, pFile); //считать текст, обновить размер данных (по факту сколько считано)
	pData[dataSize] = 0; //обозначить конец данных
	fclose(pFile); //закрываем входной файл

	// Конвертируем char* pData в std::string
	std::string remainingText;
	remainingText.assign(pData);
	delete[] pData; //не забудем удалить буфер

	std::cout << "Input file:\n" << remainingText.c_str() << "\n";

	//открываем вЫходной файл
	fopen_s(&pFile, "C:/CPPtest01/ex2.txt", "w");
	if (pFile == NULL) {
		fprintf(stderr, "error handling");
		exit(EXIT_FAILURE);
	}

	std::cout << "\nOutput:\n";

	while (1) {
		int sentencePositionEnd = remainingText.find_first_of(".!?");
		if (sentencePositionEnd == std::string::npos) {
			//предложений больше нет
			break;
		}
		//тут я бы еще проверил, не в кавычках ли это,
		//то есть завершающий предложение знак найден, но это НЕ конец предложения.

		//проверяем надо ли предложение сохранить 
		if (remainingText.at(sentencePositionEnd) != discardChar) {
			std::string outString = remainingText.substr(0, sentencePositionEnd + 1);
			fwrite(outString.c_str(), 1, outString.size(), pFile);
			std::cout << outString.c_str();
		}
		//удалить обработанное предложение из remainingText
		remainingText = remainingText.substr(sentencePositionEnd + 1);
	}
	// если какой-то текст еще остался (типа перевод строки или незаконченное предложение), то записать его тоже
	if (remainingText.size() > 0) {
		fwrite(remainingText.c_str(), 1, remainingText.size(), pFile);
		std::cout << remainingText.c_str();
	}
	std::cout << "\n";
	fclose(pFile); //закрываем выходной файл
}

Это console app.
Выхлоп:

Input file:
aaa. bbb!
ccc? ddd,

Output:
aaa.
ccc? ddd,