Wskaźnik do zmiennej typu int (wskaźnik do pierwszego elementu tablicy) przekazany jako parametr.

0

Witam mam mały problem z zadaniem ze wskaźnikami :
Napisz funkcję, której zadaniem będzie utworzenie tablicy oraz pobranie od użytkownika pewnej ilości liczb typu int i zapamiętanie ich w tablicy. Parametrem funkcji jest wskaźnik do zmiennej typu int (wskaźnik do pierwszego elementu tablicy)
Rozmiar tablicy początkowo ustalamy na 10, wczytywane liczby są z przedziału <1,100>; podanie liczby, która nie naley do przedziału, powoduje zakończenie wczytywania. Jeśli użytkownik poda więcej liczb, tablicę należy powiększyć do 20, 30, 40.... Funkcja ma zwróci wskaźnik do ostatniego elementu tablicy, albo NULL, jeliś użytkownik nie podał żadnej liczby z przedziału <1,100>. Niewypełnione elementy tablicy ustawiamy na 0.Napisz program wykorzystujący napisaną funkcję. Mój problem to sposób w jaki mogę uzyskać (wskaźnik do pierwszego elementu tablicy) Kod:
#include<iostream>
#include<time.h>
#include<stdlib.h>
using namespace std;

int *fun(int *p){
int *t;
int w=10,k=0;
t=new int[w];

do{
	cin>>*t;
		if(*t>0 && *t<=100){
		k++;
		t++;
			if(k-1==w)
			w=w+10;
	}		
}while(*t<0 && *t<100);

	if(k!=0){
		for(;k<w;k++){
		*t=0;
		t++;
		}
	p=t-k;

	return t-1;
}

else return NULL;

}

int main(){
int *wsk2;
int *wsk1=NULL;

wsk2=fun(wsk1);
cout<<wsk1<<endl; // pokaż adres pierwszego elementu tablicy;/zwraca NULL'a
cout<<wsk2<<endl; // pokaż adres ostatniego elementu tablicy;/ zwraca prawidłowy adres ostatniego elementu tablicy
system("pause");
return 0;

}

Niestety nie wiem w jaki sposób zmusić wsk1 to wskazywanie na t-k(pierwszy element tablicy)
0

Użyj malloc/realloc/free lub new/delete

0

Dopiero zaczynam programowanie ze wskaźnikami, gdzie miał bym użyć new??

0

new służy do przydzielenia pamięci.

Spik8 napisał(a):

... gdzie miał bym użyć new ...
oczywiście tam gdzie chcesz wyświetlić tablice.

0

Nie rozumiem do końca jak miałbym tego użyć, według zadanie funkcja powinna zwrócić mi tylko pierwszy o ostatni adres a później zapewne wrzucić to do fora (w main)
gdzie wsk1- pierwszy adres tablicy(p=t-w;) ,wsk2-ostatni adres (return t);

 for(;wsk1<=wsk2;{
                   cout<<*wsk1<<" ";
                   wsk1++;
}

I teraz jak użyć tego new ??
int *wsk1;
wsk1=new int;// ???
wsk2=fun(wsk1);

1

Przy użyciu new i delete, new tworzy obiekt, a delete niszczy obiekt.

Tworzenie nowej tablicy 30-elementowej:

int* Tablica = new int[30];

Niszczenie tablicy:

delete[] Tablica;

W C++ obiekt musisz ręcznie niszczyć w sytuacji, gdy przestaje być potrzebny, w przeciwnym wypadku dochodzi do wycieku pamięci.

W Twoim zadaniu chodzi o to, że jeżeli użytkownik podaje jedenastą liczbę, to należy kolejno utworzyć tablicę 20-elementową, przepisać wszystkie elementy ze starej do nowej tablicy i zniszczyć starą tablicę.

0

Sprawę z powiększeniem tablicy o 10 gdy użytkownik poda 10 znaczących liczb nie licząc zera załatwia
if(k-1==w)
w=w+10;
}

0

Dobra chyba jednak nie,po wprowadzenie więcej niż 14 elementów program się wysypuje.

0
Spik8 napisał(a):

Sprawę z powiększeniem tablicy o 10 gdy użytkownik poda 10 znaczących liczb nie licząc zera załatwia

               if(k-1==w)
                w=w+10;
        }         

Niestety, ale nie załatwia...
Jak najpierw zadeklarowałeś tablicę na w elementów, a później zmieniłeś wartość w to tablica się nie powiększy automagicznie.

0

Nie nauczysz się tak niczego, jeżeli z każdym małym zadaniem lecisz na forum:

int *fun(unsigned &count)
  {
   int value=0,*tb=0;
   for(count=0;(cin>>value)&&(1<=value)&&(value<=100);tb[count++]=value)
     {
      if(!(count%10))
        {
         int *ntb=new int[count+10];
         memcpy(ntb,tb,count*sizeof(int*)); // dla ignorantów nie umiejących skorzystać z google: for(int i=0;i<count;++i) ntb[i]=tb[i];
         delete tb[];
         tb=ntb;
        }
     }
   return tb;
  }
0

Tak wszystko fajnie itp ale jestem dopiero po drugiej lekcji ze wskaźnikami i takich pojęć jak memcpy czy sizeof jeszcze nawet nie miałem, posiedziałem trochę i skleiłem coś takiego int *fun(int &e){

int *wk;
int w=10,k=0;
wk=new int [w];
int *wsk2;

cin>>wk[0];
if(wk[0]>0 && wk[0]<101){
for(int i=1;i<w;i++){
    if(k==0){
        cin>>wk[i];
        if(wk[i]<1 || wk[i]>100)
            k++;
        if(k==0 && i+1==w){
            wsk2=new int [w];
            for(int i=0;i<w;i++){//kopia wk do wsk2;
                wsk2[i]=wk[i];
            }
            delete wk;
            w=w+10;
            wk=new int [w];

            for(int i=0;i<w;i++){ // kopia wsk2 do wk;
                wk[i]=wsk2[i];
            }
            delete wsk2;
        }
    }

    if(k!=0)
        wk[i]=0;
}
e=w;
return &wk[w-1];

}
else
return NULL;
}

int main(){
int *wsko;
int liczb;
wsko=fun(liczb);
if(wsko!=NULL){
wsko=wsko-(liczb-1);//ustawienie wskaznika na pierwszy element tablicy
for(int i=0;i<liczb;i++){
cout<<wsko[i]<<" ";

}
}
else cout<<"Brak liczb z przedzialu"<<endl;
return 0;

}

; Teraz już program się nie wysypuje i "chyba działa dobrze", nie oczekuje że ktoś napisze całość za mnie bo co to za frajda no nie ?, liczyłem na wskazanie drogi ale mniejsza z tym, teraz program zwraca ostatni adres elementu tablicy i ilosc elementów owej tablicy , a chce aby zwracał pierwszy i ostatni adres tej tablicy. Jak to zrobić?.
1
Spik8 napisał(a):

Jak to zrobić?.
Bardzo prosto ale w twoim przypadku dopiero po spełnieniu jednego z dwóch warunków:

  • Jesteś po 1002 lekcji
  • Przełamiesz swój wstręt do dokumentacji i przeczytasz o std::pair

Tak a propos. może i chcesz aby funkcja zwracała te dwie rzeczy ale z całą pewnością tego nie potrzebujesz.

0

Źle napisałem aby zwracał ostatni i pierwszy adres tablicy, bo funkcja int może zwracać przez return tylko jedną rzecz Tak?.W sumie największy problem mam z tym ( Parametrem funkcji jest wskaźnik do zmiennej typu int (wskaźnik do pierwszego elementu tablicy), i jak bym nie kombinował,jak bym tego wskaźnika nie przypisał to ten " dziad" wskaźnik nie chce ze mną współpracować.Gdy przypisaniu wskaźnik z parametru do wt(pierwszy adres tablicy) i wypisuje go przed returnem to jego adres się zgadza,ale gdy w wypisuje go w main to już lipa. Pewnie powinienem użyć & aby działać na originale, ale to mi nie pomaga.

1
Spik8 napisał(a):

... bo funkcja int może zwracać przez return tylko jedną rzecz Tak?
Nie. Funkcja zwracająca int może zwracać jeden int i tylko jeden int, natomiast funkcja zwracająca np pair<> de facto zwraca dwie składowe.

Spik8 napisał(a):

... Parametrem funkcji jest wskaźnik do zmiennej typu int (wskaźnik do pierwszego elementu tablicy), i jak bym nie kombinował,jak bym tego wskaźnika nie przypisał to ten " dziad" wskaźnik nie chce ze mną współpracować.
Nic dziwnego, jak ja ci podam swój numer telefonu (przekazanie do funkcji) to jak się nie wysilaj mojego numeru telefonu nie zmienisz.

Spik8 napisał(a):

... Pewnie powinienem użyć & aby działać na originale, ale to mi nie pomaga.
Pomaga tylko że źle użyłeś.

Obejrzyj sobie kod który podałem, przeanalizuj, a potem weź się za poprawienie swego.

0
 #include <iostream>
#include <cstring>

using namespace std;
int *fun(int &w){

    int *wk;
    int k=0;
    wk=new int [w];// tablica zrodlowa;
    int *wsk2,s=0;

    cin>>wk[0];
    if(wk[0]>0 && wk[0]<101){ // sprawdzenie czy pierwsza podana liczba miesici sie w przedziale, jesli nie to return null
    for(int i=1;i<w;i++){
        if(k==0){
            cin>>wk[i];
            if(wk[i]<1 || wk[i]>100) // jesli podana liczba jest poza przedzialem k++, przypisze 0 do pozostałych elementow
                k++,s=i;//ostatni element mieszczacy sie w przedziale
            else if(k==0 && i+1==w){// jeżeli ostatni element <w jest jest w przedziale to powieksz tablice o 10;
                wsk2=new int [w]; // tablica zapasowa
                for(int i=0;i<w;i++){//kopia wk do wsk2;
                    wsk2[i]=wk[i];
                }
                delete wk; // usuniecie tablicy zrodlowej
                w=w+10;
                wk=new int [w]; // powolanie nowej tablicy o w+10 elementach

                for(int i=0;i<w;i++){ // kopia wsk2 do wk;
                    wk[i]=wsk2[i];
                }
                delete wsk2; // usuniecie tablicy zapasowej
            }

        }

        if(k!=0)
            wk[i]=0;// przypisanie 0 do pozostalych elementow
    }
    w=wk[0]; // powinno zwracac pierwszy element tablicy, ale jak ?
    return &wk[s-1]; // zwrocenie adresu ostatniego elementu tablicy
   }
    else // jesli nie podano liczby z przedzialu zwraca null
    return NULL;
}

int main(){
    int *wsko;
   int liczb=10;
    wsko=fun(liczb);

    if(wsko!=NULL){
        cout<<liczb<<" "<<endl;//
        cout<<*wsko<<endl;
    }
    else cout<<"Brak liczb z przedzialu"<<endl;


return 0;
}

Teraz zwraca pierwszy i ostatni element tablicy dla liczb 3,5,0 zwraca 3 i 5 wszystko fajnie tylko że adres liczb to 0X7fff.... a wsko to 0x1e51014, tak więc jeżeli liczb ma być wskaźnikiem do pierwszego element powinien posiadać adres 0x1e51010 ??Twój program zwraca adres pierwszego elementu tablicy a przez parametr ilość liczb mieszczących się w przedziale, wtedy adres ostatniego zawsze można uzyskać przez *(tb+count-1);, ale chyba nie o to chodziło ??

1

Zacznij od usunięcia wycieków pamięci w swoim programie.
Po czym usuń powtarzanie się kodu (zasada DRY)
Później użyj odpowiedniego delete
No i na koniec wyeliminuj podwójne przydzielanie pamięci.

Spik8 napisał(a):

Twój program zwraca adres pierwszego elementu tablicy a przez parametr ilość liczb mieszczących się w przedziale, wtedy adres ostatniego zawsze można uzyskać przez *(tb+count-1);, ale chyba nie o to chodziło ??
Na 100% nie wiadomo o co chodziło ponieważ podałeś treść zadania swoimi słowami. Podane przeze mnie rozwiązanie jest rozwiązaniem najbliższego sensownego zadania do tego co podałeś.

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