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

Błędne użycie wskaźnika, jak to naprawić?

Object Storage Arubacloud
0 głosów
281 wizyt
pytanie zadane 23 lutego 2020 w C i C++ przez matzar24 Początkujący (250 p.)

Bardzo uprzejmie proszę o pomoc.  wink  Będę wdzięczny za każdą radę!

Witam, napisałem sobie program, żeby poćwiczyć sobie używanie wskaźnika, ale coś idzie nie tak. Wyskakuje error: 0xC0000005. Według opisu z Google jest to błąd związany z błędnym użyciem wskaźnika.

Program pyta się najpierw, na ilu liczbach będą prowadzone operacje. Następnie losuje zadaną ilość liczb z przedziału od 1 do 100. (po tej operacji wyskakuje error, tylko wtedy gdy ilość liczb jest większa od 10).

Dalej następują operacje wykonujące się zadaną ilość razy bez wskaźnika oraz kolejno ze wskaźnikiem.

#include <iostream>
#include <time.h>
using namespace std;

size_t start,stop;
double czas;
int ile;


int main()
{
    int *zbior;
    zbior=new int [ile];

    cout<<"Podaj ilosc operacji: ";
    cin>>ile;

    srand(time(NULL));
    for(int i=0;i<ile;i++)
    {
        zbior[i]=rand()%100+1;
        cout<<zbior[i]<<endl;
    }

    cout<<"po tym cout sie cos psuje, 
    gdy wpisze do zmiennej liczbe wieksza od 10, np. 20, 
    pojawia sie: error 0xC0000005"<<endl;


    start=clock();
    for(int i=0;i<ile;i++)
    {
        cout<<zbior[i]<<endl;
        zbior[i]+=10;
        cout<<zbior[i]<<endl<<endl;
    }
    stop=clock();
    czas=(double)(stop-start)/CLOCKS_PER_SEC;
    cout<<"Czas wykonania bez wskaznika: "<<czas<<" sec"<<endl;

    //--------------------------------------------------------

    int *wsk=zbior;

    start=clock();
    for(int i=0;i<ile;i++)
    {
        cout<<*wsk<<endl;
        *wsk+=10;
        cout<<*wsk<<endl<<endl;
        wsk++;
    }
    stop=clock();
    czas=(double)(stop-start)/CLOCKS_PER_SEC;
    cout<<"Czas wykonania z wskaznikiem: "<<czas<<" sec"<<endl;


    delete [] zbior;

    return 0;
}

Ktoś umie pomóc? Chciałbym ten błąd rozwiązać, albo czy macie lepszy pomysł na poćwiczenie/zrozumienie przydatności wskaźnika? Dlaczego w tym przypadku czas operacji ze wskaźnikiem jest dłuższy??

Pytanie nr 2: Czemu gdy przenoszę ten fragment kodu nad funkcję główną, to nie chce się to skompilować?

int *zbior;
zbior=new int [ile];

 

2 odpowiedzi

+2 głosów
odpowiedź 23 lutego 2020 przez adrian17 Ekspert (344,860 p.)

Kod w funkcji wykonuje się linia po linii, czyli:

int ile; // poza funkcją, zmienna globalna

masz zmienną globalną której nie nadałeś wartości,

zbior=new int [ile];

alokujesz `ile` intów (czyli ile?)

cout<<"Podaj ilosc operacji: ";
cin>>ile;

A dopiero teraz dowiadujesz się, ile tak naprawdę ma być tych intów.

Także robisz rzeczy nie po kolei. To, że niepotrzebnie używasz zmienne globalne, też nie pomaga w czytelności kodu.

Pytanie nr 2: Czemu gdy przenoszę ten fragment kodu nad funkcję główną, to nie chce się to skompilować?

Bo kod wykonywalny (jak przypisywanie wartości do zmiennych) umieszcza się tylko w funkcjach; linia `zbior=cokolwiek` nie ma sensu poza funkcją, więc kompilator krzyczy.

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

W trybie minimalnych (prawie) poprawek:

#include <iostream>
#include <ctime>
#include <cstddef>

using namespace std;

std::size_t start;
std::size_t stop;
double czas;
int ile;

int main()
{
    int *zbior;

    cout << "Podaj ilosc operacji: ";
    cin >> ile;
    // Tu brakuje sprawdzenia czy dane zostały wprowadzone poprawnie.
    // Nawet takie naiwne sprawdzenie jest ok.
    if(!cin)
    {
        cerr << "Pdałeś nieprawidłowe dane!\n";
        return -1;
    }
    zbior = new(std::nothrow) int [ile];
    // Tu brakuje sprawdzenia czy alokacja się powiodła.
    // Można tak.
    if(zbior == NULL)
    {
        cerr << "Alokacja pamięci na tablicę, nie powiodła się!\n";
        return -1;
    }

    srand(time(NULL));
    for(int i = 0; i < ile; ++i)
    {
        zbior[i] = rand() % 100 + 1;
    }

    start = clock();
    for(int i = 0; i < ile; ++i)
    {
        zbior[i] += 10;
    }
    stop = clock();
    czas = static_cast<double>(stop-start) / CLOCKS_PER_SEC;
    cout << "Czas wykonania bez wskaznika: " << czas << " sec" << '\n';

    //--------------------------------------------------------

    int *wsk = zbior;

    start = clock();
    for(int i = 0; i < ile; ++i)
    {
        *wsk += 10;
        ++wsk;
    }
    stop = clock();
    czas = static_cast<double>(stop-start) / CLOCKS_PER_SEC;
    cout << "Czas wykonania z wskaznikiem: " << czas << " sec" << '\n';

    delete [] zbior;

    return 0;
}

1. Nie wczytuj nagłówka <time.h> bo dla C++ jest to <ctime>

2. Typ size_t jest w std::size_t i nagłówku <cstddef>

3. Staraj się (jeśli to możliwe), umieszczać każdą deklarację zmiennej w oddzielnej linii. To pomaga przy deklarowaniu wskaźników.

4. To co masz teraz przed funkcją main(), zostanie domyślnie zainicjowane zerem.

5. Dobrze jest sprawdzić stan strumienia po wprowadzeniu danych (stąd test if (!cin) )

6. new int[ile] może się nie powieść. Stąd powinieneś sprawdzić czy nie jest ustawiony na NULL lub nie rzucił wyjątkiem (tu przyjąłem że wyjątków nie chcesz)

7. srand/rand, mają słabą losowość no ale przyjąłem że piszesz zgodnie ze standardem przed C++11 więc dopuszczalne.

8. Rzutowanie "w stylu C", jest usilnie odradzane w C++. Zawsze stosuj rzutowanie w stylu C++. Tu static_cast<int>(...) jest odpowiednie.

9. W pętlach o ile to jest obojętne dla działania, staraj się stosować operacje pre a nie post.

10. clock(), nie oferuje obecnie dobrej rozdzielczości co do pomiaru czasu. Tu znów przyjąłem że piszesz przed C++11.

11. Jeśli chcesz nieco lepiej zmierzyć czas (z użyciem clock()), pozbądź się wyświetlania. Wpływa na wynik.

 

Podobne pytania

0 głosów
3 odpowiedzi 1,936 wizyt
pytanie zadane 5 września 2019 w C i C++ przez Vitall Początkujący (400 p.)
0 głosów
4 odpowiedzi 195 wizyt
pytanie zadane 4 października 2018 w C i C++ przez estewui Początkujący (270 p.)

92,551 zapytań

141,393 odpowiedzi

319,523 komentarzy

61,936 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!

...