Problem z programem w Pascalu

0
program zadanie_domowe; 

uses 
  Crt; 

var 
  dane: text; 
  a, b, c: integer; 
  v, pp: real; 
  figura: string; 

begin 
  assign(dane, 'dane.txt'); 
  reset(dane); 
  readln(dane, figura); 
  readln(dane, a); 
  readln(dane, b); 
  readln(dane, c); 
  Close(dane); 

  if figura = 'walec' then 

    begin 
      v:= 3.14*(b*b)*a; 
      pp:= 2*3.14*b*(b+a); 

      writeln('Dane walca to: '); 
      writeln('- wysokość: ', a); 
      writeln('- promień podstawy: ', b); 
      writeln('=========================================='); 
      writeln('Objętość walca wynosi: ', v); 
      writeln('=========================================='); 
      writeln; 
      writeln('=========================================='); 
      writeln('Pole powierzchni walca wynosi: ', pp); 
      writeln('=========================================='); 
    end; 

  readkey; 

end.
walec 
6 
2 

UWAGA! Dane wpisujemy w postaci: 
NAZWA FIGURY 
WYSOKOŚĆ 
PROMIEŃ PODSTAWY

Uruchomiony program wyświetla konsolę, która w tym samym momencie znika. Kompilator nie widzi błędów w kodzie. Mógłby ktoś podać przyczynę niepoprawnego działania programu?

2

Mógłby ktoś podać przyczynę niepoprawnego działania programu?

Kompilator mści się za nieumiejętność użycia debuggera.

0

@buczuch
W przykładowym pliku jaki pokazałeś nie ma danej c, którą próbujesz odczytać.

0

Dodanie wartości dla c nic nie zmieniło. Nie była ona wymagana w obliczeniach, więc nawet gdyby program uznał ją za 0 nic by się nie stało. Poczytam o debuggerze, po prawdzie to nie korzystałem nigdy z tego - jestem absolutnym nowicjuszem w dziedzinie programowania. Gdyby ktoś wskazał problem nim może sam go kiedyś odnajdę byłbym wdzięczny. Zadanie powinienem mieć na jutro.

0

wypisz sobie wartość zmiennej figura przed sprawdzeniem warunku.

0

Wartość program miał odczytywać z pliku dane.txt. Jest ona podana w pierwszej linii pliku z danymi. Dodanie jej dodatkowo w kodzie (figura:= 'walec';) przed IF'em nic nie zmieniło. Modyfikacja programu, tak aby nie korzystał z pliku dane.txt (co jednak jest ideą zadania) i dodanie wartości bezpośrednio w kodzie sprawiła iż program uruchomił się, jednak obliczone przez niego wartości były niepoprawne. Najpierw jednak zanim zajmę się obliczeniami muszę coś zrobić, aby program korzystając z załączonego pliku z danymi rozpoznawał figurę (1 z 3 (każda ma swój plik z danymi)) i liczył jej pole powierzchni i objętość.

0

Gdyby ktoś wskazał problem nim może sam go kiedyś odnajdę

Czyli za wszelką cenę NIE CHCESZ się nauczyć programować?

Poprawa kodu to podstawowa czynność, jak już mówiłem debugger ułatwia to zadanie, więc jakbyś miał komponent TBrain to byś poszedł na google poszukać jak tego użyć.

wypisz sobie wartość zmiennej figura przed sprawdzeniem warunku.

Kolejny co debuggera nie umie użyć #.#

Jeżeli liczysz na pomoc, to użyj debuggera i jeżeli nie będziesz w stanie samemu zlokalizować błędu to podaj jego kod, call stack, stany zmiennych itp. to wtedy będziemy wiedzieć co jest nie tak.

0

Nie jestem w stanie przyswoić całej wiedzy dziś wieczór. Na jutro potrzebuję gotowy program. Dopiszę do kodu pozostałe figury i pokaże niedokończony program nauczycielowi, a od jutra zaczynam edukację na temat wymienionego debuggera i pewnie innych rzeczy.

0
buczuch napisał(a):

Dodanie wartości dla c nic nie zmieniło. Nie była ona wymagana w obliczeniach, więc nawet gdyby program uznał ją za 0 nic by się nie stało.

Jesteś newbie. Nie kompromituj się już.
Jeżeli w pliku nie było wartości c to wyskoczył runtime error przy próbie wykonania readln(dane, c); - reszta programu się nie wykona dlatego okno konsoli momentalnie znika.

0

Przede wszystkim:

assign(dane, 'dane.txt'); 
reset(dane); 
readln(dane, figura); 
readln(dane, a); 
readln(dane, b); 
readln(dane, c); 
Close(dane);

wypadałoby zabezpieczyć wczytywanie danych przed brakiem jakiejś linii w pliku; Nie wiem dlaczego korzystasz z plików tekstowych, ale niech już będzie; Za obsługę plików typowanych nauczyciel nie powinien Cię opiepszyć, których zastosowanie było by bardziej wskazane;

W każdym razie musisz podczas odczytywania danych z pliku uważać na to, czy nie odczytałeś przypadkiem wszystkich danych z pliku i odpowiednio zareagować; Możesz do tego celu skorzystać z funkcji EoF i pętli oraz macierzy (zamiast a, b i c);

Moja propozycja jest taka:

program Fgr;
uses
  Crt;
const
  PI = 3.14;
  { WALEC }
  ROLLER_RADIUS = 0;
  ROLLER_HEIGHT = 1;
var
  { DANE FIGURY }
  fFigureData: Text;
  sFigureName: String;
  aFigureProps: array of Word;
var
  { WYNIKI }
  rBase, rVolume: Real;
begin
  ClrScr;
  SetLength(aFigureProps, 0);

  Assign(fFigureData, 'C:\Dane.txt');
  Reset(fFigureData);

  if not EoF(fFigureData) then
    begin
      { NAZWA FIGURY }
      ReadLn(fFigureData, sFigureName);

      { DANE POTRZEBNE DO OBLICZEN }
      while not EoF(fFigureData) do
        begin
          SetLength(aFigureProps, Length(aFigureProps) + 1);
          ReadLn(fFigureData, aFigureProps[High(aFigureProps)]);
        end;

      { ROZPOZNANIE FIGURY }
      if sFigureName = 'walec' then
        if Length(aFigureProps) >= 2 then
          begin
            { OBLICZENIA }
            rBase := PI * Sqr(aFigureProps[ROLLER_RADIUS]);
            rVolume := rBase * aFigureProps[ROLLER_HEIGHT];

            { WYSWIETLENIE WYNIKSOW }
            WriteLn('Walec - obliczenia:'#10);
            WriteLn('Pole podstawy: ', rBase:5:2);
            Write('Objętość: ', rVolume:5:2);
          end
        else
          Write('Zbyt mało danych do obliczeń!');
    end
  else
    Write('Plik jest pusty!');

  Close(fFigureData);
  ReadLn;
end.

Ten kod w sumie niczym się nie różni od Twojego, ale zabezpieczone zostaje wprowadzanie danych do zmiennych, a także wykorzystana zostaje macierz na liczby (oraz stałe określające indeks elementu w macierzy); Dzięki temu jeśli plik jest pusty lub posiada zbyt mało danych do obliczeń - nie wyłączy się z ExitCode, a w zamian wyświetli stosowny komunikat i poczeka na reakcję użytkownika (tutaj: wciśnięcie klawisza Enter);

To tylko przykład zabezpieczeń, które można w tej sytuacji zrobić, ale więcej czasu nie mam żeby przysiąść i wymyślić coś sensowniejszego; Nad innym rozwiązaniem popracuj sam;

0
pelsta napisał(a):
buczuch napisał(a):

Dodanie wartości dla c nic nie zmieniło. Nie była ona wymagana w obliczeniach, więc nawet gdyby program uznał ją za 0 nic by się nie stało.

Jesteś newbie. Nie kompromituj się już.
Jeżeli w pliku nie było wartości c to wyskoczył runtime error przy próbie wykonania readln(dane, c); - reszta programu się nie wykona dlatego okno konsoli momentalnie znika.

Tak jestem newbie. Każdy kiedyś był. Prośby o pomoc nie uważam za kompromitację. Co prawda nie wiem jak program zachowa się gdy miał pobrać wartość z pliku i jej nie napotkał. Jednak bez pobierania jakichkolwiek wartości z innych plików w przypadku, gdy ma wyświetlić zmienną, której nie przypisaliśmy wartości wydaje mi się, że nadaje jej 0. Chyba, że tak nie jest to proszę mnie naprostować.

Nie student. ;) Jestem w technikum i właściwie to niedawno zaczęliśmy jakiekolwiek programowanie. Absolutne początki: obliczenia, write, read, pętle, i ostatnio właśnie odczyt z plików tekstowych. Ostatecznie działający kod wygląda tak:

program zadanie_domowe;

uses
  Crt;

var
  dane, wynik: text;
  a, b, c: integer;
  v, pp: real;
  figura: string;

begin
  assign(dane, 'dane.txt');
  rewrite(dane);
  readln(dane, figura);
  readln(dane, a);
  readln(dane, b);
  readln(dane, c);

  assign(wynik, 'wynik.txt');
  rewrite(wynik);

  if figura = 'walec' then
    begin
      v:= PI*(b*b)*a;
      pp:= 2*PI*b*(b+a);

      writeln('Dane walca to: ');
      writeln('- wysokość: ', a);
      writeln('- promień podstawy: ', b);
      writeln;
      writeln('==========================================');
      writeln('Objętość walca wynosi: ', v);
      writeln('==========================================');
      writeln;
      writeln('==========================================');
      writeln('Pole powierzchni walca wynosi: ', pp);
      writeln('==========================================');
    end;

  if figura = 'prostopadloscian' then
    begin
      v:= a*b*c;
      pp:= 2*(b*c)+2*(a*c)*2*(a*b);

      writeln('Dane prostopadloscianu to: ');
      writeln('- wysokość: ', a);
      writeln('- podstawa - bok a: ', b);
      writeln('- podstawa - bok b: ', c);
      writeln;
      writeln('==========================================');
      writeln('Objętość prostopadłościanu wynosi: ', v);
      writeln('==========================================');
      writeln;
      writeln('==========================================');
      writeln('Pole powierzchni prostopadłościanu wynosi: ', pp);
      writeln('==========================================');
    end;

  if figura = 'stozek' then
    begin
      v:= 1/3*PI*(b*b)*a;
      pp:= PI*b*(b*c);

      writeln('Dane stozka to: ');
      writeln('- wysokość: ', a);
      writeln('- promień podstawy: ', b);
      writeln('- tworząca stożka: ', c);
      writeln;
      writeln('==========================================');
      writeln('Objętość stożka wynosi: ', v);
      writeln('==========================================');
      writeln;
      writeln('==========================================');
      writeln('Pole powierzchni stożka wynosi: ', pp);
      writeln('==========================================');
    end;

  writeln(wynik,v);
  writeln(wynik,pp);

  Close(dane);
  Close(wynik);
  readkey;
end.
0

Wyjaśniłem już jak, program się zachowa.
Nie liczyłbym na to, że każdy kompilator zawsze nada wartości początkowe zerowe zmiennym.
Bezpieczniej jest założyć, że tylko zarezerwuje miejsce w pamięci i wyzerować je samemu.

0
_13th_Dragon napisał(a)

A co będzie jak w pliku będą trzy wiersze (dosłownie): walec; radius; wysokość ? Mam taką generalną radę, jak nie chce ci się obsługiwać wszystkich przypadków to dawaj odpowiedzi fragmentaryczne - fragment kodu.

Jak to nie chce? Wystarczy chyba, że przedstawiłem sposób zabezpieczenia wczytywania przed mniejszą ilością linii niż jest to wymagane do obliczeń; Z Twojego komentarza można śmiało wywnioskować, że miałem podać gotowe rozwiązanie (tzw. gotowca); Dlaczego to ja mam myśleć o wszystkich zabezpieczeniach? Czy to mój program? Dla mnie on jest? Ja rozumiem, że jak już podawać jakieś rozwiązanie to opisać jego wszystkie aspekty, jednak robiąc to odbieram autorowi wątku całą przyjemność główkowania i kodzenia; Może tak by wypadało...? Nie mam zdania; Jednak jeśli autorowi programu zależy na jego ukończeniu to myślę, że łaski nie zrobi jak coś sam doda do mojego programu, lub napisze swój podpatrując sposoby z mojego kodu;

Co prawda mój algorytm nie jest idealny i na pewno można go zrobić prościej i szybciej, ale nie miałem zbyt wiele czasu i podałem tylko częściowe rozwiązanie (o które de facto @_13th_Dragon poprosiłeś w komentarzu); Jak by na to nie popatrzyć - fragment zabezpieczeń jest - resztę banalnie doinstalować do kodu;

Rozumiem, że nie zostało wykonane sprawdzenie istnienia pliku z danymi, ale chyba nie problem dodać jeden warunek; To samo tyczy się konwersji danych wejściowych (prawdopodobnych danych liczbowych);

No nic, nie czas się kłócić; Jeśli komukolwiek na tym zależy - podam pełne rozwiązanie; Dodam jeszcze informację, że wykorzystując przedstawiony przeze mnie kod i nieznacznie go modyfikując można śmiało obsłużyć wiele figur; Wystarczy zmienić trochę warunek sprawdzający nazwę figury i dodać kolejne warunki dla innych figur; Reszta pozostaje bez zmian; Oczywiście można dodać dodatkowe stałe (dla walca ROLLER_RADIUS oraz ROLLER_HEIGHT) określające indeks elementu w macierzy dla innych figur, ale można to zrobić ręcznie bez ich użycia; Kwestia gustu i oszczędności pamięci; Jeśli ktoś będzie chciał - z chęcią pokażę w jaki sposób dokonać takowych zmian;


Na prośbę @_13th_Dragon (No to przedstawiaj fragmenty, odpowiedzialne za to lub tamto. Jak już podajesz całość to podaj CAŁOŚĆ.) przedstawiam całość - komplet różnych zabezpieczeń (pewnie nie wszystkich, ale co tam...); Obsługę pliku umieściłbym w bloku try .. finally .. end, ale mam z nim problem pod FPC 2.6.0; Zamieniłem także słowa Figure na Block - to bryły, nie figury... Oto kod:

program Blocks;
uses
  Crt,
  SysUtils;
const
  PI = 3.14;
const
  { WALEC }
  ROLLER_RADIUS = 0;
  ROLLER_HEIGHT = 1;
const
  { PROSTOPADLOSCIAN }
  CUBOID_BASE_WIDTH  = 0;
  CUBOID_BASE_LENGTH = 1;
  CUBOID_HEIGHT      = 2;
const
  { STOZEK }
  CONE_RADIUS  = 0;
  CONE_HEIGHT  = 1;
var
  { DANE BRYLY }
  fBlockData: Text;
  sInputFileName, sBlockName, sNumber: String;
  aBlockProps: array of Integer;
  iNumber: LongInt;
var
  { WYNIKI }
  rBase, rSurface, rVolume, rForming: Real;
begin
  ClrScr;
  sInputFileName := 'C:\Dane.txt';  

  { ISTNIENIE PLIKU }
  if not FileExists(sInputFileName) then
    begin
      Write('Plik "', sInputFileName, '" nie istnieje!');
      ReadLn;
      Halt;
    end;

  { ODCZYT DANYCH }
  Assign(fBlockData, sInputFileName);
  Reset(fBlockData);
  SetLength(aBlockProps, 0);

  if not EoF(fBlockData) then
    begin
      { NAZWA FIGURY }
      ReadLn(fBlockData, sBlockName);
      sBlockName := UpperCase(sBlockName);

      { DANE POTRZEBNE DO OBLICZEN }
      while not EoF(fBlockData) do
        begin
          ReadLn(fBlockData, sNumber);
          SetLength(aBlockProps, Length(aBlockProps) + 1);

          if TryStrToInt(sNumber, iNumber) and (iNumber > 0) then
            aBlockProps[High(aBlockProps)] := iNumber
          else
            begin
              Write('Wczytano niewlasciwa wartosc!');
              ReadLn;
              Halt;
            end;
        end;

      { WALEC }
      if sBlockName = 'WALEC' then
        begin
          if Length(aBlockProps) >= 2 then
            begin
              { OBLICZENIA }
              rBase := PI * Sqr(aBlockProps[ROLLER_RADIUS]);
              rSurface := rBase * 2 + 2 * PI * Sqr(aBlockProps[ROLLER_HEIGHT]);
              rVolume := rBase * aBlockProps[ROLLER_HEIGHT];
              { WYNIKI }
              WriteLn('Walec - obliczenia'#10);
              WriteLn('Promien podstawy: ', aBlockProps[ROLLER_RADIUS]);
              WriteLn('Wysokosc:         ', aBlockProps[ROLLER_HEIGHT]);
              WriteLn('Pole powierzchni: ', rSurface:5:2);
              Write('Objetosc:         ', rVolume:5:2);
            end
          else
            Write('Zbyt malo danych do obliczen dla walca!');
        end
      else
        { PROSTOPADLOSCIAN }
        if sBlockName = 'PROSTOPADLOSCIAN' then
          begin
            if Length(aBlockProps) >= 3 then
              begin
                { OBLICZENIA }
                rBase := aBlockProps[CUBOID_BASE_WIDTH] *
                         aBlockProps[CUBOID_BASE_LENGTH];
                rSurface := rBase * 2 + 2 * aBlockProps[CUBOID_BASE_WIDTH] *
                            aBlockProps[CUBOID_HEIGHT] + 2 *
                            aBlockProps[CUBOID_BASE_LENGTH] *
                            aBlockProps[CUBOID_HEIGHT];
                rVolume := rBase * aBlockProps[CUBOID_HEIGHT];
                { WYNIKI }
                WriteLn('Prostopadloscian - obliczenia'#10);
                WriteLn('Szerokosc podstawy: ', aBlockProps[CUBOID_BASE_WIDTH]);
                WriteLn('Dlugosc podstawy:   ', aBlockProps[CUBOID_BASE_LENGTH]);
                WriteLn('Wysokosc bryly:     ', aBlockProps[CUBOID_HEIGHT]);
                WriteLn('Pole powierzchni:   ', rSurface:5:2);
                Write('Objetosc:           ', rVolume:5:2);
              end
            else
              Write('Zbyt malo danych do obliczen dla prostopadloscianu!');
            end
          else
            { STOZEK }
            if sBlockName = 'STOZEK' then
              begin
                if Length(aBlockProps) >= 2 then
                  begin
                    { OBLICZENIA }
                    rBase := PI * Sqr(aBlockProps[CONE_RADIUS]);
                    rForming := Sqrt(Sqr(aBlockProps[CONE_RADIUS]) +
                                Sqr(aBlockProps[CONE_HEIGHT]));
                    rSurface := rBase + PI * aBlockProps[CONE_RADIUS] * rForming;
                    rVolume := rBase * aBlockProps[CONE_HEIGHT] / 3;
                    { WYNIKI }
                    WriteLn('Stozek - obliczenia'#10);
                    WriteLn('Promien podstawy: ', aBlockProps[CONE_RADIUS]);
                    WriteLn('Wysokosc:         ', aBlockProps[CONE_HEIGHT]);
                    WriteLn('Tworzaca:         ', rForming:5:2);
                    WriteLn('Pole powierzchni: ', rSurface:5:2);
                    Write('Objetosc:         ', rVolume:5:2);
                  end
                else
                  Write('Zbyt malo danych do obliczen dla stozka!');
              end
            else
              Write('Brak obslugi bryly o nazwie "', sBlockName, '" !');
    end
  else
    Write('Plik jest pusty!');

  Close(fBlockData);
  ReadLn;
end.

Nie jest doskonały, ale cóż... Działa bez zarzutu, zabezpieczenia spełniają swoje zadanie bardzo dobrze; Można przerobić ten kod na bardziej proceduralny - jeśli trzeba, autor wątku będzie miał zajęcie;

@buczuch - obejrzyj kod - mam nadzieję, że Ci się przyda;

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