c++ tablica dynamiczna i różne problemy...funcje i dynamiczne przypisanie rozmiaru tablicy

1

W moim programie mam zastosowaną tablicę jednowymiarową dynamiczną...tzn chciał bym żeby była dynamiczna ale właściwie to nie jest :-)
Póki wygląda to tak, to działa:

int ilosc_cyfr = 15;
int* tablica_cyfr = new int[ilosc_cyfr];

To aktualnie siedzi przed int main() więc jest globalne...ale o tym za chwilę.

Chciałbym aby rozmiar tablicy warunkowała zmienna ilosc_cyfr, ale tak żeby jej wartość
zostawała przypisana w czasie pracy programu,, czyli po tej pętli: ( to już jest w main)

for ( ilosc_cyfr = 0; kwota_w_c > 0; ilosc_cyfr++) // obliczanie ilości cyfr
		kwota_w_c = kwota_w_c / 10;

Jeśli wstawię deklarację tablicy i zmiennej ilosc_cyfr w miejsce, w którym bym chciał żeby były ( to już jest w main)...

int ilosc_cyfr;
	kwota_w_c = kwota_wszystkie_cyfry;
	for ( ilosc_cyfr = 0; kwota_w_c > 0; ilosc_cyfr++) // obliczanie ilości cyfr
		kwota_w_c = kwota_w_c / 10;

	int* tablica_cyfr = new int[ilosc_cyfr];

... to tablica nie jest widoczna w zdefiniowanych funkcjach:
screenshot-20210323230246.png

Jak zwykle proszę o wskazówki. :-)

2

To z czym masz problem przydzielaj pamięć wtedy kiedy wiesz ile potrzebujesz i to cała filozofia.
Radzę jednak zacząć od użycia gotowych kontenerów, jak zacznie działać zamieniaj na new/delete lub lepiej zrób własne (jeżeli chodzi o naukę języka).

Jeżeli chcesz skonwertować ręcznie liczbę na cyfry to:

  • wystarczy użyć tablicy char.
  • przydziel lokalną tablicę na stosie aby mieściło każdą wartość konwertowanego typu.
  • po konwersji przydziel dokładnie tyle pamięci ile potrzebujesz i wypełnij tablicę.
  • ponieważ tak czy owak trzeba będzie odwracać wynik to poprzedni punkt - jak znalazł.
0

@_13th_Dragon: > przydzielaj pamięć wtedy kiedy wiesz ile potrzebujesz >
Nie wiem ile potrzebuję, stąd tablica dynamiczna :-) Zostaje wprowadzona liczba i dopiero wiadomo ile miejsca potrzeba.
( Może czegoś nie zrozumiałem ) :-)

1
Waran3 napisał(a):

Zostaje wprowadzona liczba i dopiero wiadomo ile miejsca potrzeba.

Dokładnie ceil(log10(liczba+1)) tyle znaków zajmuje liczba w systemie dziesiętnym.
Więc jak już masz liczbę i wiesz jak obliczyć potrzebną ilość pamięci to dopiero przydzielaj.

0

@_13th_Dragon: Fajnie, że podałeś te sposoby obliczania ilości cyfr, ale ja nie z tym mam problem :-)
Chodzi o to, że funkcja zdefiniowana w programie "traci" tablicę jak ta siedzi w main.

screenshot-20210324003055.png

6

Chodzi o to, że funkcja zdefiniowana w programie "traci" tablicę jak ta siedzi w main.

Tak, bo to zmienna innej funkcji. Możesz przekazywać ją jako parametr funkcji, możesz uczynić z tego zmienną globalną, a potem dopiero w przyszłości ją inicjalizować tym int* tablica_cyfr = new int[ilosc_cyfr];.

Ogólnie, to co Ty robisz, to proszenie się o problemy z wyciekiem pamięci. Jak piszesz w C++ — a piszesz — to korzystaj z gotowych kolekcji, w tym przypadku std::vector będzie najodpowiedniejszy. Przekazuj go normalnie, jako referencję, pilnuj constów gdzie się da, zadbaj o RAIImoże nie wyłysiejesz przy debuggowaniu.

5

https://dsp.krzaq.cc/post/176/ucze-sie-cxx-kiedy-uzywac-new-i-delete/
doczytaj co to jest zakres ważności "scope" (podstawy C/C++).

0

Dostałem dużo cennych wskazówek ale póki co wcisnąłem nogę w drzwi ;-) bazując na tym co wiem.
Czyli zadeklarowałem zmienną globalną:

int ilosc_cyfr;

Zainicjalizowałem tablicę dynamiczną, metodą która w podsuniętych mi linkach jest właściwie negowana ;-)

kwota_w_c = kwota_wszystkie_cyfry;
	for ( ilosc_cyfr = 0; kwota_w_c > 0; ilosc_cyfr++) // obliczanie ilości cyfr
		kwota_w_c = kwota_w_c / 10;

	int* tablica_cyfr = new int[ilosc_cyfr];

Zadeklarowałem funkcję, podając jako parametr nazwę tablicy :

void grosze_jednosci_nascie_diesiatki_setki(int* tablica_cyfr);

W nagłówku definicji funkcji podałem również nazwę tablicy:

void grosze_jednosci_nascie_diesiatki_setki(int * tablica_cyfr)
{
	display = ""; //zerowanie zmiennej - string display.
		cout << "Ilość cyfr w  funkcji =" << licznik_cyfr_w_funkcji << "\n";

// to tylko fragment definicji funkcji

Tam gdzie funkcja jest wywoływana również wstawiłem nazwę tablicy ( bez int *):

if (wskaznik_ulamka != 0) // kwota ma część ułamkową (grosze)
			{
				grosze_jednosci_nascie_diesiatki_setki(tablica_cyfr); // grosze
				grosze_display = display;
				odmiana_groszy();
			}

Program działa, choć jak zrozumiałem trzeba go napisać inaczej, co też uczynię jak tylko ogarnę podpowiedziane mi zagadnienia. :-)
Zapomniałem jeszcze dodać, że użyłem delete, a to podobno zło wcielone, choć nie mam bladego pojęcia dlaczego. :-)

delete[] tablica_cyfr;
	return 0;
2
Waran3 napisał(a):

Dostałem dużo cennych wskazówek ale póki co wcisnąłem nogę w drzwi ;-) bazując na tym co wiem.

Ale my nie dostaliśmy żadnych na temat tego co próbujesz osiągnąć.

  • Po kiego ci tablica z cyframi na dodatek typu int
  • Czemu nie możesz użyć normalnego stringa?
  • Czemu skoro i tak potrzebujesz słownie (wyczytałem z nazw zmiennych) nie użyjesz gotowej konwersji np https://en.cppreference.com/w/cpp/string/basic_string/to_string ?
  • Po kiego w ogóle próbujesz używać new/delete? (to jest nie zalecane w c++)
  • Po kiego używasz zmienne globalne? (mogą być użyte jako stałe, nawet jako stałe wczytywane z pliku ini/xml/json/itp to już brzydkie rozwiązania)

Mam nieodparte wrażenie że próbujesz stworzyć projekt pokazujący jak nie należy podchodzić do programowania.

Poniżej przykład funkcji Słownie w delphi, zauważ że nawet nie ma potrzeby przekształcać całości na cyfry.

function InWordPL(Val:Int64):String;
var S,Sadd:String;
var I,N,N1,N2,N3:Word;
const Range:array[0..3,0..2]of String=
(
  ('','',''),
  ('tysiąc ','tysiące ','tysięcy '),
  ('milion ','miliony ','milionów '),
  ('miliard ','miliardy ','miliardów ')
);
const Digits:array[0..3,0..9]of String=
(
  ('','jeden ','dwa ','trzy ','cztery ','pięć ','sześć ','siedem ','osiem ','dziewięć '),
  ('dziesięć ','jedenaście ','dwanaście ','trzynaście ','czternaście ','piętnaście ','szesnaście ','siedemnaście ','osiemnaście ','dziewiętnaście '),
  ('','','dwadzieścia ','trzydzieści ','czterdzieści ','pięćdziesiąt ','sześćdziesiąt ','siedemdziesiąt ','osiemdziesiąt ','dziewięćdziesiąt '),
  ('','sto ','dwieście ','trzysta ','czterysta ','pięćset ','sześćset ','siedemset ','osiemset ','dziewięćset ')
);
begin
  if Val<0 then
  begin
    Result:='- ';
    Val:=-Val;
  end
  else SetLength(Result,0);
  
  if Val=0 then Result:='Zero '
  else
  begin
    I:=0;
    while Val>0 do
    begin
      N:=(Val)mod(1000);
      N1:=(Val)mod(10);
      N2:=(Val)div(10)mod(10);
      N3:=(Val)div(100)mod(10);
      Val:=(Val)div(1000);
      Sadd:=Digits[3,N3];
      if N2=1 then Sadd:=Sadd+Digits[1,N1] else Sadd:=Sadd+Digits[2,N2]+Digits[0,N1];
      if N>0 then
      begin
        if N2=1 then Sadd:=Sadd+Range[I,2]
        else if (2<=N1)and(N1<=4) then Sadd:=Sadd+Range[I,1]
        else if N1<>1 then Sadd:=Sadd+Range[I,2]
        else if (N2=0)and(N3=0) then Sadd:=Sadd+Range[I,0]
        else Sadd:=Sadd+Range[I,2];
      end;
      Inc(I);
      S:=Sadd+S;
    end;
    Result:=Result+S;
  end;
end;
0

@_13th_Dragon:

Ale my nie dostaliśmy żadnych na temat tego co próbujesz osiągnąć.
13 razy edytowałem pierwszy post, tak żeby był czytelny i zrozumiały...no ale może nie jest :-)

Po kiego ci tablica z cyframi na dodatek typu int
Tam trzymam wszystkie pojedyncze cyfry, dzięki temu wiem co, w którym miejscu i jak napisać słownie.

Czemu nie możesz użyć normalnego stringa?
używam (chyba ) :-)

Czemu skoro i tak potrzebujesz słownie (wyczytałem z nazw zmiennych) nie użyjesz gotowej konwersji np https://en.cppreference.com/w/cpp/string/basic_string/to_string ?
Po pierwsze chciałem napisać taką konwersję( w ramach nauki i ćwiczeń), po drugie jeszcze nie wiem co jest, a czego nie ma :-)

Po kiego w ogóle próbujesz używać new/delete? (to jest nie zalecane w c++)
Najpierw się dowiedziałem, że coś takiego w ogóle jest, a potem że nie należy tego stosować...właśnie w takiej kolejności :-)

Po kiego używasz zmienne globalne?
Póki co nie wiem dlaczego miałbym ich nie używać, choć ciągle natrafiam na teks w którym o tym piszą. :-)

Mam nieodparte wrażenie że próbujesz stworzyć projekt pokazujący jak nie należy podchodzić do programowania.
Hmm...chyba tak musi być, przynajmniej na początku każdej drogi. :-) Przyrzekam, że nie robię tego celowo i że każdy następny program będzie coraz lepszy. :-)
Póki co czytam te wszystkie Wasze uwagi bo to najcenniejsze co może być w fazie uczenia się.

Zamieszczam link do całego kodu, jak by coś..;-)
https://github.com/Waran3/Slownie_cpp

2
Waran3 napisał(a):

Zamieszczam link do całego kodu, jak by coś..;-)
https://github.com/Waran3/Slownie_cpp

Do wywalenia i napisania od nowa, w c++ da się napisać w 30 wierszach, bez zmiennych globalnych oraz innych dziwactw.

0

Do wywalenia i napisania od nowa, w c++ da się napisać w 30 wierszach, bez zmiennych globalnych oraz innych dziwactw.

ok:-)
ps.Mam nawet kłopot żeby zamieścić tutaj cytat :-)

2

Co tam optymalizacja - na początku programowania przy pierwszych programach napisanych samemu jest super radocha i podjarka, że coś w ogóle działa. :-) Jak autorowi nie przejdzie i się wciągnie, to za dwa - trzy lata będzie się jarał optymalizacją, czasami, beauty kodu itp.

0
PaulGilbert napisał(a):

przy pierwszych programach napisanych samemu jest super radocha i podjarka, że coś w ogóle działa. :-)

No, dokładnie tak jest :-)

0
Waran3 napisał(a):
PaulGilbert napisał(a):

przy pierwszych programach napisanych samemu jest super radocha i podjarka, że coś w ogóle działa. :-)

No, dokładnie tak jest :-)

Jak nie będziesz doprowadzał do stanu bliskiemu perfekcji (przynajmniej w twoim mniemaniu) to za rok czy dwa ta podjarka zniknie, zaś zaczniesz zauważać że byle początkujący pisze szybsze i krótsze kody, w tym momencie porzucisz programowanie bo za późno na perfekcję.

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