• 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ć?

0 głosów
109 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 (319,300 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 VIP (148,200 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,052 wizyt
pytanie zadane 5 września 2019 w C i C++ przez Vitall Początkujący (400 p.)
0 głosów
4 odpowiedzi 133 wizyt
pytanie zadane 4 października 2018 w C i C++ przez estewui Początkujący (270 p.)
0 głosów
3 odpowiedzi 419 wizyt

87,894 zapytań

136,484 odpowiedzi

304,289 komentarzy

58,280 pasjonatów

Motyw:

Akcja Pajacyk

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

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...