Przepisywanie kodu z Pascala na C++

0

Znalazem w pewnej hiszpanskiej e-ksiazce kod pewnego programu w Pascalu

uses crt;
type tArchivo=text;
     tComponente=string;

procedure LeerElemDetectandoFin(var arch:tArchivo;var comp:tComponente;var finArch:boolean);
begin
	finArch:=eof(arch);
	if not finArch then
		readln(arch,comp);
end;

procedure PasarElemDetectandoFin(var archOrigen,archDestino:tArchivo;var comp:tComponente;var finArchOrigen:boolean);
begin
	writeln(archDestino,comp);
	LeerElemDetectandoFin(archOrigen,comp,finArchOrigen)
end;

procedure Mezcla(var aux1,aux2,arch:tArchivo);
var c1,c2:tComponente;
	finArch1,finArch2:boolean;
begin
	Reset(aux1);
	Reset(aux2);
	Rewrite(arch);
	LeerElemDetectandoFin(aux1,c1,finArch1);
	LeerElemDetectandoFin(aux2,c2,finArch2);
	while not finArch1 and not finArch2 do
		if(c1<c2)then
			PasarElemDetectandoFin(aux1,arch,c1,finArch1)
		else
			PasarElemDetectandoFin(aux2,arch,c2,finArch2);
	while not finArch1 do
		PasarElemDetectandoFin(aux1,arch,c1,finArch1);
	while not finArch2 do
		PasarElemDetectandoFin(aux2,arch,c2,finArch2);
	Close(arch);
	Close(aux1);
	Close(aux2)
end;

procedure Division(var arch,aux1,aux2:tArchivo;var esVacio2:boolean);
var valorActual,valorAnterior:tComponente;
	cambio:boolean;
begin
	Reset(arch);
	Rewrite(aux1);
	Rewrite(aux2);
	cambio:=True;
	esVacio2:=True;
	if not eof(arch)then
	begin
		Readln(arch,valorActual);
		Writeln(aux1,valorActual);
		valorAnterior:=valorActual
	end;
	while not eof(arch)do
	begin
		Readln(arch,valorActual);
		if(valorAnterior>valorActual)then
			cambio:=not cambio;
		if cambio then
			Writeln(aux1,valorActual)
		else
		begin
			Writeln(aux2,valorActual);
			esVacio2:=False;
		end;
		valorAnterior:=valorActual
	end;
	Close(arch);
	Close(aux1);
	Close(aux2)
end;

var arch,aux1,aux2:tArchivo;
	ruta,ruta1,ruta2:string;
	esVacio2:boolean;

begin
	clrscr;
	writeln('Darme ruta de archivo que quieres ordenar');
	readln(ruta);
	ruta1:=copy(ruta,1,pos('.',ruta)-1)+'_temp001.txt';
	ruta2:=copy(ruta,1,pos('.',ruta)-1)+'_temp002.txt';
	assign(arch,ruta);
	assign(aux1,ruta1);
	assign(aux2,ruta2);
	esVacio2:=False;
	while not esVacio2 do
	begin
		Division(arch,aux1,aux2,esVacio2);
		if not esVacio2 then
			Mezcla(aux1,aux2,arch);
	end;
end.

Probowalem przepisac ten kod na C++ w ten sposob

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

using namespace std;

void LeerElemDetectandoFin(fstream &arch,string &comp,bool &finArch)
{
    finArch=arch.eof();
    if(!finArch)
    {
        getline(arch,comp);
    }
}

void PasarElemDetectandoFin(fstream &archOrigen,fstream &archDestino, string &comp,bool &finArchOrigen)
{
    archDestino<<comp<<"\n";
    LeerElemDetectandoFin(archOrigen,comp,finArchOrigen);
}



void Mezcla(string ruta,fstream &aux1,fstream &aux2,fstream &arch)
{
    string c1,c2;
    string ruta1,ruta2;
    bool finArch1,finArch2;
    size_t posicion;

    posicion=ruta.find(".");
    if(posicion!=string::npos)
    {
        ruta1=ruta.substr(0,posicion)+"_temp001.txt";
        ruta2=ruta.substr(0,posicion)+"_temp002.txt";
    }

    aux1.open(ruta1.c_str(),ios::in);
    aux2.open(ruta2.c_str(),ios::in);
    arch.open(ruta.c_str(),ios::out);

    LeerElemDetectandoFin(aux1,c1,finArch1);
    LeerElemDetectandoFin(aux2,c2,finArch2);
    while(!finArch1 && !finArch2)
        if(c1<c2)
            PasarElemDetectandoFin(aux1,arch,c1,finArch1);
        else
            PasarElemDetectandoFin(aux2,arch,c2,finArch2);
    while(!finArch1)
        PasarElemDetectandoFin(aux1,arch,c1,finArch1);
    while(!finArch2)
        PasarElemDetectandoFin(aux2,arch,c2,finArch2);

    arch.close();
    aux1.close();
    aux2.close();
}

void Division(string ruta,fstream &arch, fstream &aux1,fstream &aux2,bool &esVacio2)
{
    string valorActual,valorAnterior;
    string ruta1,ruta2;
    bool cambio;
    size_t posicion;

    posicion=ruta.find(".");
    if(posicion!=string::npos)
    {
        ruta1=ruta.substr(0,posicion)+"_temp001.txt";
        ruta2=ruta.substr(0,posicion)+"_temp002.txt";
    }

    arch.open(ruta.c_str(),ios::in);
    aux1.open(ruta1.c_str(),ios::out);
    aux2.open(ruta2.c_str(),ios::out);
    cambio=true;
    esVacio2=true;
    if(!arch.eof())
    {
        getline(arch,valorActual);
        aux1<<valorActual<<"\n";
        valorAnterior=valorActual;
    }
    while(!arch.eof())
    {
        getline(arch,valorActual);
        if(valorAnterior>valorActual)
            cambio=!cambio;
        if(cambio)
            aux1<<valorActual<<"\n";
        else
        {
            aux2<<valorActual<<"\n";
            esVacio2=false;
        }
        valorAnterior=valorActual;
    }
    arch.close();
    aux1.close();
    aux2.close();

}


int main()
{
    string ruta;
    bool esVacio2=false;
    fstream arch,aux1,aux2;
    cout<<"Darme ruta de archivo que quieres ordenar\n";
    getline(cin,ruta);

    while(!esVacio2)
    {
        Division(ruta,arch,aux1,aux2,esVacio2);
        if(!esVacio2)
        {
            Mezcla(ruta,aux1,aux2,arch);
        }
    }

}

Jednak zamiast dzialac tak jak ten kod Pascalowy tworzy puste pliki

Procedury Pascalowe zamieniamy na funkcje typu void
Parametry procedur poprzedzone slowkiem var w C++ przekazujemy przez referencje
W Pascalu mamy osobna procedure do zwiazywania zmiennej plikowej z plikiem
oraz do otwierania pliku , w C++ mamy tylko funkcje otwierajaca plik wiec dodalem jeszcze dodatkowy parametr funkcji

Ciekaw jestem dlaczego kod w C++ nie dziala tak jak ten Pascalowy

Slowniczek

LeerElemDetectandoFin czytac element wykrywajac koniec
arch skrot od archivo czyli plik
comp skrot od componente czyli skladowa
finArch koniec pliku
PasarElemDetectandoFin
Gdyby chcial to tlumaczyc to pewnie wyszloby cos takiego przejsc przez element wykrywajac koniec poniewaz pisac to u nich escribir
ArchOrigen plik zrodlowy
ArchDestino plik docelowy
finArchOrigen koniec pliku zrodlowego

Mezcla tutaj scalanie
ruta sciezka
aux1 pierwszy plik pomocniczy
aux2 drugi plik pomocniczy
posicion pozycja
Division dzielenie
esVacio2 czy drugi (plik pomocniczy) jest pusty
valorActual wartosc aktualna
valorAnterior wartosc poprzednia
cambio zamiana

0

Kod w Pascalu napisany w normalnym języku wygląda tak:

uses
  Crt;

procedure ReadFileDetectEnd(var AFile: TextFile; var AComponent: String; out ADetect: Boolean);
begin
  ADetect := EoF(AFile);

  if not ADetect then
    ReadLn(AFile, AComponent);
end;

procedure GoThroughDetectEnd(var ASourceFile, ADestFile: TextFile; var AComponent: String; var ASourceEnd: Boolean);
begin
  WriteLn(ADestFile, AComponent);
  ReadFileDetectEnd(ASourceFile, AComponent, ASourceEnd);
end;

procedure MergeFile(var ATempFileA, ATempFileB, ADestFile: TextFile);
var
  CompA, CompB: String;
  EndFileA, EndFileB: Boolean;
begin
  ReWrite(ADestFile);
  Reset(ATempFileA);
  Reset(ATempFileB);
  try
    ReadFileDetectEnd(ATempFileA, CompA, EndFileA);
    ReadFileDetectEnd(ATempFileB, CompB, EndFileB);

    while not EndFileA and not EndFileB do
      if CompA < CompB then
        GoThroughDetectEnd(ATempFileA, ADestFile, CompA, EndFileA)
      else
        GoThroughDetectEnd(ATempFileB, ADestFile, CompB, EndFileB);

      while not EndFileA do
        GoThroughDetectEnd(ATempFileA, ADestFile, CompA, EndFileA);

      while not EndFileB do
        GoThroughDetectEnd(ATempFileB, ADestFile, CompB, EndFileB);
  finally
    CloseFile(ADestFile);
    CloseFile(ATempFileA);
    CloseFile(ATempFileB);
  end;
end;

procedure DivideFile(var ASourceFile, ATempFileA, ATempFileB: TextFile; var AEmptyFileB: Boolean);
var
  CurrValue, PrevValue: String;
  Swap: Boolean;
begin
  Reset(ASourceFile);
  ReWrite(ATempFileA);
  ReWrite(ATempFileB);
  try
    Swap := True;
    AEmptyFileB := True;

    if not EoF(ASourceFile) then
    begin
      ReadLn(ASourceFile, CurrValue);
      WriteLn(ATempFileA, CurrValue);

      PrevValue := CurrValue;
    end;

    while not EoF(ASourceFile) do
    begin
      ReadLn(ASourceFile, CurrValue);

      if PrevValue > CurrValue then
        Swap := not Swap;

      if Swap then
        WriteLn(ATempFileA, CurrValue)
      else
      begin
        WriteLn(ATempFileB, CurrValue);
        AEmptyFileB := False;
      end;

      PrevValue := CurrValue;
    end;
  finally
    CloseFile(ASourceFile);
    CloseFile(ATempFileA);
    CloseFile(ATempFileB);
  end;
end;

var
  SourceFile, TempFileA, TempFileB: TextFile;
  SourcePath, TempPathA, TempPathB: String;
  EmptyFileB: Boolean;
begin
  ClrScr();

  Write('Enter source file path: ');
  ReadLn(SourcePath);

  TempPathA := Copy(SourcePath, 1, Pos('.', SourcePath) - 1) + '_temp001.txt';
  TempPathB := Copy(SourcePath, 1, Pos('.', SourcePath) - 1) + '_temp002.txt';

  AssignFile(SourceFile, SourcePath);
  AssignFile(TempFileA, TempPathA);
  AssignFile(TempFileB, TempPathB);

  EmptyFileB := False;

  while not EmptyFileB do
  begin
    DivideFile(SourceFile, TempFileA, TempFileB, EmptyFileB);

    if not EmptyFileB then
      MergeFile(TempFileA, TempFileB, SourceFile);
  end;
end.

@nowy121105 – zrób to samo z kodem w C++, a ktoś na pewno pomoże.

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

using namespace std;

void ReadFileDetectEnd(fstream &AFile,string &Acomponent,bool &ADetect)
{
   ADetect=AFile.eof();
   if(!ADetect)
      getline(AFile,AComponent);
}

void GoThroughDetectEnd(fstream &ASourceFile, fstream &ADestFile,string &AComponent,bool &ASourceFile)
{
    ADestFile<<AComponent<<'\n';
    ReadFileDetectEnd(ASourceFile,AComponent,ASourceEnd);
}

void MergeFile(string ADestPath,fstream &ATempFileA,fstream &ATempFileB,fstream &ADestFile)
{
   string ATempPathA,ATempPathB;
   string CompA,CommpB;
   bool EndFileA,EndFileB;
   size_t position;
   
   position=ADestPath.find(".");
   if(position!=string::npos)
   {
      ATempPathA=ADestPath.substr(0,position)+"_temp001.txt";
      ATempPathB=ADestPath.substr(0,position)+"_temp002.txt";
   }
   
   ATempFileA.open(ATempPathA.c_str(),ios::in);
   ATempFileB.open(ATempPathB.c_str(),ios::in);
   ADestFile.open(ADestPath.c_str(),ios::out);
   
   ReadFileDetectEnd(ATempFileA,CompA,EndFileA);
   ReadFileDetectEnd(ATempFileB,CompB,EndFileB);
   
   while(!EndFileA && !EndFileB)
   {
       if(CompA<CompB)
          GoThroughDetectEnd(ATempFileA,ADestFile,CompA,EndFileA);
       else 
          GoThroughDetectEnd(ATempFileB,ADestFile,CompB,EndFileB);
       
       while(!EndFileA)
           GoThroughDetectEnd(ATempFileA,ADestFile,CompA,EndFileA);
       
       while(!EndFileB)
          GoThroughDetectEnd(ATempFileB,ADestFile,CompB,EndFileB);
   }

   ADestFile.close();
   ATempFileA.close();
   ATempFileB.close();
}


void DiviDeFile(string ASourcePath,fstream &ASourceFile,fstream &ATempFileA,fstream &ATempFileB,bool &AEmptyFileB)
{
   
   string ATempPathA,ATempPathB;
   string CurrValue,PrevValue;
   bool Swap;
   size_t position;
   
   position=ASourcePath.find(".");
   if(position!=string::npos)
   {
      ATempPathA=ASourcePath.substr(0,position)+"_temp001.txt";
      ATempPathB=ASourcePath.substr(0,position)+"_temp002.txt";
   }
   
   ATempFileA.open(ATempPathA.c_str(),ios::in);
   ATempFileB.open(ATempPathB.c_str(),ios::in);
   ASourceFile.open(ASourcePath.c_str(),ios::out);
   
   Swap=true;
   AEmptyFileB=true;
   
   if(!ASourceFile.eof())
   {
      getline(ASourceFile,CurrValue);
      ATempFileA<<CurrValue<<'\n';
      
      PrevValue=CurrValue;
   }
   
   while(!ASourceFile.eof())
   {
      getline(ASourceFile,CurrValue);

      if(PrevValue>CurrValue)
         Swap=!Swap;
      
      if(Swap)
         ATempFileA<<CurrValue<<'\n';
      else
      {
         ATempFileB<<CurrValue<<'\n';
         AEmptyFileB=false;
      }

      PrevValue=CurrValue; 
   }
       
   ADestFile.close();
   ATempFileA.close();
   ATempFileB.close();

}


int main()
{
   fstream SourceFile,TempFileA,TempFileB;
   string SourcePath;
   bool EmptyFileB;
   
   cout<<"Enter source file path:\n";
   getline(cin,SourcePath);
   
   EmptyFileB=false;
   
   while(!EmptyFileB)      
   {
      DivideFile(SourcePath,SourceFile,TempFileA,TempFileB,EmptyFileB);
      
      if(!EmptyFileB)
         MergeFile(SourcePath,TempFileA,TempFileB,SourceFile);   
   }
}

0

Wiesz co, otwórz sobie oba kody w edytorach (do Pascala użyj Lazarusa, do C++ czegoś co ma debugger), przekompiluj, postaw breakpointy tuż po podaniu ścieżek i naprzemian linijka po linijce debuguj oba programy.

Jeśli kody działają różnie to w pewnym momencie zauważysz, że przepływ sterowania jest inny. Sprawdź też czy wartości parametrów są w obu kodach takie same. Kody nie są długie, więc wiele roboty z tym nie będzie. A jeśli przepływ sterowania będzie taki sam w obu kodach to przyczyna będzie leżeć w instrukcjach dotyczących zapisu danych do pliku (bo pisałeś, że pliki są puste).

0

To moze troche inne pytanie
Jak zmodyfikowac te procedury aby dzialaly takze dla listy

Dla listy mam wstawianie w sposob uporzadkowany (ale jest zbyt wolne np dla listowej implementacji algorytmu Grahama)
Mam tez rekurencyjna wersje sortowania przez scalanie (ale mysle ze np dla listowej implementacji algorytmu Grahama wygodniejsza bedzie jednak wersja iteracyjna)

0

Nie ma sensu przerabiać kodu, tak aby dodać obsługę list – to zupełnie inny kontener, więc i kod musi być zupełnie inny, bez wszystkiego z bieżącego, co dotyczy stricte operacji na plikach.

Ewentualnie możesz zrobić w ten sposób, że listę źródłową zapiszesz do pliku, skorzystasz z bieżącego kodu (które de facto operuje na plikach), a na koniec z powrotem wczytasz gotową listę z pliku do pamięci. Dzięki temu będziesz miał jeden kod, obsługujący źródło w dwóch typach (plik oraz listę).

0

Tak wlasciwie to chcialem wzorujac sie na tym algorytmie dla plikow napisac jego listowa wersje
Zarowno do pliku jak i do listy mamy dostep sekwencyjny i stad pomysl aby wykorzystac ten algorytm do sortowania listy
Myslalem nad tym aby najpierw wkleic cialo procedur LeerElemDetectandoFin oraz PasarElemDetectandoFin
do procedur Mezcla oraz Division oraz nad dopisaniem procedury sortujacej (tutaj fragment glownego bloku programu)
Zamiast zmiennych plikowych mielibysmy wskazniki na glowe listy
Z zmiennych esVacio2 finArch mozna by zrezygnowac - zastapic porownywaniem z nil
zamiast valorActual i valorAnterior mozna dac wskazniki curr, prev
Mam rekurencyjna procedure sortujaca ale czasami wygodniejsza w uzyciu bylaby wersja iteracyjna
Twoja propozycja jest o tyle dobra ze trzeba jedynie dopisac zapisywanie i wczytywanie listy do pliku
z czym nie powinno byc problemu

Jak sie przyjrzalem tym procedurom to mam watpliwosci czy jest on poprawny
Wyglada na to ze procedura scalajaca nie uwzglednia scalania serii
Wydaje mi sie ze scala elementy tak jakby w plikach pomocniczych byla tylko jedna seria a mimo to zatrzymuje sie zwracajac poprawne dane

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