C++, tablice i masa błędów...

Bash, C, C++, Java, PHP, Ruby, GTK, Qt i wiele innych - wszystko tutaj.
Awatar użytkownika
Mattiah
Sędziwy Jeż
Sędziwy Jeż
Posty: 38
Rejestracja: 07 wrz 2008, 13:56
Płeć: Mężczyzna
Wersja Ubuntu: 13.04
Środowisko graficzne: Unity
Architektura: x86_64
Lokalizacja: Kielce
Kontakt:

C++, tablice i masa błędów...

Post autor: Mattiah »

Witam, jestem w trakcie nauki C++ i mam zrobic programik do dodawania/mnozenia 2 tablic. Wykonalem taki program (mnozenie nie liczy najlepiej ale teraz to niewazne) tylko ze w jednym pliku,ale chodził Teraz musze go wykonac z klasa (w sumie 3pliki) porozdzielalem wszystko ale mam problemy z uzywaniem składników klasy. Co chwile pojawiają sie nowe błędy... Jak poprawnie korzystać ze składników klasy?? Bardzo chciałbym sie tego nauczyc, licze ze ktoś mi to wytlumaczy :)

PS. Oczywiście jeżeli coś jest nie tak jak powinno to prosze zmienić po swojemu :) Z góry dzieki

Tablica.h

Kod: Zaznacz cały

#ifndef TABLICA_H
#define TABLICA_H
#include<iostream>
using namespace std;

class tablica
{
private:
int wiersz[];
int kolumna[];   //new
//int m, n, e, f, o, p, v;
//int tab1[10][10];
//int tab2[10][10];
//int tab3[10][10];
public:
tablica(int w, int k);
~tablica(void);
void uzupelnianie_tablicy1(tablica tab1[10][10]);
void uzupelnianie_tablicy2(tablica tab2[10][10]);
void wyswietlanie_tablicy(tablica tab3[10][10]);
void dodawanie_tablic(tablica tab1[10][10], tablica tab2[10][10]);
void mnozenie_tablic(tablica[10][10], tablica[10][10]);
};

#endif
Tablica.cpp

Kod: Zaznacz cały

#include "tablica.h"
#include<iostream>
using namespace std;

int m, n, e, f, o, p, v;
int i, j, x, y;
tablica tab1[10][10];
tablica tab2[10][10];
tablica tab3[10][10];

tablica::tablica(int w, int k)
{
        w = wiersz[10];
        k = kolumna[10];
}

void tablica::uzupelnianie_tablicy1(tablica)
{
for(m=0; m<i; m++)
{
        for(n=0; n<j; n++)
        {
                cout << "podaj element [" << m << "][" << n << "] tablicy pierwszej" << endl;
                cin >> tab1[m][n];
        }
}
}

void tablica::uzupelnianie_tablicy2(tablica)
{
for(e=0; e<x; e++)
{
        for(f=0; f<y; f++)
        {
                cout << "podaj element [" << e << "][" << f << "] tablicy drugiej" << endl;
                cin >> tab2[e][f];
        }
}
}

void tablica::dodawanie_tablic(tablica, tablica)
{
for(e=0,m=0,o=0; m<i; e++, m++, o++)
{
        for(f=0,n=0,p=0; n<j; f++, n++, p++)
        {
                tab3[o][p]=tab1[m][n]+tab2[e][f];
        }
}        
}

void tablica::mnozenie_tablic(tablica, tablica)
{
for(o=0; o<i; o++)
{
        for(p=0; p<j; p++)
        {
                for(v=0; v<i; v++)
                {
                        tab3[o][p] += tab1[o][v] * tab2[v][o];
                }
        }
}
}


void tablica::wyswietlanie_tablicy(tablica)
{
for(o=0; o<i; o++)
{
        for(p=0; p<j; p++)
        {
                cout << "[" << o << "][" << p << "]=" << tab3[o][p] << endl;
        }
}
}
Main.cpp

Kod: Zaznacz cały

#include "tablica.h"
#include <iostream>
using namespace std;

//int i, j, m, n, x, y, e, f, o, p, a;
int a;
int i, j, x, y;
tablica tab1[10][10];
tablica tab2[10][10];
tablica tab3[10][10];
void uzupelnianie_tablicy1(tablica);
void uzupelnianie_tablicy2(tablica);
void wyswietlanie_tablicy(tablica);
void dodawanie_tablic(tablica, tablica);
void mnozenie_tablic(tablica, tablica);
tablica * wsk;
//tablica dwuwymiarowa;

int main()
{
cout<<"__________________Oblicznia na Macierzach_______________________\n";
cout<<"|                                                              |\n";
cout<<"|Prosze wybrac opcje:                                              |\n";
cout<<"|1)Dodawanie 2 Macierzy                                              |\n";
cout<<"|2)Mnozenie 2 Macierzy                                              |\n";
cout<<"|______________________________________________________________|\n";
cin>>a;

switch(a)
{
        case 1:          //******tablica pierwsza********
                cout<<"podaj ilosc wierszy tablicy pierwszej" << endl;
                cin>>i;
                cout<<"podaj ilosc kolumn tablicy pierwszej" << endl;
                cin>>j;
                        //*******tablica druga***********
                cout<<"podaj ilosc wierszy tablicy drugiej" << endl;
                cin>>x;
                cout<<"podaj ilosc kolumn tablicy drugiej" << endl;
                cin>>y;
                
                if(i==x && j==y)
                {                
                uzupelnianie_tablicy1(tab1[10][10]);
                uzupelnianie_tablicy2(tab2[10][10]);
                dodawanie_tablic(tab1[10][10],tab2[10][10]);
                wyswietlanie_tablicy(tab3[10][10]);
                }
                else{
                cout<<"Można dodawać tylko równe tablice!!!\n";
                }
                break;
        case 2:         //*******tablica pierwsza********
                cout<<"podaj ilosc wierszy tablicy pierwszej" << endl;
                cin>>i;
                cout<<"podaj ilosc kolumn tablicy pierwszej" << endl;
                cin>>j;
                        //*******tablica druga***********
                cout<<"podaj ilosc wierszy tablicy drugiej" << endl;
                cin>>x;
                cout<<"podaj ilosc kolumn tablicy drugiej" << endl;
                cin>>y;
                
                if(i==y)
                {
                uzupelnianie_tablicy1(tab1[10][10]);
                uzupelnianie_tablicy2(tab2[10][10]);
                mnozenie_tablic(tab1[10][10],tab2[10][10]);
                wyswietlanie_tablicy(tab3[10][10]);
                }
                else{
                cout<<"Nie można pomnożyć!!!";
                }
                break;

}
}
arrevalk
Piegowaty Guziec
Piegowaty Guziec
Posty: 29
Rejestracja: 07 sie 2006, 16:51
Płeć: Mężczyzna
Wersja Ubuntu: 8.10
Środowisko graficzne: GNOME

Odp: C++, tablice i masa błędów...

Post autor: arrevalk »

No cóż po 1 proponuje poczytać sobie książkę "Thinking in C++", wydaną po polsku pod takim samym tytule. Bo szczerze mówiąc to strasznie dużo nie tyle błędów co niewiedzy widać po programie.
Po 2. Jeżeli deklarujesz klase rozdzialając definicje do pliku h i implementacje do pliku c to powinno to mniej więcej wyglądać tak:
klasa.h:

Kod: Zaznacz cały

class CKlasa{
public:
int parametr1;
int parametr2;
CKlasa(int par1, int par2);
void Wypelnij(int par1, int par2);
void Dodaj(CKlasa par1, CKlasa par2);
private:
int parametr3
};
klasa.cpp:

Kod: Zaznacz cały

CKlasa::CKlasa(int par1, int par2){
this->Wypelnij(par1, par2);
}

void CKlasa::Wypelnij(int par1, int par2){
this->parametr1 = par1;
this->parametr2 = par2;
this->parametr3 = this->parametr1 + this->parametr2;
}

void CKlasa::Dodaj(CKlasa par1, CKlasa par2){
this->parametr1 = par1.parametr1 + par2.parametr1;
this->parametr2 = par1.parametr2 + par2.parametr2;
this->parametr3 = this->parametr1 + this->parametr2;
}
Co ten kod robi? Deklarujemy tutaj klase CKlasa (C na poczatku to dobry zwyczaj sygnalizowania sobie/innym programistom ze mamy do czynienia z klasą). Klasa ta ma dwa publiczne atrybuty (parametr1, oraz parametr2), jeden konstruktor z dwoma parametrami, oraz publiczną funkcje "dodawania" dwóch obiektów(wiem można to zrobić przeciążając operator, ale przyklad ma byc prosty). Klasa posiada także jeden atrybut prywatny(dostępny jedynie dla funkcji składowych klasy). "this->" to po prostu wywołanie elementów składowych aktualnego obiektu, można z niego kożystać jedynie wewnątrz klasy.
Jak kozystać z takiej klasy? Np tak:

Kod: Zaznacz cały

CKlasa Obiekt1;
CKlasa Obiekt2;
CKlasa Obiekt3;
Obiekt1.Wypelnij(1,2);
Obiekt2.Wypelnij(3,4);
Obiekt3.Dodaj(Obiekt1, Obiekt2);
Po wykonaniu takiego kodu, atrybuty Obiekt3 będą wynośiłu odpowiednio 4,6 oraz 10
Dodatkowo próba wywołania w kodzie, np:

Kod: Zaznacz cały

Obiekt1.parametr3 = 3;
Zakończy się błędem, ze względu na fakt że parametr3 jest atybutem prywatnym. Natomiast:

Kod: Zaznacz cały

Obiekt1.parametr2 = 10
Wykona się bez problemowo.
Na tym kończe bardzo krótki kurs C++. Więcej nie będe pisał, może to Ciebie jakoś naprowadzi na prawidłowe rozwiązanie. I mam nadzieje że sam błędów nie narobiłem, całość pisana była "z palca".
P.S Powyższą książke można legalnie zassać z sieci.
Awatar użytkownika
Mattiah
Sędziwy Jeż
Sędziwy Jeż
Posty: 38
Rejestracja: 07 wrz 2008, 13:56
Płeć: Mężczyzna
Wersja Ubuntu: 13.04
Środowisko graficzne: Unity
Architektura: x86_64
Lokalizacja: Kielce
Kontakt:

Odp: C++, tablice i masa błędów...

Post autor: Mattiah »

Zrobiłem program w ten sposób:

tablica.h

Kod: Zaznacz cały

#ifndef TABLICA_H
#define TABLICA_H
#include<iostream>
using namespace std;

class tablica
{
private:
int tabl[ wiersz ][ kolumna ]; 

public:
int wiersz;
int kolumna;

tablica();
tablica(int wie, int kol);

void rozmiarTablicy();
void uzupelnianie_tablicy();
void wyswietlanie_tablicy();
void dodawanie_tablic(tablica& b, tablica& c);
//void mnozenie_tablic(tablica, tablica);

};

#endif
tablica.cpp

Kod: Zaznacz cały

#include "tablica.h"
#include<iostream>
using namespace std;

int m, n;

tablica::tablica()
{
for(m=0; m<wiersz; m++)
{
	for(n=0; n<kolumna; n++)
	{
		tabl[m][n]=0;
	}
}
}

tablica::tablica(int wie, int kol)
{
wiersz = wie;
kolumna = kol;
}


void tablica::rozmiarTablicy()
{
	cout << "Podaj ile jest wierszy w tablicy ";
	cin >> wiersz;
	
	cout << "Podaj ile jest kolumn w tablicy ";
	cin >> kolumna;
}


void tablica::uzupelnianie_tablicy()
{
for(m=0; m<wiersz; m++)
{
	for(n=0; n<kolumna; n++)
	{
		cout << "podaj element [" << m << "][" << n << "] tablicy" << endl;
		cin >> tabl[m][n];
	}
}
}


void tablica::dodawanie_tablic(tablica& b, tablica& c)
{
for(m=0; m<wiersz; m++)
{
	for(n=0; n<kolumna; n++)
	{
		tabl[ m ][ n ] = b.tabl[ m ][ n ] + c.tabl[ m ][ n ];
	}
}	
}
/*
void tablica::mnozenie_tablic(tablica tab1[m][n], tablica tab2[m][n])
{
for(o=0; o<i; o++)
{
	for(p=0; p<j; p++)
	{
		for(int v=0; v<i; v++)
		{
			tab3[o][p] += tab1[o][v] * tab2[v][o];
		}
	}
}
}
*/

void tablica::wyswietlanie_tablicy()
{
for(m=0; m<wiersz; m++)
{
	for(n=0; n<kolumna; n++)
	{
		cout << "[" << m << "][" << n << "]=" << tabl[m][n] << endl;
	}
}
}
main.cpp

Kod: Zaznacz cały

#include "tablica.h"
#include <iostream>
using namespace std;


int a;
int m, n;
tablica tab1;
tablica tab2;
tablica tab3;

int main()
{
cout<<"__________________Oblicznia na Macierzach_______________________\n";
cout<<"|							      |\n";
cout<<"|Prosze wybrac opcje:					      |\n";
cout<<"|1)Dodawanie 2 Macierzy					      |\n";
cout<<"|2)Mnozenie 2 Macierzy					      |\n";
cout<<"|______________________________________________________________|\n";
cin>>a;

switch(a)
{
	case 1:          //******tablica pierwsza********
		tab1.rozmiarTablicy();
			//*******tablica druga***********
		tab2.rozmiarTablicy();


		if(tab1.wiersz == tab2.wiersz && tab1.kolumna == tab2.kolumna)
		{		
		tab1.uzupelnianie_tablicy();
		tab2.uzupelnianie_tablicy();
		tab3.dodawanie_tablic(tab1,tab2);
		tab3.wyswietlanie_tablicy();
		}
		else{
		cout<<"Można dodawać tylko równe tablice!!!\n";
		}
		break;
	case 2:         //*******tablica pierwsza********
		cout<<"podaj ilosc wierszy tablicy pierwszej" << endl;
		
		cout<<"podaj ilosc kolumn tablicy pierwszej" << endl;
		
			//*******tablica druga***********
		cout<<"podaj ilosc wierszy tablicy drugiej" << endl;
		
		cout<<"podaj ilosc kolumn tablicy drugiej" << endl;
		
		
		
		break;

}
}
mysle że jest to sensowniejsze rozwiązanie niz poprzednio :) niestety pare błędów nadal jest:

Kod: Zaznacz cały

In file included from tablica.cpp:1:
tablica.h:9: error: ?wiersz? was not declared in this scope
tablica.h:9: error: ?kolumna? was not declared in this scope
tablica.cpp: In constructor ?tablica::tablica()?:
tablica.cpp:13: error: ?tabl? was not declared in this scope
tablica.cpp: In member function ?void tablica::uzupelnianie_tablicy()?:
tablica.cpp:42: error: ?tabl? was not declared in this scope
tablica.cpp: In member function ?void tablica::dodawanie_tablic(tablica&, tablica&)?:
tablica.cpp:54: error: ?tabl? was not declared in this scope
tablica.cpp:54: error: ?class tablica? has no member named ?tabl?
tablica.cpp:54: error: ?class tablica? has no member named ?tabl?
tablica.cpp: In member function ?void tablica::wyswietlanie_tablicy()?:
tablica.cpp:80: error: ?tabl? was not declared in this scope
In file included from main.cpp:1:
tablica.h:9: error: ?wiersz? was not declared in this scope
tablica.h:9: error: ?kolumna? was not declared in this scope
moje pytanie teraz jest nastepujące, dlaczego kompilator wypisuje ze "wiersz" i "kolumna" nie są zadeklarowane skoro SĄ w klasie ?? :/
mikolajs
Wytworny Kaczor
Wytworny Kaczor
Posty: 352
Rejestracja: 15 paź 2008, 18:30
Płeć: Mężczyzna
Wersja Ubuntu: 9.04
Środowisko graficzne: KDE Plasma

Odp: C++, tablice i masa błędów...

Post autor: mikolajs »

Kod: Zaznacz cały

int tabl[ wiersz ][ kolumna ]; 
takiego czegoś nie możesz zadeklarować jaki niby ma być rozmiar tablicy jeżeli wiersz i kolumna nie są znane. Zamiast tego zadeklaruj int** tabl. Ogólnie do tworzenia tablic o nieznanych z góry rozmiarach należy używać alokacji dynamicznej. (operator new)
Można by zadeklarować rozmiar tablic za pomocą zmiennej statycznej, która zawsze jest wcześniej inicjowana.
Awatar użytkownika
Mattiah
Sędziwy Jeż
Sędziwy Jeż
Posty: 38
Rejestracja: 07 wrz 2008, 13:56
Płeć: Mężczyzna
Wersja Ubuntu: 13.04
Środowisko graficzne: Unity
Architektura: x86_64
Lokalizacja: Kielce
Kontakt:

Odp: C++, tablice i masa błędów...

Post autor: Mattiah »

ok Dzieki, zastosowalem to "int** tabl;" zamiast "int tabl[ wiersz ][ kolumna ];" wszystko sie skompilowalo jednakże jak program dochodzi do wpisywania elementów wylatuje błąd:

Kod: Zaznacz cały

__________________Oblicznia na Macierzach_______________________
|							      |
|Prosze wybrac opcje:					      |
|1)Dodawanie 2 Macierzy					      |
|2)Mnozenie 2 Macierzy					      |
|______________________________________________________________|
1
Podaj ile jest wierszy w tablicy 2
Podaj ile jest kolumn w tablicy 2
Podaj ile jest wierszy w tablicy 2
Podaj ile jest kolumn w tablicy 2
podaj element [0][0] tablicy
Segmentation fault
a z tym "new" to jak? Wpisywałem takie cos w main.cpp

Kod: Zaznacz cały

tab1 = new tablica();
tab2 = new tablica();
tab3 = new tablica();
jednakze wylatywalo cos takiego:

Kod: Zaznacz cały

main.cpp:8: error: expected constructor, destructor, or type conversion before ?=? token
main.cpp:10: error: expected constructor, destructor, or type conversion before ?=? token
main.cpp:12: error: expected constructor, destructor, or type conversion before ?=? token
arrevalk
Piegowaty Guziec
Piegowaty Guziec
Posty: 29
Rejestracja: 07 sie 2006, 16:51
Płeć: Mężczyzna
Wersja Ubuntu: 8.10
Środowisko graficzne: GNOME

Odp: C++, tablice i masa błędów...

Post autor: arrevalk »

C++ pozwala na deklarowanie rozmiaru tablicy zmienna const, a static chyba bo taka zmienna może przyjąć inną wartość gdzieś w programie.

Kod: Zaznacz cały

const int WIERSZ = 10;
const int KOLUMNA = 20;
int tablica [WIERSZ][KOLUMNA];
Dlaczego duże litery, bo to PEWNA STAŁA a nie jakaś tam zmienna ;)
Można to też zrobić za pomocą dyrektywy #define:

Kod: Zaznacz cały

#define WIERSZ 10
#define KOLUMNA 20

/*kod kod kod kod*/
int tablica [WIERSZ][KOLUMNA];
dlaczego kompilator wypisuje ze "wiersz" i "kolumna" nie są zadeklarowane skoro SĄ w klasie ?? :/
Chodzi o kolejność w jakiej zadeklarowałeś te zmienne. Kompilator gdy "czyta" plik źródłowy przetwarza go od pierwszej do ostatniej linijki. Czyli w twoim wypadku gdy doszedł do linijki:

Kod: Zaznacz cały

int tablica[wiersz][kolumna];
i natknął się w niej na dwa symbole (wiersz, kolumna) których wcześniej nie przetworzył w danym zakresie, więc dla niego nie istnieją mimo że znajdują się w kodzie kawałek dalej. To samo dotyczy funkcji. Funkcji możesz użyć w kodzie tylko wtedy gdy zadeklarowałeś ją wcześniej (czy to w pliku nagłówkowym, czy też bezpośrednio w *.c). Dlatego bardzo często umieszcza się same nagłówki funkcji/zmienne globalne/definicje klasy w oddzielnym pliku *.h, który się załącza na początku pliku *.c który implementuje te funkcje oraz w we wszystkich innych plikach *.c w których się z tych funkcji korzysta.
A tablice dynamiczne można wykorzystać np w taki sposób:

Kod: Zaznacz cały

int **stworz_tablice(unsigned int wiersz, unsigned int kolumna){
    unsigned int i = 0;
    int **bufor = new int * [wiersz];
    for(i = 0; i < wiersz;i ++)
        bufor[i] = new  int [kolumna];
    return bufor;
}
void zniszcz_tablice(int **tablica, unsigned int wiersz, unsigned int kolumna){
    unsigned int i = 0;
    for(i = 0; i < wiersz; i++){
        delete[] tablica[i];
        tablica[i] = 0;
    }
    delete [] tablica;
    tablica = 0;
}
Przykład użycia:

Kod: Zaznacz cały

int **tablica;
    tablica = stworz_tablice(20,20);
    cout << tablica[19][19]<< "\n";
    tablica[19][19] = 200;
    cout << tablica[19][19]<< "\n";
    zniszcz_tablice(tablica,20,20);
    cout << tablica[19][19]<< "\n";
Uwaga w ostatniej linijce program zwróci SEGMENTATION FAULT. Bo program próbuje odwołać się do nieistniejącego już obiektu.
EDIT:
Heh. Jak pisałem tego posta już poprawiłeś program, ale może to coś ci pomoże.
Awatar użytkownika
Mattiah
Sędziwy Jeż
Sędziwy Jeż
Posty: 38
Rejestracja: 07 wrz 2008, 13:56
Płeć: Mężczyzna
Wersja Ubuntu: 13.04
Środowisko graficzne: Unity
Architektura: x86_64
Lokalizacja: Kielce
Kontakt:

Odp: C++, tablice i masa błędów...

Post autor: Mattiah »

:) dzieki za pomoc. Co do tego SEGMENTATION FAULT to właściwie mi sie pojawia :) i teraz jak mozna cos na to poradzic??
Bo program próbuje odwołać się do nieistniejącego już obiektu
jak to nieistniejacego??
Awatar użytkownika
Hauleth
Wytworny Kaczor
Wytworny Kaczor
Posty: 382
Rejestracja: 18 sie 2008, 17:43
Płeć: Mężczyzna
Wersja Ubuntu: inny OS
Środowisko graficzne: GNOME
Architektura: x86

Odp: C++, tablice i masa błędów...

Post autor: Hauleth »

Inaczej, do istniejącego, ale nie zawierającego nic. W ten sposób spróbuje się odwołać do danych już nie zarezerwowanych dla tego procesu i rzuca SF
Jeśli problem rozwiązany dodaj na początku tematu [SOLVED].

Biblioteka do C++ - Bust Lib: http://code.google.com/p/bust/
arrevalk
Piegowaty Guziec
Piegowaty Guziec
Posty: 29
Rejestracja: 07 sie 2006, 16:51
Płeć: Mężczyzna
Wersja Ubuntu: 8.10
Środowisko graficzne: GNOME

Odp: C++, tablice i masa błędów...

Post autor: arrevalk »

Hauleth pisze:Inaczej, do istniejącego, ale nie zawierającego nic.
A czy przypadkiem po użyciu operatora delete nie niszczymy danego obiektu?
Bo to że możemy próbować się dostać do obszaru pamięci który ten obiekt zajmowal (np poprzez indeks tablicy), nie oznacza że on istnieje(kompilator na to pozwala, ale system operacyjny blokuje takie próby, bo jest to zagrożenie dla stabilności systemu).
clansman5
Sędziwy Jeż
Sędziwy Jeż
Posty: 77
Rejestracja: 06 sty 2009, 10:59
Płeć: Mężczyzna
Wersja Ubuntu: 9.10
Środowisko graficzne: GNOME
Architektura: x86

Odp: C++, tablice i masa błędów...

Post autor: clansman5 »

Tak na mrginesie:

Nie uzywaj zmiennych globalnych (int m,n) w pliku tablica.cpp, to strasznie nie eleganckie zmienne tego typu; uzywane w petlach deklaruj jako zmienne lokalne danej funkcji.
Awatar użytkownika
Mattiah
Sędziwy Jeż
Sędziwy Jeż
Posty: 38
Rejestracja: 07 wrz 2008, 13:56
Płeć: Mężczyzna
Wersja Ubuntu: 13.04
Środowisko graficzne: Unity
Architektura: x86_64
Lokalizacja: Kielce
Kontakt:

Odp: C++, tablice i masa błędów...

Post autor: Mattiah »

Nie uzywaj zmiennych globalnych (int m,n) w pliku tablica.cpp
:) już ich tam nie ma, po poprawkach sam kompilator nalegał na ich skasowanie :)

Wracając do tego SEGMENTATION FAULT to dziekuje za przedstawienie teorii jednakże jak sobie teraz z tym poradzic??
mikolajs
Wytworny Kaczor
Wytworny Kaczor
Posty: 352
Rejestracja: 15 paź 2008, 18:30
Płeć: Mężczyzna
Wersja Ubuntu: 9.04
Środowisko graficzne: KDE Plasma

Odp: C++, tablice i masa błędów...

Post autor: mikolajs »

C++ pozwala na deklarowanie rozmiaru tablicy zmienna const, a static chyba bo taka zmienna może przyjąć inną wartość gdzieś w programie.

Kod:
const int WIERSZ = 10;
const int KOLUMNA = 20;
int tablica [WIERSZ][KOLUMNA];
Dlaczego duże litery, bo to PEWNA STAŁA a nie jakaś tam zmienna
Można to też zrobić za pomocą dyrektywy #define:

Kod:
#define WIERSZ 10
#define KOLUMNA 20

/*kod kod kod kod*/
int tablica [WIERSZ][KOLUMNA];
Cytat:
dlaczego kompilator wypisuje ze "wiersz" i "kolumna" nie są zadeklarowane skoro SĄ w klasie ?? :/
Chodzi o kolejność w jakiej zadeklarowałeś te zmienne. Kompilator gdy "czyta" plik źródłowy przetwarza go od pierwszej do ostatniej linijki. Czyli w twoim wypadku gdy doszedł do linijki:

Kod:
int tablica[wiersz][kolumna];
i natknął się w niej na dwa symbole (wiersz, kolumna) których wcześniej nie przetworzył w danym zakresie, więc dla niego nie istnieją mimo że znajdują się w kodzie kawałek dalej. To samo dotyczy funkcji
Widać, że na co dzień piszesz raczej w C. To wszystko co piszesz może być prawdą, ale poza deklaracją klasy tak jak w tym przypadku. Nie można zadeklarować niestatycznej stałej const bo nie można jej zainicjować w deklaracji klasy. Nie można inicjować tablicy niezainicjowaną zmienną, bo nie wiadomo jaki miałby rozmiar, czyli nie wiadomo jaki byłby rozmiar klasy. (da się to zrobić poza klasą, ale nie jest to dobry pomysł - zresztą zależy to od wersji kompilatora) Nie jest to więc kwestia kolejności deklaracji, choć w deklaracji klasy musi być zachowana tak jak piszesz.
Metoda z preprocesorem też nie zadziała, bo da w efekcie kod nieprawidłowy dla kompilatora.
Natomiast przy zadeklarowaniu static const int, można ustawić rozmiar tablicy, bo zmienne statyczne są inicjowane zawsze jako pierwsze, wiec wiadomo jaka będzie wartość w momencie tworzenia klasy.
arrevalk
Piegowaty Guziec
Piegowaty Guziec
Posty: 29
Rejestracja: 07 sie 2006, 16:51
Płeć: Mężczyzna
Wersja Ubuntu: 8.10
Środowisko graficzne: GNOME

Odp: C++, tablice i masa błędów...

Post autor: arrevalk »

Miło dowiedzieć się czegoś nowego;) Jestem C++ samoukiem, uczylem sie sam w domu mając za sobą jedynie Pascala wczesniej. Potem przesiadka na C (male procesory 8/16/32 bitowe), ostatnio troche kernela i portowania linuxa na maszyny embedded(znowu C) i powrót do C++. Oto moja historia ;)
A co do SEGMFAULT to chyba najprosciej to wyjasnić wten sposób:
W momencie uruchomienia programu system operacyjny przydziela mu pewien obszar pamięci. Gdy program pruóboje uzyskać dostęp do danych poza tym obszarem, system operacyjnymu na to niepozwala zgłaszając SEGMFAULT i zatrzymuje dzialanie programu.
Aby zwiększyć ilość pamięci dostępnej dla programu należy skorzystać z funkcji malloc w C lub operatora new w C++. Z tego co pamiętam system operacyjny też automatycznie zwiększa ilość pamięci przeznaczonej dla programu wrazie potrzeby.
Mam nadzieje że niczego nie pokręciłem.
mikolajs
Wytworny Kaczor
Wytworny Kaczor
Posty: 352
Rejestracja: 15 paź 2008, 18:30
Płeć: Mężczyzna
Wersja Ubuntu: 9.04
Środowisko graficzne: KDE Plasma

Odp: C++, tablice i masa błędów...

Post autor: mikolajs »

A co do SEGMFAULT to chyba najprosciej to wyjasnić wten sposób:
W momencie uruchomienia programu system operacyjny przydziela mu pewien obszar pamięci. Gdy program pruóboje uzyskać dostęp do danych poza tym obszarem, system operacyjnymu na to niepozwala zgłaszając SEGMFAULT i zatrzymuje dzialanie programu.
Aby zwiększyć ilość pamięci dostępnej dla programu należy skorzystać z funkcji malloc w C lub operatora new w C++. Z tego co pamiętam system operacyjny też automatycznie zwiększa ilość pamięci przeznaczonej dla programu wrazie potrzeby.
Mam nadzieje że niczego nie pokręciłem.
Z punktu widzenia programisty: w pamięci alokowanej dynamicznie możesz tworzyć większe struktury danych (teoretycznie aż do wyczerpania dostępnej pamięci operacyjnej), ale za to musisz pamiętać o jej zwolnieniu.
Wszelkie duże struktury danych i takie których rozmiarów z góry nie znasz musisz tworzyć dynamicznie (new).
Awatar użytkownika
Mattiah
Sędziwy Jeż
Sędziwy Jeż
Posty: 38
Rejestracja: 07 wrz 2008, 13:56
Płeć: Mężczyzna
Wersja Ubuntu: 13.04
Środowisko graficzne: Unity
Architektura: x86_64
Lokalizacja: Kielce
Kontakt:

Odp: C++, tablice i masa błędów...

Post autor: Mattiah »

zrobiłem tak:

Kod: Zaznacz cały

tablica tab1;
tab1 = new tablica;
tablica tab2;
tab2 = new tablica;
tablica tab3;
tab3 = new tablica;
i taki jest efekt:

Kod: Zaznacz cały

main.cpp:8: error: expected constructor, destructor, or type conversion before ?=? token
main.cpp:10: error: expected constructor, destructor, or type conversion before ?=? token
main.cpp:12: error: expected constructor, destructor, or type conversion before ?=? token
doradzono mi takie cos:

Kod: Zaznacz cały

tablica* tab1 = new tablica;
i zastosowałem (nie wiem czy dobrze)

Kod: Zaznacz cały

tablica tab1;
tablica* tab1 = new tablica;
tablica tab2;
tablica* tab2 = new tablica;
tablica tab3;
tablica* tab3 = new tablica;
i teraz pisze ze jest za duzo deklaracji

Kod: Zaznacz cały

main.cpp:8: error: conflicting declaration ?tablica* tab1?
main.cpp:7: error: ?tab1? has a previous declaration as ?tablica tab1?
main.cpp:10: error: conflicting declaration ?tablica* tab2?
main.cpp:9: error: ?tab2? has a previous declaration as ?tablica tab2?
main.cpp:12: error: conflicting declaration ?tablica* tab3?
main.cpp:11: error: ?tab3? has a previous declaration as ?tablica tab3?
no i ok bo faktycznie tak jest, ale jak usune np.

Kod: Zaznacz cały

tablica tab1;
to zaraz wylatują błedy o deklaracje, prosze o pomoc.
Awatar użytkownika
el.pescado
Zakręcona Traszka
Zakręcona Traszka
Posty: 734
Rejestracja: 26 maja 2005, 11:43
Płeć: Mężczyzna
Wersja Ubuntu: inny OS
Środowisko graficzne: GNOME
Architektura: x86
Kontakt:

Odp: C++, tablice i masa błędów...

Post autor: el.pescado »

@Mattiah, polecałbym zakup dobrej książki (Grębosz, Eckel). Nauka czegoś tak przekombinowanego jak C++ "na ślepo" to katorga.

W skrócie - w C++ zmienne mogą być tworzone na stosie i na stercie. W przypadku zmiennych na stercie, trzeba mieć wskaźnik do tej zmiennej. Wskaźnik to jest zmienna, która pamięta adres innej zmiennej. Zmienne na stosie tworzy się po prostu deklarując je:

Kod: Zaznacz cały

tablica tab1;
Zmienne na stercie tworzy się najpierw deklarując wskaźnik odpowiedniego typu, a następnie przydzielając mu nową pamięć za pomocą operatora new:

Kod: Zaznacz cały

tablica *tab1;
tab1 = new tablica();
Tak więc, przykład

Kod: Zaznacz cały

tab1 = new tablica;
jest błędny, gdyż do zmiennej typu tablica chcesz przypisać wskaźnik do typu tablica


Przykład

Kod: Zaznacz cały

tablica tab1;
tablica* tab1 = new tablica;
jest błędny, gdyż najpierw deklarujesz zmienną o nazwie tab1, która jest typu tablica, a następnie deklarujesz drugą zmienną o tej nazwie, tym razem typu wskaźnik na obiekt typu tablica.

Wskaźnik, to nie obiekt - przechowuje tylko adres obiektu. Żeby dostać się do wskazywanego obiektu, trzeba użyć operatora *:

Kod: Zaznacz cały

int a = 5;
int *p = new int;
// p = 7; // <- błąd
*p = 7;
W przypadku klas i struktur, zamiast pisać

Kod: Zaznacz cały

(*obiekt).cośtam
można w skrócie

Kod: Zaznacz cały

obiekt->cośtam
ODPOWIEDZ

Wróć do „Programowanie”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 6 gości