• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Zmienne lokalne i globalne

Object Storage Arubacloud
0 głosów
441 wizyt
pytanie zadane 19 stycznia 2020 w C i C++ przez xZenit Użytkownik (760 p.)
edycja 19 stycznia 2020 przez xZenit

Dane jest zadanie:

Na przemian

Limit pamięci: 64 MB

Antek z Zuzią często bawią się w pisanie liczb. Na kartce zapisują na przemian liczby całkowite - raz Zuzia, raz Antek. W wyniku zabawy powstaje zazwyczaj wiele zapisanych liczbami kartek.

Zadanie

Napisz program, który:

  • wczyta ze standardowego wejścia:
    • liczbę kartek zapisanych przez dzieci,
    • liczbę elementów ciągu,
    • ciąg liczb całkowitych,
  • dla każdego zestawu danych wypisze na standardowe wyjście wczytane liczby w taki sposób, aby najpierw pojawiły się liczby zapisane przez Antka, a następnie te, które zapisała Zuzia (według kolejności występowania na wejściu).

Wejście

Pierwszy wiersz zawiera jedną liczbę całkowitą image (image), będącą liczbą zestawów danych. W kolejnych image wierszach znajdują się opisy poszczególnych zestawów danych. Każdy zestaw składa się z liczby image (image) oraz następujących po niej liczb image (imageimage), pooddzielanych pojedynczymi odstępami.

Wyjście

Program powinien wypisać image wierszy. W image-tym z nich powinien się znajdować ciąg odpowiadający image-temu zestawowi danych. Są to wczytane liczby w zmienionej kolejności - najpierw liczby, które były na wejściu na pozycjach parzystych, następnie liczby z pozycji nieparzystych.

Przykład

Dla danych wejściowych:

2 
3 5 7 2
4 2 1 4 3

poprawną odpowiedzią jest:

7 5 2
1 3 2 4

Napisałem taki kod:

#include <iostream>
using namespace std;

int main()
{
	int ile, a, n, k, p, g, z=0, t;
	int koncowa [1];

	cin>>ile;
	for (a=0; a<ile; a)
	{
		cin>>k;
		int tab[k*2];
		for (n=0; n<k; n++)
		{
			cin>>tab[n*(a+1)];
		}

		a++;
	}

	for(g=0; g<ile; g)
	{
	p=0;
	while (p<=1)
	{
	for (t=0; t<ile; t+2)
	{
		cout<<tab[t]<<endl;
	}
	p++;
	}
    g++
	}
}

Oczywiście widzę gdzie jest w nim błąd - tablica o nazwie tab została zadeklarowana lokalnie. Jednak potrzebuję jej użyć w dalszych instrukcjach, co prze obecnej (lokalnej) deklaracji jest oczywiście niemożliwe. Nie można jej zadeklarować wcześniej (poza pętlą for), gdyż dopiero w tej pętli dostarczana jest informacja o wielkości pożądanej tabeli. I tu pojawia się pytanie: czy ktoś ma może pomysł jak rozwiązać ów problem?

komentarz 19 stycznia 2020 przez tkz Nałogowiec (42,000 p.)
Dlatego jest coś takiego jak new. Poza tym musisz powtórzyć C++ od podstaw.
komentarz 19 stycznia 2020 przez xZenit Użytkownik (760 p.)
Mógłbyś rozwinąć wątek "new"?

PS. Powtórzę.
komentarz 19 stycznia 2020 przez adrian17 Ekspert (344,860 p.)

Mógłbyś rozwinąć wątek "new"?

To jest najbardziej podstawowy w C++ie sposób alokowania tablic o dowolnym rozmiarze. Musisz poczytać o dynamicznej alokacji pamięci.

Bez std::vector'a lub surowej dynamicznej alokacji z `new` ogólnie trudno pisać jakiekolwiek zadania w C++ie :/

komentarz 19 stycznia 2020 przez tkz Nałogowiec (42,000 p.)
W odpowiedziach polecili std::vector, na pewno bezpieczniejsza wersja i tego bym użył. new używasz by dynamicznie alokować pamięć, nie wiedząc o rozmiarze w compile-time.
komentarz 19 stycznia 2020 przez xZenit Użytkownik (760 p.)
Ok, dzięki "new" już ogarnąłem.

3 odpowiedzi

+1 głos
odpowiedź 19 stycznia 2020 przez mokrowski Mędrzec (155,460 p.)

To jest VLA. Taka konstrukcja nie występuje w C++. To że kompilator to obsługuje, to wyłącznie uprzejmość dostawcy: https://en.wikipedia.org/wiki/Variable-length_array

int tab[k*2];

Zapoznaj się z std::vector.

komentarz 19 stycznia 2020 przez xZenit Użytkownik (760 p.)
Ok, dzięki za informację.
+1 głos
odpowiedź 19 stycznia 2020 przez adrian17 Ekspert (344,860 p.)

Oczywiście widzę gdzie jest w nim błąd - tablica o nazwie tab została zadeklarowana lokalnie

To nie jest błąd, to normalne. Ale fakt, za głęboki ma scope. Ale ogólnie tu nie ma niczego, z czym zmienne globalne by pomogły (a często tylko przeszkadzają).

Jednak potrzebuję jej użyć w dalszych instrukcjach, co prze obecnej (lokalnej) deklaracji jest oczywiście niemożliwe. Nie można jej zadeklarować wcześniej (poza pętlą for), gdyż dopiero w tej pętli dostarczana jest informacja o wielkości pożądanej tabeli.

Nie, masz tu inny problem. Chcesz obsłużyć `ile` zestawów danych, ale najpierw robisz pętlę wczytującą wszystkie zestawy danych, a potem pętlę obsługującą te zestawy danych. To strasznie utrudnia Ci robotę, bo przez to tak naprawdę potrzebujesz kilka tablic `tab`, po jednej dla każdej kartki - więc tablica tablic. A zupełnie niepotrzebnie sobie to utrudniasz, bo przecież wystarczy zrobić jedną pętlę (zamiast dwóch) która wykonuje się `ile` razy, wczytuje ciąg liczb do pamięci i od razu go obsługuje.

A z powiązanych tematów, poczytaj o std::vector i dynamicznej alokacji pamięci.

1
komentarz 19 stycznia 2020 przez adrian17 Ekspert (344,860 p.)

A na boku, to sposób w jaki napisałeś swoje tablice jest technicznie nielegalny w C++ie, po prostu Twój kompilator na to pozwala dla kompatybilności z C:

warning: ISO C++ forbids variable length array 'tab' [-Wvla]
   13 |         int tab[k*2];
      |             ^~~

Ogólnie bardzo, bardzo w stylu C jest ten kod napisany. Czemu tak dziwnie piszesz pętle? :(

komentarz 19 stycznia 2020 przez xZenit Użytkownik (760 p.)
Wielkie dzięki za odpowiedź!
xZenit
komentarz 19 stycznia 2020 przez xZenit Użytkownik (760 p.)
Nasz nauczyciel informatyki tak wymaga, cóż można zrobić...
komentarz 19 stycznia 2020 przez adrian17 Ekspert (344,860 p.)

Nasz nauczyciel informatyki tak wymaga

:/

Jak tak się pisze, to równie dobrze mozna `for` nie używać, bo on nic nie daje...

Zamiast

int i;

for (i=0; i < 5; i) { // to `i` nic nie robi, nawet kompilator mi na to narzeka
    // rzeczy
    i++;
}

Można znacznie ładniej napisać na przykład

for (int i = 0; i < 5; i++) {
    // rzeczy
}

 

komentarz 19 stycznia 2020 przez xZenit Użytkownik (760 p.)
To wiem, robiłbym tak, gdyby nie ów siła wyższa.
komentarz 19 stycznia 2020 przez adrian17 Ekspert (344,860 p.)

...ja bym włączył ostrzeżenia kompilatora, podszedł do niego i niewinnie zapytał o co chodzi z tymi ostrzeżeniami ;)

warning: for increment expression has no effect
   10 |     for (a=0; a<ile; a)
      |                      ^
warning: for increment expression has no effect
   22 |     for(g=0; g<ile; g)
      |                     ^
warning: for increment expression has no effect
   27 |     for (t=0; t<ile; t+2)
      |                      ~^~

Szczególnie to ostatnie wygląda kompletnie bez sensu.

komentarz 19 stycznia 2020 przez xZenit Użytkownik (760 p.)
Podejdę :)
Dzięki za odpowiedzi.
0 głosów
odpowiedź 19 stycznia 2020 przez xZenit Użytkownik (760 p.)
edycja 20 stycznia 2020 przez xZenit

Poprawiłem kod:
 

#include <iostream>
using namespace std;

int main()
{
	int ile, a, n, p, k, g, z=0, t;
	int *tab;

	cin>>ile;
	int prz[ile];
	for (a=0; a<ile; a)
	{
		cin>>k;
        prz[a]=k;
		int *tab = new int[(k*2)];
		for (n=0; n<k; n++)
		{
			cin>>tab[n*(a+1)];
		}

    a++;
	}
	for (g=0; g<ile; g)
	{
        p=0;
        while (p<=1)
        {
            for (t=0; t<prz[g]; t+=2)
            {
                cout<<tab[t]<<endl;
            }
        p++;
        }
    g++;
	}
}

Nadal nie działa on poprawnie (wypisuje błędne wartości). Ma ktoś pomysł co jest źle tym razem?

Podobne pytania

+1 głos
1 odpowiedź 393 wizyt
pytanie zadane 26 czerwca 2020 w C i C++ przez Kacperek_code Obywatel (1,690 p.)
+1 głos
1 odpowiedź 4,863 wizyt
pytanie zadane 24 kwietnia 2018 w C# przez DODO Bywalec (2,950 p.)
0 głosów
2 odpowiedzi 603 wizyt

92,579 zapytań

141,429 odpowiedzi

319,657 komentarzy

61,962 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...