Люди помогите плиз срочно. скоро сессия а немогу прогу сделать чтоб работала.
вообщем суть такова: надо считать файл, и если в нем попадается заданный символ, удалить его, но потом надо будет вернуть обратно. например, удалим пробелы из строки файла:
__ABC_____FDC__
чтобы допустим получилось
2,3ABC5,3FDC2,0
Получается что цифра перед запятой - это количество пробелов или последовательно идущих символа, а после запятой - через сколько символов опять будет пробел. Причем сделать мне это надо именно так (препод так сказал)
Язык программирования С++ Builder но тут вроде нету неизвестных функций
вот что получилось
void __fastcall TForm1::delClick(TObject *Sender)
{
char p[255];
sym=Edit->Text;
output=fopen ("WWW.txt","w");
u=0;
g=sym[1]; - это символ который надо удалить
i=0;
c=',';
while (!feof(input)) пока не конец файла
{
if (feof(input)) break;
fgets (p,255,input); считываем строку
for (i=1;i<strlen(p);i++) пока не конец строки
{
u=0; nu=0; u- количество подряд идущих пробелов например; nu-через сколько символов опять будет пробел
if (p[i]==g) {
k=i;
while (p[i]==g){ считаем кол-во повторов символа
u++;
i++;
}
while (p[i]!=g){ считаем через сколько опять пробел будет
i++;
nu++; }
s=IntToStr(u);
r=s[1];
fwrite (&r,sizeof(char),1,output);
fwrite (&c,sizeof(char),1,output);
s=IntToStr(nu);
r=s[1];
fwrite (&r,sizeof(char),1,output);}
else
{
while (p[k]==g)
k++;
fwrite (&p[k],sizeof(char),1,output);}
}
}
fclose (input);
fclose (output);
Mem->Clear();
output=fopen ("WWW.txt","r");
Mem->Lines->LoadFromFile("WWW.txt");
}
М | Почему в паскалевском разделе?.. Переношу в С. |
Child of Bodom, так что-ли:
#include <fstream.h>
...
void __fastcall TForm1::Button1Click(TObject *Sender)
{
const int max_size = 256;
char buffer[max_size];
ifstream in_file("G:\\www.txt", ios::in);
ofstream out_file("G:\\www2.txt", ios::out);
char to_delete = ' ';
int count = 0;
while(!in_file.eof()) {
in_file.getline(buffer, max_size);
AnsiString result = "";
for(char *p = buffer; *p; p++) {
while(*p != to_delete) p++;
while(*p == to_delete) {
count += 1;
p++;
}
AnsiString after = "";
for(; *p && *p != to_delete; *p++) {
after += *p;
}
result +=
IntToStr(count) + "," + IntToStr(after.Length()) + after;
count = 1;
}
out_file << result.c_str() << endl;
}
out_file.close();
in_file.close();
Memo1->Lines->LoadFromFile("G:\\www2.txt");
}
#include <fstream.h>
...
void __fastcall TForm1::Button1Click(TObject *Sender)
{
const int max_size = 256;
char buffer[max_size];
ifstream in_file("G:\\www.txt", ios::in);
ofstream out_file("G:\\www2.txt", ios::out);
char to_delete = ' ';
int count = 0;
while(!in_file.eof()) {
in_file.getline(buffer, max_size);
AnsiString result = "";
for(char *p = buffer; *p; p++) {
while(*p != to_delete) p++;
while(*p == to_delete) {
count += 1;
p++; // вот тут че то не понятно
}
AnsiString after = "";
for(; *p && *p != to_delete; *p++) { // и вот это
after += *p;
}
result +=
IntToStr(count) + "," + IntToStr(after.Length()) + after;
count = 1;
}
out_file << result.c_str() << endl;
}
out_file.close();
in_file.close();
Memo1->Lines->LoadFromFile("G:\\www2.txt");
}
// пробегаем по всей строке buffer, используя указатель на строку
for(char *p = buffer; *p; p++) {
// Сначала - пропускаем все символы, которые НЕ являются удаляемыми (т.е., пока
// очередной символ не является удаляемым, увеличиваем p, что означает переход
// к следующему символу строки buffer). По окончании этого цикла while переменная
// p будет указывать на первый удаляемый символ.
while(*p != to_delete) p++;
// Теперь надо посчитать, сколько удаляемых символов идут подряд
// Опять же увеличиваем указатель, пока текущий символ равен to_delete
// одновременно с этим, кстати, еще и увеличиваем счетчик (count)
while(*p == to_delete) {
count += 1;
p++; // что тут тебе было не понятно - я не знаю, это и есть переход на следующий символ строки
}
// В этой строке будут храниться все символы, следующие ПОСЛЕ удаляемых,
// для того чтобы вычислить расстояние до следующей группы пробелов (ну, или чего там у тебя)
AnsiString after = "";
// Здесь - использование преимуществ цикла for
// ОБЫЧНО в цикле for указываются начальные значения переменных ";" условие продолжения
// цикла ";" и оператор, выполняемый при переходе на следующую итерацию...
// У меня нет первого парамента, то есть, начальное значение p я не задаю, его значение останется
// таким же, каким и было при выходе из предыдущего цикла while...
// А вот продолжаться этот for будет, пока не будет достигнут конец строки
// (*p равносильно *p != 0, то есть, как только *p станет равным 0 - конец строки - цикл прервется)
// и очередной символ не будет являться пробелом (как только дойдем до следующего пробела -
// цикл тоже прервется)
for(; *p && *p != to_delete; *p++) {
// Что же делаем в цикле?
// Очень просто: добавляем очередной просмотренный символ в строку
after += *p;
}
// Ну, и собираем изо всех элементов результат, который нужен: счетчик пробелов, запятая,
// сколько символов будет до следующего пробела и сама строка до следующего пробела
result +=
IntToStr(count) + "," + IntToStr(after.Length()) + after;
// Не забываем сбросить счетчик, чтобы при следующем подсчете пробелов он считал правильно
count = 1;
}
Восстановление исходной строки я бы делал так:
void __fastcall TForm1::Button2Click(TObject *Sender)О том, что именно здесь делает sscanf - читай здесь, я уже объяснял как подобный фрагмент работает:
{
const int max_size = 256;
char buffer[max_size];
int count = 0, after = 0;
ifstream infile("G:\\www2.txt", ios::in); // Это - "закодированный" файл
ofstream out_file("G:\\www3.txt", ios::out); // Сюда будет помещен результат...
char char_to_insert = ' ';
while(!infile.eof()) {
AnsiString result = "";
infile.getline(buffer, max_size);
char *p = buffer;
for(; *p; p++) {
if((sscanf(p, "%d,%d", &count, &after))) {
for(int i = 0; i < count; i++) {
result += char_to_insert;
}
p += (IntToStr(count) + "," + IntToStr(after)).Length() - 1;
}
else result += *p;
}
out_file << result.c_str() << endl;
}
out_file.close();
infile.close();
Memo1->Lines->LoadFromFile("G:\\www3.txt");
}
А вот еще у меня вопросик. Можно ли по этой технологии считывать не только текстовый файл но и .dat .dll ну или просто не только текстовый файл???
В принципе, если ты знаешь формат файла, который читаешь - то достаточно просто открыть файл как бинарный:
ifstream infile("myfile.dat", ios::in|ios::binary);и работать с ним.
void __fastcall TForm1::delClick(TObject *Sender)
{
const int max_size = 256;
char buffer[max_size];
input=fopen (vibor->FileName.c_str(),"r"); // тут из диалогового окна
output=fopen ("WWW.txt", "w");
sym=Edit->Text;
char to_delete = sym[1];
int count = 0;
while(!feof(input)) {
fgets (buffer,max_size,input);
AnsiString result = "";
for(char *p = buffer; *p; p++) {
while(*p != to_delete) p++;
while(*p == to_delete) {
count += 1;
p++;
}
AnsiString after = "";
for(; *p && *p != to_delete; *p++) {
after += *p;
}
result +=
IntToStr(count) + "," + IntToStr(after.Length()) + after;
count = 1;
}
out_file << result.c_str() << endl; // вот а как тут мне заменить тогда
}
fclose(input);
fclose(output);
Mem->Lines->LoadFromFile("WWW.txt");
}
Вот так там будет:
void __fastcall TForm1::Button6Click(TObject *Sender)
{
const int max_size = 256;
char buffer[max_size];
if(!vibor->Execute()) return; // У тебя в коде не запускается OpenDialog
FILE *input = fopen (vibor->FileName.c_str(),"rt"); // Открываем ТЕКСТОВЫЙ файл = "rt"
FILE *output = fopen ("WWW.txt", "wt"); // и здесь тоже текстовый
AnsiString sym = Edit->Text;
char to_delete = sym[1];
int count = 0;
while(!feof(input)) {
buffer[0] = '\0'; // Буфер надо сбрасывать
fgets(buffer,max_size,input);
AnsiString result = "";
for(char *p = buffer; *p; p++) {
while(*p != to_delete) p++;
while(*p == to_delete) {
count += 1;
p++;
}
AnsiString after = "";
for(; *p && *p != to_delete; *p++) {
after += *p;
}
result +=
IntToStr(count) + "," + IntToStr(after.Length()) + after;
count = 1;
}
fprintf(output, "%s\n", result.c_str()); // Вывод в файл
}
fclose(input);
fclose(output);
Mem->Lines->LoadFromFile("WWW.txt");
}
Так вывод я попробую по аналогии сделать. Спасибо большое за помощь, за советы.Попробую следовать им. Ща попробую все это скомпилить. Прикольно будет если получитсья
Слушай че то не то получается. Например, пишу удалить пробел а он еще часть текста удаляет:
Исходный файл:
Превед я тупой робот пните меня чтоб я начал работать
Полученный файл:
1,1я2,5робот2,4меня2,1я2,8работать
for(char *p = buffer; *p; p++) {У меня на твоем примере отработало...
// while(*p != to_delete) p++; // Эту строку можешь удалить...
while(*p == to_delete) {
count += 1;
p++;
}
оооо круто работает!!!! Спасибо ))
ура ща буду смотреть кнопку возвращения обратно текста этого )
ой я скоро покончу с собой:(( препод начал проверять: открыл текстовый файл, одну строку нормально проработало. он говорит а че ты мне тока одну , давай я напишу текст и посмотрим как будет удаляться. ну вот он написал :
на поле танки грохотали_ // _ это пробел поставил чтоб видно было
солдаты шли в последний бой_
а молодого китайца_
несли с пробитой головой_
7,2на1,4поле1,5танки1,9грохотали1,1
1,2х1,3Х‰1,3Х‰1,3¤G’1,1„
4,7солдаты1,3шли1,1в1,9последний3,3бой1,1
3,1а1,8молодого1,7китайца1,1
1,3ний3,3бой1,1
7,5несли1,1с1,8пробитой1,7головой
А теперь расскажи, что ИМЕННО ты вводишь? У тебя в конце каждой строки что расположено? Перевод строки? Что же ты хотел? Я тебе для чего в самом начале говорил делать это через поток ifstream + метод getline? Потому что этот метод читает всю строку, не включая символ перевода строки. Ты переделал по-своему, теперь ищи в buffer-е после прочтения символ '\n' и выкидывай его из буфера (т.е., заменяй символом '\0'). Тогда получишь в результате обработки файла
na pole tanki grohotali_
soldaty shli v posledniy boy_
a molodogo komandira_
nesli s probitoi golovoy_
4,2na1,4pole1,5tanki1,9grohotali
4,7soldaty1,4shli1,1v1,9posledniy3,3boy
3,1a1,8molodogo1,9komandira
7,5nesli1,1s1,8probitoi1,7golovoy
void __fastcall TForm1::Button6Click(TObject *Sender)
{
const int max_size = 256;
char buffer[max_size];
if(!vibor->Execute()) return;
FILE *input = fopen (vibor->FileName.c_str(),"rt");
FILE *output = fopen ("G:\\WWW4.txt", "wt");
AnsiString sym = Edit->Text;
char to_delete = sym[1];
int count;
while(!feof(input)) {
buffer[0] = '\0';
fgets(buffer,max_size,input);
AnsiString result = "";
for(char *p = buffer; (*p) && (*p != '\n'); p++) {
count = 0;
while(*p == to_delete) {
count += 1;
p++;
}
AnsiString after = "";
for(; *p && *p != '\n' && *p != to_delete; *p++) {
after += *p;
}
p -= 1;
result +=
IntToStr(count) + "," + IntToStr(after.Length()) + after;
}
fprintf(output, "%s\n", result.c_str());
}
fclose(input);
fclose(output);
Mem->Lines->LoadFromFile("G:\\WWW4.txt");
}
Спасибо большое еще раз. Вроде пашет.ну при определенных параметрах. может прокатит