Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Слияние двух файлов в один


Автор: kandrey 9.10.2009, 15:00
Задание таково: 
"Написать программу на языке C++ чересстрочного слияния (т.е. первая строка в выходном файле - это первая строка из первого файла, вторая строка в выходном файле - это первая строка из второго файла, третья строка в выходном файле - вторая строка из первого файла и т.д.) двух текстовых файлов с удалением в каждой строке слов после которых стоит любой знак препинания."

вот моя прога
Код

#include <stdio.h>
#include <iostream.h>
#include <ctype.h>
#include <stdlib.h>

char* rez_strok_dubl;
int ch_str_1= 0;
int ch_str_2= 0;
int lenf1;
int lenf2;

void func (char* uk, int* ch_str, char* stroka, int len) {
  while ((*uk!=10)&&(*ch_str<len-1)) {
   uk++;
   (*ch_str)++;
  }
  if (!ispunct(*(uk-1))) {
     do {
    uk--;
    (*ch_str)--;
   }
   while (!ispunct(*uk)&&(*uk!=10)&&(uk!=stroka));
   if (uk!=stroka) {
    uk++;
    (* ch_str)++;
   }
   while ((*uk!= 10)&&(*ch_str<len- 1)) {
    *rez_strok_dubl++=*uk++;
    (*ch_str)++;
   }
   *rez_strok_dubl++=*uk++;
  }
  uk++;
  (*ch_str)++;
 }

int main(){
 FILE *f1, *f2;
 if (!(f1= fopen ("D:\\work\\file_1.txt", "rb"))) {
  cout<<"file_1_ne_otkrit\n";
  system ("PAUSE");
  exit (1);
 }
 if (!(f2= fopen ("D:\\work\\file_2.txt", "rb"))) {
  cout<< "file_2_ne_otkrit\n";
  system ("PAUSE");
  exit (1);
 }
 fseek (f1, 0, SEEK_END);
 lenf1=ftell(f1);
 fseek (f2, 0, SEEK_END);
 lenf2=ftell(f2);
 char* stroka_1= (char*) malloc (lenf1) ;
 char* stroka_2= (char*) malloc (lenf2) ;
 fseek (f1, 0, SEEK_SET);
 fseek (f2, 0, SEEK_SET);
 fread (stroka_1, lenf1, 1, f1);
 fread (stroka_2, lenf2, 1, f2);
 fclose (f1);
 fclose (f2);
 char* rez_strok= (char*) malloc (lenf1+lenf2) ;
 rez_strok_dubl= rez_strok;
 while (ch_str_2<lenf2) {
  func (&stroka_1[ch_str_1], &ch_str_1, stroka_1, lenf1);
  func (&stroka_2[ch_str_2], &ch_str_2, stroka_2, lenf2);
 }

 FILE* f3;
 if (!(f3= fopen ("D:\\work\\B.txt", "wb"))) {
  cout<< "file_3_ne_otkrit\n";
  system ("PAUSE");
  exit (1);
 }

 int i= 0;
 while (&rez_strok [i]!= rez_strok_dubl)
  fputc ((unsigned char)rez_strok [i++], f3);
 fclose (f3);
 return 0;
}


file_1.txt
Код

First codex was used for accounting, but 
with the development of parchment in the III century BC. e., gradually began to displace the papyri. 
This is already happening in the Christian world. The reasons for the adoption of the manuscript as the main type of books 
several: it is economical because you can use both sides of the paper, it is easy to hide; 
It was convenient and accessible. Perhaps the Christian writers used the original purpose, that they were not 
similar to the pagan texts, which are usually written in the form of scrolls.


file_2.txt
Код
At the beginning of XIV century in Western Europe appeared woodcutting (it was developed 
long before the East). In the matrix of woodcuts depicting Pages 
cut from a piece of wood. It can be dipped in ink and 
used to make multiple copies of a page. Books, as well as playing 
cards and religious pictures, began to produce woodcuts. But the creation of the book was 
laborious process, since each page had to do his carving. Besides,
First codex was used for accounting, but 
with the development of parchment in the III century BC. e., gradually began to displace the papyri. 
This is already happening in the Christian world. The reasons for the adoption of the manuscript as the main type of books 
several: it is economical because you can use both sides of the paper, it is easy to hide; 
It was convenient and accessible. Perhaps the Christian writers used the original purpose, that they were not 
similar to the pagan texts, which are usually written in the form of scrolls.


B.txt
Код
but 
it was developed 
 
 In the matrix of woodcuts depicting Pages 
 The reasons for the adoption of the manuscript as the main type of books 
 It can be dipped in ink and 
 
 as well as playing 
 that they were not 
 But the creation of the book was 
 which are usually written in the form of scrolls.
 but 
¦ 
¦ The reasons for the adoption of the manuscript as the main type of books 
¦ 
¦ that they were not 
¦ which are usually written in the form of scrolls.


Добавлено @ 15:01
Проблемы:
1) У меня не получилось организовать слияние строк... В моём случае в первом файле 6 строк, а во втором - 12 строк... При черезстрочном слиянии получается, что когда в первом файле обработалось 6 строк и во втором файле 6 строк, в первом файле строки закончились, но во втором и еще 6.. И они копируются оставляя перед собой то какой-то символ, то просто пустую строчку...
Как бы сделать, чтобы когда одинаковое кол-во строк в файлах закончилось, и если в каком-то файле еще остались строки, то чтобы они просто скопировались в исходный файл (без пропусков строки и всяких посторонних символов)??

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

Код

with the development of parchment in the III century gradually began to displace the

Автор: zim22 9.10.2009, 15:05
Цитата(kandrey @  9.10.2009,  15:00 Найти цитируемый пост)
Задание таково: "Написать программу на языке C++

у тебя программа на Си. 
то, что ты cout используешь - не делает её С++.

Автор: kandrey 9.10.2009, 15:58
Цитата(zim22 @ 9.10.2009,  15:05)
Цитата(kandrey @  9.10.2009,  15:00 Найти цитируемый пост)
Задание таково: "Написать программу на языке C++

у тебя программа на Си. 
то, что ты cout используешь - не делает её С++.

да эт лан, препод говорит пойдет и так...

Автор: bsa 9.10.2009, 17:13
На С++ будет выглядеть примерно так:
Код
#include <iostream>
#include <fstream>
#include <string>

int main()
{
   std::ifstream in1("file1.txt");
   if (in1.bad()) {
      std::cerr << "Unable to open file1.txt" << std::endl;
      return 1;
   }
   std::ifstream in2("file2.txt");
   if (in2.bad()) {
      std::cerr << "Unable to open file2.txt" << std::endl;
      return 1;
   }
   std::ofstream out("file.txt");
   if (out.bad) {
      std::cerr << "Unable to open file.txt" << std::endl;
      return 1;
   }
   std::string buf;
   while(in1 || in2) {
      if (std::getline(in1, buf))
         out << buf << '\n';
      if (std::getline(in2, buf))
         out << buf << '\n';
   }
   std::cin.get();
   return 0;
}
Заметно проще, не правда ли?  smile 

Автор: zim22 9.10.2009, 17:19
Цитата(bsa @  9.10.2009,  17:13 Найти цитируемый пост)
 while(in1 && in2) {

while (in1 || in2)

Автор: bsa 9.10.2009, 17:36
zim22, точно. Спасибо. Исправил.
Когда писал думал, надо ставить "или"... А поставил "И".

Автор: kandrey 9.10.2009, 21:14
Цитата(bsa @ 9.10.2009,  17:13)
На С++ будет выглядеть примерно так:
Код
#include <iostream>
#include <fstream>
#include <string>

int main()
{
   std::ifstream in1("file1.txt");
   if (in1.bad()) {
      std::cerr << "Unable to open file1.txt" << std::endl;
      return 1;
   }
   std::ifstream in2("file2.txt");
   if (in2.bad()) {
      std::cerr << "Unable to open file2.txt" << std::endl;
      return 1;
   }
   std::ofstream out("file.txt");
   if (out.bad) {
      std::cerr << "Unable to open file.txt" << std::endl;
      return 1;
   }
   std::string buf;
   while(in1 || in2) {
      if (std::getline(in1, buf))
         out << buf << '\n';
      if (std::getline(in2, buf))
         out << buf << '\n';
   }
   std::cin.get();
   return 0;
}
Заметно проще, не правда ли?  smile

все дело, что у меня должно работать на Turbo C++ (досовая версия)... 
Т.к. мне нужно чтобы работало в классе информатики...

Автор: bsa 9.10.2009, 21:46
не знаю, есть ли там string...
Отличия будут заключаться в наличии расширения у подключаемых файлов (например: iostream.h) и отсутствии std::.
Возможно, в той среде нет класса string. В этом случае придется объявить buf как char buf[1024], а вместо std::getline использовать http://www.cplusplus.com/reference/iostream/istream/getline/.
А преподавателю рекомендую посоветовать не учить тому, что никому не нужно (можно дать ссылку на это сообщение на форуме).

Автор: kandrey 10.10.2009, 10:56
Цитата(bsa @ 9.10.2009,  21:46)
не знаю, есть ли там string...
Отличия будут заключаться в наличии расширения у подключаемых файлов (например: iostream.h) и отсутствии std::.
Возможно, в той среде нет класса string. В этом случае придется объявить buf как char buf[1024], а вместо std::getline использовать http://www.cplusplus.com/reference/iostream/istream/getline/.
А преподавателю рекомендую посоветовать не учить тому, что никому не нужно (можно дать ссылку на это сообщение на форуме).

спасибо, можешь объяснить что да как здесь работает, а то если честно практически ничего не понятно....

Код

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

int main()
{
   //char buf[1024];
   ifstream in1("D:\\work\\file_1.txt");
   if (in1.bad()) {
      cerr << "Unable to open file_1.txt" << endl;
      return 1;
   }
   ifstream in2("D:\\work\\file_2.txt");
   if (in2.bad()) {
      cerr << "Unable to open file_2.txt" << endl;
      return 1;
   }
   ofstream out("D:\\work\\B.txt");
   if (out.bad) {  \\Error: Member function must be called or its address taken
      cerr << "Unable to open B.txt" << endl;
      return 1;
   }
   char buf[1024];
   while(in1 || in2) {
      if (in1.getline(in1, buf))   //Error: Could not find a match for 'istream::getline(ifstream, char*) '
         out << buf << '\n';
      if (in2.getline(in2, buf))   //Error: Could not find a match for 'istream::getline(ifstream, char*) '
         out << buf << '\n';
   }
   cin.get();
   return 0;
}


И к данному коду выкидывает еще три ошибки, по которым не понимаю что исправить..

Автор: zim22 10.10.2009, 11:06
Цитата(kandrey @  10.10.2009,  10:56 Найти цитируемый пост)
 if (out.bad) {  \\Error: Member function must be called or its address taken

до причины этой ошибки мог бы и сам додуматься
Цитата(kandrey @  10.10.2009,  10:56 Найти цитируемый пост)
  if (in1.bad()) {

Цитата(kandrey @  10.10.2009,  10:56 Найти цитируемый пост)
   if (in2.bad()) {

Автор: kandrey 10.10.2009, 11:13
Цитата(zim22 @ 10.10.2009,  11:06)
Цитата(kandrey @  10.10.2009,  10:56 Найти цитируемый пост)
 if (out.bad) {  \\Error: Member function must be called or its address taken

до причины этой ошибки мог бы и сам додуматься
Цитата(kandrey @  10.10.2009,  10:56 Найти цитируемый пост)
  if (in1.bad()) {

Цитата(kandrey @  10.10.2009,  10:56 Найти цитируемый пост)
   if (in2.bad()) {

Понимаешь в том виде как у меня было написано в первом посте я все понимаю...
Но в таком виде я ни разу прогу не видел... мы и учили С++ на это Turbo C++...

Автор: Dov 11.10.2009, 00:13
Цитата(kandrey @  10.10.2009,  10:13 Найти цитируемый пост)
Понимаешь в том виде как у меня было написано в первом посте я все понимаю...

Так что ли?
Код
#define LEN 256

void delSep(char * str)
{
    char *    beg, * end;
    char *    sep    = ".,:;?!(){}[]";         // добавить разделители, если нужно

    while(end = strpbrk(str, sep))
    {
        beg = end;

        while(*(end + 1) && !isalnum(*(end + 1)))      end++;
        while(!isalnum(*beg) && beg >= str)            beg--;
        while(!isspace(*beg) && beg >= str)            beg--;
        while(!isalnum(*beg) && beg >= str)            beg--;

        if(beg >= str)
            *(++beg) = ' ';
        strcpy(beg + 1, end + 1);
    }
}

void writeStr(char * str, FILE * in, FILE * out)
{
    if(fgets(str, LEN, in))
    {
        delSep(str);
        fputs(str, out);
        
        if(str[strlen(str) - 1] != '\n')
            fputc('\n', out);
    }
}

int main()
{
    // проверку на открытие файлов сделаешь сам...
    FILE *    f1            = fopen("file_1.txt", "rt");
    FILE *    f2            = fopen("file_2.txt", "rt"); 
    FILE *    f3            = fopen("b.txt", "wt");
    char      buf[LEN]      = "";

    while(!feof(f1) || !feof(f2))
    {
        writeStr(buf, f1, f3);
        writeStr(buf, f2, f3);
    }

    fcloseall();
    return 0;
}


Автор: kandrey 11.10.2009, 09:21
Код

#include <string.h>
#define LEN 256
#include <stdio.h>
#include <ctype.h>

void delSep(char * str)
{
    char *    beg, * end;
    char *    sep    = ".,:;?!(){}[]";         // добавить разделители, если нужно

    while(end = strpbrk(str, sep))  //??
    {
        beg = end;

        while(*(end + 1) && !isalnum(*(end + 1)))      end++;  //??
        while(!isalnum(*beg) && beg >= str)            beg--;      //??
        while(!isspace(*beg) && beg >= str)            beg--;      //??
        while(!isalnum(*beg) && beg >= str)            beg--;      // ??

        if(beg >= str)
            *(++beg) = ' '; //??
        strcpy(beg + 1, end + 1); //??
    }
}

void writeStr(char * str, FILE * in, FILE * out)
{
    if(fgets(str, LEN, in)) //??
    {
        delSep(str);  //??
        fputs(str, out);
        
        if(str[strlen(str) - 1] != '\n')
            fputc('\n', out);
    }
}

int main()
{
    // проверку на открытие файлов сделаешь сам...
    FILE *    f1            = fopen("file_1.txt", "rt");
    FILE *    f2            = fopen("file_2.txt", "rt"); 
    FILE *    f3            = fopen("b.txt", "wt");
    char      buf[LEN]      = "";

    while(!feof(f1) || !feof(f2))  //??
    {
        writeStr(buf, f1, f3);
        writeStr(buf, f2, f3);
    }

    fcloseall();
    return 0;
}

Во спасибо это как раз почти что подходит для меня...
Только как бы исправить некоторые ошибки??
И где здесь осуществляется поиск знаков препинания??
Все с ошибками разобрался, нужно было подключить модуль с type

Объясни пожалуйста некоторые места в проге отмеченные знаками вопроса...

Автор: bsa 12.10.2009, 10:16
http://www.cplusplus.com/reference/clibrary/cstring/strpbrk/
http://www.cplusplus.com/reference/clibrary/cctype/
http://www.cplusplus.com/reference/clibrary/cstring/strcpy/
http://www.cplusplus.com/reference/clibrary/cstdio/fgets/
http://www.cplusplus.com/reference/clibrary/cstdio/feof/

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)