C++ frågor
-
- Inlägg: 1394
- Blev medlem: 29 januari 2011, 21:06:30
- Ort: Lapplandet
Re: C++ frågor
Jo private är det mest lämpliga. Då är de skyddade från (o)avsiktliga ändringar då bara klassfunktionerna kan komma åt dem.
Att designa en bra inkapsling utan att överkomplicera programstrukturen kan vara knepigt men en bra grundregel är; Om programmet kan krascha eller göra dåliga saker om variabeln ändras utifrån använd private (eller protected vid behov)
Att designa en bra inkapsling utan att överkomplicera programstrukturen kan vara knepigt men en bra grundregel är; Om programmet kan krascha eller göra dåliga saker om variabeln ändras utifrån använd private (eller protected vid behov)
Re: C++ frågor
Ok men då går det inte deklarera static under private: ?
static double allocbuf[STACKSIZEMAX];
static double* stackTopPointer;
class StackDouble {
public:
StackDouble(int);
bool allocdouble();
void push(double);
double pop(void);
void testit(double*);
private:
int stackSize;
};
Sedan en annan fråga:
Från main vill jag anropa så här...
till funktionen....
Det jag önskar är att i funktionen extrahera storleken hos v
för att därigenom deklarera en buffert allocbuf[2] i klassen.
Eller kanske helt enkelt kopiera v till allocbuf. Jag är ute efter att
komma ifrån deklarationen
static double allocbuf[STACKSIZEMAX];
jag vill sätta storleken på allocbuf från main.
Är detta möjligt eller omöjligt?
Jag ser inga andra möjligheter att få till en dynamiskt valbar storlek på allocbuf.
static double allocbuf[STACKSIZEMAX];
static double* stackTopPointer;
class StackDouble {
public:
StackDouble(int);
bool allocdouble();
void push(double);
double pop(void);
void testit(double*);
private:
int stackSize;
};
Sedan en annan fråga:
Från main vill jag anropa så här...
Kod: Markera allt
double v[2];
v[0] = 2.5;
v[1] = 3.5;
stackDouble_000.testit(v);
Kod: Markera allt
void StackDouble::testit(double* p){
cout << *(p) << NEWLINE;
cout << *(p+1) << NEWLINE;
}
för att därigenom deklarera en buffert allocbuf[2] i klassen.
Eller kanske helt enkelt kopiera v till allocbuf. Jag är ute efter att
komma ifrån deklarationen
static double allocbuf[STACKSIZEMAX];
jag vill sätta storleken på allocbuf från main.
Är detta möjligt eller omöjligt?
Jag ser inga andra möjligheter att få till en dynamiskt valbar storlek på allocbuf.
Re: C++ frågor
Jag hade med #include <vector> för att testa med nån size grej men
då blev det massa gula varnings-symboler vid varje funktions-start
så jag tänkte att det är nog inget bra?
då blev det massa gula varnings-symboler vid varje funktions-start
så jag tänkte att det är nog inget bra?
Re: C++ frågor
Nu läste jag det här...
tror kommer bli den största stacken av de stack-objekt som skapas.
Varje objekt kommer om jag förstått det hela riktigt att ha en allocbuf[STACKSIZEMAX]
som låser det minnet. Tänkte mig att det är mindre bra på en Arduino med ont om minne.
Det kanske är bättre att låta bli och så helt enkelt sätta STACKSIZEMAX till det värde jag1) std::vector is a sequence container that encapsulates dynamic size arrays.
2) std::pmr::vector is an alias template that uses a polymorphic allocator
The storage of the vector is handled automatically, being expanded and contracted as needed. Vectors usually occupy more space than static arrays, because more memory is allocated to handle future growth.
tror kommer bli den största stacken av de stack-objekt som skapas.
Varje objekt kommer om jag förstått det hela riktigt att ha en allocbuf[STACKSIZEMAX]
som låser det minnet. Tänkte mig att det är mindre bra på en Arduino med ont om minne.
-
- Inlägg: 1394
- Blev medlem: 29 januari 2011, 21:06:30
- Ort: Lapplandet
Re: C++ frågor
Jo. Men först måste du nog förklara vad du vill göra. Ska varje StackDouble-instans ha sin egen stack eller ska de dela på samma?Ok men då går det inte deklarera static under private: ?
Standardcontainers, vector, list, map, etc, bör man nog undvika på plattformar med begränsat heap-minne.
Angående storlek så hade jag personligen valt templates istället för defines. Då kan man återanvända koden istället för att vara låst till en enda storlek eller typ.
Det kanske verkar konstigt att rekommendera templates till en som är ny med c++ men de är faktiskt inte så komplicerade som alla vill få det att låta. Se dem som en lite mer avancerad define till att börja med.
T.ex.
Kod: Markera allt
#include <iostream>
// templateargument
// överallt där TYPE finns, ersätt med den riktiga typen
// överallt där SIZE finns, ersätt med den riktiga storleken
template <typename TYPE, int SIZE>
class Stack {
public:
void push(TYPE val) { if (current_ != end_) { *current_++ = val; } }
TYPE pop() { if (current_ != start_) { return *--current_; } return 0; }
size_t size() const { return SIZE; }
size_t free() const { return end_ - current_; }
size_t used() const { return size() - free(); }
private:
TYPE start_[SIZE];
const TYPE* end_ = start_+ SIZE;
TYPE* current_ = start_;
};
int main() {
using std::cout;
using std::endl;
// instansiera template
Stack<double, 5> stack; // TYPE=double, SIZE=5
cout << "stack size: " << stack.size() << endl;
cout << "stack used: " << stack.used() << endl;
cout << "stack free: " << stack.free() << endl << endl;
stack.push(1);
stack.push(2);
stack.push(3);
cout << "stack used: " << stack.used() << endl;
cout << "stack free: " << stack.free() << endl << endl;
stack.push(4);
stack.push(5);
stack.push(6);
cout << "stack used: " << stack.used() << endl;
cout << "stack free: " << stack.free() << endl << endl;
cout << stack.pop() << endl;
cout << stack.pop() << endl;
cout << stack.pop() << endl;
cout << stack.pop() << endl;
cout << stack.pop() << endl;
cout << "stack used: " << stack.used() << endl;
cout << "stack free: " << stack.free() << endl << endl;
}
Kod: Markera allt
stack size: 5
stack used: 0
stack free: 5
stack used: 3
stack free: 2
stack used: 5
stack free: 0
5
4
3
2
1
stack used: 0
stack free: 5
Re: C++ frågor
Jag ska titta på det men först förklara hur jag tror jag löst det
med dynamisk allokerad stack.
Jag använde new.
Jag vill att varje nytt objekt ska vara en stack och behålla sina värden.
Något blir hur som helst påverkat när ett nytt objekt skapas för som i exemplet
nedan så ska den första stacken jag skapar inte gå att fylla på med mer än
2 värden och det fungerar i första uppsättningen med push. Efter 3:dje push
så meddelas att stacken är full, helt ok.
Sedan skapar jag en ny stack som också beter sig helt ok.
Sedan återgår jag till första stacken men nu måste jag pusha 4ggr för att
få meddelande om att stacken är full, däremot när jag utför pop så verkar
det fungera helt riktigt.
Jag ser inte felet och jag testade att stacKSize var ok för första stacken i båda dessa fall.
med dynamisk allokerad stack.
Jag använde new.
Jag vill att varje nytt objekt ska vara en stack och behålla sina värden.
Något blir hur som helst påverkat när ett nytt objekt skapas för som i exemplet
nedan så ska den första stacken jag skapar inte gå att fylla på med mer än
2 värden och det fungerar i första uppsättningen med push. Efter 3:dje push
så meddelas att stacken är full, helt ok.
Sedan skapar jag en ny stack som också beter sig helt ok.
Sedan återgår jag till första stacken men nu måste jag pusha 4ggr för att
få meddelande om att stacken är full, däremot när jag utför pop så verkar
det fungera helt riktigt.
Jag ser inte felet och jag testade att stacKSize var ok för första stacken i båda dessa fall.
Kod: Markera allt
//============================================================================
// Name : MyFirstC++.cpp
// Author : 4kTRB
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================
#include "StackDouble.h"
using namespace std;
int main() {
StackDouble stackDouble_000(2); // första stacken
cout << "push" << NEWLINE;
stackDouble_000.push(5.5);
cout << "push" << NEWLINE;
stackDouble_000.push(6.5);
cout << "push" << NEWLINE;
stackDouble_000.push(7.5);
cout << "pop ";
printf("%.2f\n", stackDouble_000.pop());
cout << "pop ";
printf("%.2f\n", stackDouble_000.pop());
cout << "pop ";
printf("%.2f\n", stackDouble_000.pop());
cout << STRING << NEWLINE;
StackDouble stackDouble_001(3); // andra stacken
cout << "push" << NEWLINE;
stackDouble_001.push(15.5);
cout << "push" << NEWLINE;
stackDouble_001.push(16.5);
cout << "push" << NEWLINE;
stackDouble_001.push(17.5);
cout << "pop ";
printf("%.2f\n", stackDouble_001.pop());
cout << "pop ";
printf("%.2f\n", stackDouble_001.pop());
cout << "pop ";
printf("%.2f\n", stackDouble_001.pop());
cout << STRING << NEWLINE;
cout << "push" << NEWLINE; // första stacken
stackDouble_000.push(5.5);
cout << "push" << NEWLINE;
stackDouble_000.push(6.5);
cout << "push" << NEWLINE;
stackDouble_000.push(7.5);
cout << "push" << NEWLINE;
stackDouble_000.push(8.5);
cout << "pop ";
printf("%.2f\n", stackDouble_000.pop());
cout << "pop ";
printf("%.2f\n", stackDouble_000.pop());
cout << "pop ";
printf("%.2f\n", stackDouble_000.pop());
cout << "pop ";
printf("%.2f\n", stackDouble_000.pop());
return 0;
}
/*
* StackDouble.cpp
*
* Created on: 4 feb. 2019
* Author: 4kTRB
*/
#include "StackDouble.h"
using namespace std;
//static double allocbuf[STACKSIZEMAX];
static double* allocbuf = NULL;
static double* stackTopPointer;
int stackSize;
StackDouble::StackDouble(int stacksize) {
cout << "En instans av StackDouble" << NEWLINE;
cout << STRING << NEWLINE;
stackSize = stacksize;
allocbuf = new double[stacksize];
for (int i=0; i<stacksize; i++) {
allocbuf[i] = 0; // Initialize all elements to zero.
}
stackTopPointer = allocbuf; // peka på element noll i allocbuf
bool b = allocdouble(); // allokera en stack om stacksize double
if(!b){
cout << "Allokering av stack överskred STACKSIZEMAX" << NEWLINE;
cout << "STACKSIZEMAX = " << STACKSIZEMAX << NEWLINE;
cout << STRING << NEWLINE;
}
}
/**
* Allokera ett minnesområde för att lagra double.
* Avancera pekaren stackTopPointer n steg för att peka på
* start av stacken.
* Returnera true om den allokerade stacken håller
* sig inom ramen för STACKSIZEMAX annars returnera false
*/
bool StackDouble::allocdouble(){
if ((allocbuf + STACKSIZEMAX - stackTopPointer) >= stackSize){
stackTopPointer += stackSize; // peka på stackens början
return true;
} else
return false;
}
void StackDouble::push(double f){
cout << "stackSize " << stackSize << NEWLINE;
if(stackTopPointer > allocbuf){
*stackTopPointer = f;
stackTopPointer--;
}
else{
cout << "Stacken är full" << NEWLINE;
}
}
double StackDouble::pop(){
if(stackTopPointer < (allocbuf + stackSize)){
++stackTopPointer;
return *stackTopPointer;
}
else{
cout << "Stacken är tom så noll returneras ";
return 0.0;
}
}
/*
* StackDouble.h
*
* Created on: 4 feb. 2019
* Author: 4kTRB
*/
#pragma once
#define STACKSIZEMAX 20
#define NEWLINE '\n'
#define STRING "==========================================="
#include <iostream>
class StackDouble {
public:
StackDouble(int);
bool allocdouble();
void push(double);
double pop(void);
private:
int stackSize;
};
En instans av StackDouble
===========================================
push
stackSize 2
push
stackSize 2
push
stackSize 2
Stacken är full
pop 6.50
pop 5.50
pop Stacken är tom så noll returneras 0.00
===========================================
En instans av StackDouble
===========================================
push
stackSize 3
push
stackSize 3
push
stackSize 3
pop 17.50
pop 16.50
pop 15.50
===========================================
push
stackSize 2
push
stackSize 2
push
stackSize 2
push
stackSize 2
Stacken är full
pop 7.50
pop 6.50
pop Stacken är tom så noll returneras 0.00
pop Stacken är tom så noll returneras 0.00
Re: C++ frågor
För varje gång man anropar new och allokerar minne på heapen måste man komma ihåg att anropa delete sen när man är klar.
I det är fallet vore det nog lämpligt i StackDouble's destruktor.
Här där programmet bara kör en kort stund och sen termineras så är det väl inte hela världen, men det är en god programmeringsvana
I det är fallet vore det nog lämpligt i StackDouble's destruktor.
Här där programmet bara kör en kort stund och sen termineras så är det väl inte hela världen, men det är en god programmeringsvana
Re: C++ frågor
Det kan verka vettigt ja.
Men det påverkar väl inte det lite underliga felet jag får ovan?
Är det något fel med testet i push-funktionen som gör att utskriften om "stack full"
kommer först efter 4:de push ?
Om jag inte skapar ytterligare en ny stack, alltså tar bort
StackDouble stackDouble_001(3);,
och utför samma sekvens med push med stackDouble_000
en andra gång som ovan då funkar det helt ok.
Men det påverkar väl inte det lite underliga felet jag får ovan?
Är det något fel med testet i push-funktionen som gör att utskriften om "stack full"
kommer först efter 4:de push ?
Om jag inte skapar ytterligare en ny stack, alltså tar bort
StackDouble stackDouble_001(3);,
och utför samma sekvens med push med stackDouble_000
en andra gång som ovan då funkar det helt ok.
Kod: Markera allt
void StackDouble::push(double f){
cout << "stackSize " << stackSize << NEWLINE;
if(stackTopPointer > allocbuf){
*stackTopPointer = f;
stackTopPointer--;
}
else{
cout << "Stacken är full" << NEWLINE;
}
}
Re: C++ frågor
Det som verkar hända ser jag nu,
när jag skapar ett nytt objekt
så använder gamla objektet den nya stacken som nya objektet skapar.
För om jag skapar
StackDouble stackDouble_000(2); och StackDouble stackDouble_001(2);
så ger 3 push med stackDouble_000 stack full och sedan
samma resultat på nytt medans om jag skapar
StackDouble stackDouble_000(2); och StackDouble stackDouble_001(3);
så måste det till 4 push med stackDouble_000 andra gången.
Det var ju inte riktigt meningen.
när jag skapar ett nytt objekt
så använder gamla objektet den nya stacken som nya objektet skapar.
För om jag skapar
StackDouble stackDouble_000(2); och StackDouble stackDouble_001(2);
så ger 3 push med stackDouble_000 stack full och sedan
samma resultat på nytt medans om jag skapar
StackDouble stackDouble_000(2); och StackDouble stackDouble_001(3);
så måste det till 4 push med stackDouble_000 andra gången.
Det var ju inte riktigt meningen.
Re: C++ frågor
Testade med static och private men
en ny instans skapar en stack på den
gamla i alla fall.
en ny instans skapar en stack på den
gamla i alla fall.
Kod: Markera allt
/*
* StackDouble.h
*
* Created on: 4 feb. 2019
* Author: 4kTRB
*/
#pragma once
#define STACKSIZEMAX 20
#define NEWLINE '\n'
#define STRING "==========================================="
#include <iostream>
class StackDouble {
public:
StackDouble(int);
bool allocdouble();
void push(double);
double pop(void);
void FreeAlloc(void);
private:
int stackSize;
static double* allocbuf;
static double* stackTopPointer;
};
/*
* StackDouble.cpp
*
* Created on: 4 feb. 2019
* Author: 4kTRB
*/
#include "StackDouble.h"
using namespace std;
//static double allocbuf[STACKSIZEMAX];
//static double* allocbuf = NULL;
int stackSize;
double* StackDouble::allocbuf = NULL;
double* StackDouble::stackTopPointer = NULL;
-
- Inlägg: 515
- Blev medlem: 31 maj 2003, 10:42:37
- Ort: Helsingborg
Re: C++ frågor
Är det inte static-deklarationen av allocbuf och stackTopPointer som är problemet? En static class-member hänger väl med alla instanser av objektet?
-
- Inlägg: 1394
- Blev medlem: 29 januari 2011, 21:06:30
- Ort: Lapplandet
Re: C++ frågor
Sorry för att jag har skrivit om din kod en hel del, men jag har gjort på ett annat sätt som kanske är intressant?
Ett problem som kvarstår är att pop-funktionen returnerar 0.0 när det är tomt i stacken...
Ett problem som kvarstår är att pop-funktionen returnerar 0.0 när det är tomt i stacken...
Kod: Markera allt
//============================================================================
// Name : MyFirstC++.cpp
// Author : 4kTRB
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================
#include "StackDouble.h"
using namespace std;
int main() {
StackDouble stackDouble_000(2); // första stacken
cout << "push" << endl;
stackDouble_000.push(5.5);
cout << "push" << endl;
stackDouble_000.push(6.5);
cout << "push" << endl;
stackDouble_000.push(7.5);
cout << "pop ";
cout << stackDouble_000.pop() << endl;
cout << "pop ";
cout << stackDouble_000.pop() << endl;
cout << "pop ";
cout << stackDouble_000.pop() << endl;
cout << STRING << endl;
StackDouble stackDouble_001(3); // andra stacken
cout << "push" << endl;
stackDouble_001.push(15.5);
cout << "push" << endl;
stackDouble_001.push(16.5);
cout << "push" << endl;
stackDouble_001.push(17.5);
cout << "pop ";
cout << stackDouble_001.pop() << endl;
cout << "pop ";
cout << stackDouble_001.pop() << endl;
cout << "pop ";
cout << stackDouble_001.pop() << endl;
cout << STRING << endl;
return 0;
}
Kod: Markera allt
/*
* StackDouble.h
*
* Created on: 4 feb. 2019
* Author: 4kTRB
*/
#pragma once
#define STRING "==========================================="
#include <iostream>
class StackDouble {
public:
StackDouble(int stackcapacity);
~StackDouble();
void push(double number);
double pop(void);
private:
int stackSize;
int stackCapacity;
double* stack;
};
Kod: Markera allt
/*
* StackDouble.cpp
*
* Created on: 4 feb. 2019
* Author: 4kTRB
*/
#include "StackDouble.h"
using namespace std;
StackDouble::StackDouble(int stackcapacity) : stackCapacity(stackcapacity), stackSize(0)
{
stack = new double[stackCapacity];
cout << "En instans av StackDouble har skapats." << endl;
cout << STRING << endl;
}
StackDouble::~StackDouble()
{
delete stack;
cout << "En instans av StackDouble har tagits bort." << endl;
}
void StackDouble::push(double number){
cout << "stackSize " << stackSize << endl;
if(stackSize < stackCapacity)
{
stack[stackSize++] = number;
}
else
{
cout << "Stacken är full" << endl;
}
}
double StackDouble::pop(){
if(stackSize > 0)
{
return stack[--stackSize];
}
else
{
cout << "Stacken är tom så noll returneras " << endl;
return 0.0;
}
}
Re: C++ frågor
Det där ser riktigt bra ut.
Jag ser inga stora skillnader på den variant jag försöker med
mer än att stackTopPointer verkar vara en bov i dramat.
Jag jobbar mig ned mot allocbuf[0] vid push, det är tvärt om men
borde fungera.
Den här koden fungerar helt enkelt inte som var avsikten...trots att jag tar bort static.
Jag ser inga stora skillnader på den variant jag försöker med
mer än att stackTopPointer verkar vara en bov i dramat.
Jag jobbar mig ned mot allocbuf[0] vid push, det är tvärt om men
borde fungera.
Den här koden fungerar helt enkelt inte som var avsikten...trots att jag tar bort static.
Kod: Markera allt
*
* StackDouble.h
*
* Created on: 4 feb. 2019
* Author: 4kTRB
*/
#pragma once
#define STACKSIZEMAX 20
#define NEWLINE '\n'
#define STRING "==========================================="
#include <iostream>
class StackDouble {
public:
StackDouble(int stacksize);
void push(double f);
double pop(void);
private:
void FreeAlloc(void);
bool allocdouble();
double* allocbuf;
double* stackTopPointer;
int stackSize;
};
Kod: Markera allt
/*
* StackDouble.cpp
*
* Created on: 4 feb. 2019
* Author: 4kTRB
*/
#include "StackDouble.h"
using namespace std;
//static double allocbuf[STACKSIZEMAX];
//static double* allocbuf = NULL;
StackDouble::StackDouble(int stacksize) {
cout << "En instans av StackDouble" << NEWLINE;
cout << STRING << NEWLINE;
stackSize = stacksize;
allocbuf = new double[stacksize];
for (int i=0; i<stacksize; i++) {
allocbuf[i] = 0; // Initialize all elements to zero.
}
stackTopPointer = allocbuf; // peka på element noll i allocbuf
// stackTopPointer = &allocbuf[0]; // fungerar också
bool b = allocdouble(); // allokera en stack om stacksize double
if(!b){
cout << "Allokering av stack överskred STACKSIZEMAX" << NEWLINE;
cout << "STACKSIZEMAX = " << STACKSIZEMAX << NEWLINE;
cout << STRING << NEWLINE;
}
}
/**
* Allokera ett minnesområde för att lagra double.
* Avancera pekaren stackTopPointer n steg för att peka på
* start av stacken.
* Returnera true om den allokerade stacken håller
* sig inom ramen för STACKSIZEMAX annars returnera false
*/
bool StackDouble::allocdouble(){
if ((allocbuf + STACKSIZEMAX - stackTopPointer) >= stackSize){
stackTopPointer += stackSize; // peka på stackens början
return true;
} else
return false;
}
void StackDouble::push(double f){
if(stackTopPointer > allocbuf){
*stackTopPointer = f;
stackTopPointer--;
}
else{
cout << "Stacken är full" << NEWLINE;
}
}
double StackDouble::pop(){
if(stackTopPointer < (allocbuf + stackSize)){
++stackTopPointer;
return *stackTopPointer;
}
else{
cout << "Stacken är tom så noll returneras ";
return 0.0;
}
}
void StackDouble::FreeAlloc(){
delete [] allocbuf; // Free memory allocated for the a array.
allocbuf = NULL; // Be sure the deallocated memory isn't used.
stackTopPointer = NULL;
}