C++ frågor

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
Användarvisningsbild
4kTRB
Inlägg: 18395
Blev medlem: 16 augusti 2009, 19:04:48

Re: C++ frågor

Inlägg av 4kTRB »

Då är jag med.

Testade att byta i headerfilen men då blir det felmeddelanden.

Kod: Markera allt

/*
 * FirstClass.h
 *
 *  Created on: 2 feb. 2019
 *      Author: 4kTRB
 */
#ifndef _FIRSTCLASS
#define _FIRSTCLASS
#define VECTORSIZE 10
#include <string>
//using namespace std;

class FirstClass {
public:
	FirstClass();
	void addInt(int*);
	//void addString(string* s);
	void addString(std::string* s);
	void initVector(int*);
private:
	int digit[VECTORSIZE];
	int* vektorPekare;
};

#endif
Shimonu
Inlägg: 295
Blev medlem: 21 oktober 2015, 22:44:33

Re: C++ frågor

Inlägg av Shimonu »

Vad är felmeddelandet då?
Användarvisningsbild
4kTRB
Inlägg: 18395
Blev medlem: 16 augusti 2009, 19:04:48

Re: C++ frågor

Inlägg av 4kTRB »

Övade på att fylla en vektor med hjälp av pekare.
Lite förvirrande var det när jag upptäckte att

int* variabel
och
int *variabel

betyder samma sak.

Jag kör nu med int* variabel varianten för då
tänker jag mig variabel som av typen heltalspekare.

Sedan så går det alltså fylla på en vektor mha enbart pekaren eller
vektorns index.

Kod: Markera allt

//============================================================================
// Name        : MyFirstC++.cpp
// Author      : 4kTRB
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include "FirstClass.h"
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
#define LOOPMAX 5
#define NEWLINE '\n'
#define HTAB '\t'
int main() {
	string stringA = "=======================================";

	int data = 10;
	int* pointerToData = &data;

	string text = "Skepp o Hoj";
	string* pointerToText = &text;

	int heltal = 0;
	int* pekareTillHeltal = &heltal;

	FirstClass firstClass;
	for(int i=0;i<LOOPMAX;i++){
		cout << stringA  << NEWLINE;
		cout << data << NEWLINE;
		firstClass.addInt(pointerToData);
	}

	for(int i=0;i<LOOPMAX;i++){
		cout << stringA  << NEWLINE;
		cout << text << NEWLINE;
		firstClass.addString(pointerToText);
	}

	cout << stringA  << NEWLINE;
	cout << "heltal innan = " << heltal << NEWLINE << stringA <<NEWLINE;

	firstClass.initVector(pekareTillHeltal);

	cout << stringA  << NEWLINE;
	cout << "heltal efter = " << heltal << NEWLINE << stringA << NEWLINE;
	return 0;
}
/*
 * FirstClass.cpp
 *
 *  Created on: 2 feb. 2019
 *      Author: 4kTRB
 */

#include "FirstClass.h"
#include <stdio.h>
#include <iostream>

FirstClass::FirstClass() {
	printf(" FirstClass \n");
	vektorPekare = &digit[0];
}
void FirstClass::addInt(int* a){
	*a += 10;
}
void FirstClass::addString(string* s){
	*s += " =)";
}

void FirstClass::initVector(int* a){
	vektorPekare = &digit[0];
	*vektorPekare = *a;
	for(int v=1;v<10;v++){
		*a = *a + 10;		
		*(vektorPekare+v) = *a;
		//digit[v] = *(vektorPekare+v);
	}
	cout << "======="  <<  "\n";
	for(int i=0;i<VECTORSIZE; ++i){
		cout << *(vektorPekare+i) << "\n";
		cout << digit[i] << "\n";
		cout << "======="  <<  "\n";
	}
}
/*
 * FirstClass.h
 *
 *  Created on: 2 feb. 2019
 *      Author: 4kTRB
 */
#ifndef _FIRSTCLASS
#define _FIRSTCLASS
#define VECTORSIZE 10
#include <string>
using namespace std;

class FirstClass {
public:
	FirstClass();
	void addInt(int*);
	void addString(string* s);
	void initVector(int*);
private:
	int digit[VECTORSIZE];
	int* vektorPekare;
};

#endif

FirstClass
=======================================
10
=======================================
20
=======================================
30
=======================================
40
=======================================
50
=======================================
Skepp o Hoj
=======================================
Skepp o Hoj =)
=======================================
Skepp o Hoj =) =)
=======================================
Skepp o Hoj =) =) =)
=======================================
Skepp o Hoj =) =) =) =)
=======================================
heltal innan = 0
=======================================
=======
0
0
=======
10
10
=======
20
20
=======
30
30
=======
40
40
=======
50
50
=======
60
60
=======
70
70
=======
80
80
=======
90
90
=======
=======================================
heltal efter = 90
=======================================
Senast redigerad av 4kTRB 3 februari 2019, 11:37:21, redigerad totalt 1 gång.
Användarvisningsbild
4kTRB
Inlägg: 18395
Blev medlem: 16 augusti 2009, 19:04:48

Re: C++ frågor

Inlägg av 4kTRB »

Shimonu skrev:Vad är felmeddelandet då?
11:33:06 **** Incremental Build of configuration Debug for project MyFirstC++ ****
Info: Internal Builder is used for build
g++ -O0 -g3 -Wall -c -fmessage-length=0 -o "src\\FirstClass.o" "..\\src\\FirstClass.cpp"
..\src\FirstClass.cpp:19:28: error: variable or field 'addString' declared void
void FirstClass::addString(string* s){
^~~~~~
..\src\FirstClass.cpp:19:28: error: 'string' was not declared in this scope
..\src\FirstClass.cpp:19:28: note: suggested alternatives:
In file included from c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\string:39:0,
from ..\src\FirstClass.h:10,
from ..\src\FirstClass.cpp:8:
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stringfwd.h:74:33: note: 'std::__cxx11::string'
typedef basic_string<char> string;
^~~~~~
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stringfwd.h:74:33: note: 'std::__cxx11::string'
..\src\FirstClass.cpp:19:36: error: 's' was not declared in this scope
void FirstClass::addString(string* s){
^
..\src\FirstClass.cpp: In member function 'void FirstClass::initVector(int*)':
..\src\FirstClass.cpp:31:2: error: 'cout' was not declared in this scope
cout << "=======" << "\n";
^~~~
..\src\FirstClass.cpp:31:2: note: suggested alternative:
In file included from ..\src\FirstClass.cpp:10:0:
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\iostream:61:18: note: 'std::cout'
extern ostream cout; /// Linked to standard output
^~~~

11:33:06 Build Failed. 4 errors, 0 warnings. (took 724ms)
kodar-holger
EF Sponsor
Inlägg: 920
Blev medlem: 26 maj 2014, 12:54:35
Ort: Karlskoga

Re: C++ frågor

Inlägg av kodar-holger »

Om du plockar bort using namesace måste det anges överallt där du refererar till saker i detta namespace. Så du måste alltså skriva std::string iställt för bara string.

Personligen tycker jag koden blir tydligare när man alltid explicit anger namespacen på detta sätt. Åtminstone till rimliga gränser och dit tycker jag standard template library hör.

Angående int* variabel och int *variabel så är det samma sak. Återigen är det personligt tycke och smak. Jag håller med om att int* gör det tydligt att det är en pekare till ett heltal som gäller. Men egentligen gör inte kompilatorn det som någon påpekade för mig tidigare här på ef.

Skriver man
int* a,b;

Blir a en pekare till en int medan b blir en int. Trots att * står ihop med int. Den paras med nästa identifierare.

Å andra sidan skall man skriva alla deklatationer var för sig med en kommentar efteråt om namnet inte är självförklarande :-)
Användarvisningsbild
4kTRB
Inlägg: 18395
Blev medlem: 16 augusti 2009, 19:04:48

Re: C++ frågor

Inlägg av 4kTRB »

Ok, jag fick det att fungera nu.
Tycker det känns som C++ tar väldigt lång tid att lära.
Det finns rätt så många sätt att få samma sak att fungera på.

Jag försöker bara lära mig grunderna så jag kan komma igång med Arduino sedan.
Objektorienterat är bra att ha testat på hur det fungerar i C++, helt nytt för mig men
lite samma princip som i Java.

Kod: Markera allt

//============================================================================
// Name        : MyFirstC++.cpp
// Author      : 4kTRB
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include "FirstClass.h"
#include <stdio.h>
#include <iostream>
#include <string>
#include <string.h>
using namespace std;
#define LOOPMAX 5
#define NEWLINE '\n'
#define HTAB '\t'
int main() {
	string stringA = "=======================================";

	int data = 10;
	int* pointerToData = &data;

	string text = "Skepp o Hoj";
	string* pointerToText = &text;

	int heltal = 0;
	int* pekareTillHeltal = &heltal;

	FirstClass firstClass;
	//========================================================================
	// Addera en int
	//========================================================================
	for(int i=0;i<LOOPMAX;i++){
		cout << stringA  << NEWLINE;
		cout << data << NEWLINE;
		firstClass.addInt(pointerToData);
	}
	//========================================================================
	// Addera text
	//========================================================================
	for(int i=0;i<LOOPMAX;i++){
		cout << stringA  << NEWLINE;
		cout << text << NEWLINE;
		firstClass.addString(pointerToText);
	}
	cout << stringA  << NEWLINE;
	//========================================================================
	// Fyll upp en vektor
	//========================================================================
	cout << "heltal innan = " << heltal << NEWLINE << stringA <<NEWLINE;

	firstClass.initVector(pekareTillHeltal);

	cout << stringA  << NEWLINE;
	cout << "heltal efter = " << heltal << NEWLINE << stringA << NEWLINE;
	//========================================================================
	// Räkna tecken i en sträng
	//========================================================================
	char textString[] = "Massa Bokstäver";
	char* vektorPekare = &textString[0];

	int antalTecken = firstClass.stringLength(vektorPekare);

	string arrayToString(textString);
	string s = textString;
	cout << "antal tecken i strängen = " << antalTecken << NEWLINE;
	cout << "texten = " << arrayToString << NEWLINE;
	cout << "texten = " << s;
	cout << NEWLINE << stringA  << NEWLINE;
	return 0;
}
/*
 * FirstClass.cpp
 *
 *  Created on: 2 feb. 2019
 *      Author: 4kTRB
 */

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

FirstClass::FirstClass() {
	printf(" FirstClass \n");
	vektorPekare = &digit[0];
}
void FirstClass::addInt(int* a){
	*a += 10;
}
void FirstClass::addString(std::string* s){
	*s += " =)";
}

void FirstClass::initVector(int* a){
	vektorPekare = &digit[0];
	*vektorPekare = *a;
	for(int v=1;v<10;v++){
		*a = *a + 10;
		*(vektorPekare+v) = *a;
		//digit[v] = *(vektorPekare+v);
	}
	cout << "======="  <<  "\n";
	for(int i=0;i<VECTORSIZE; ++i){
		cout << *(vektorPekare+i) << "\n";
		cout << digit[i] << "\n";
		cout << "======="  <<  "\n";
	}
}

int FirstClass::stringLength(char* s){
	int n;
	for(n=0; *s != '\0'; s++){
		n++;
	}
	return n;
}
/*
 * FirstClass.h
 *
 *  Created on: 2 feb. 2019
 *      Author: 4kTRB
 */
#ifndef _FIRSTCLASS
#define _FIRSTCLASS
#define VECTORSIZE 10
#include <string>

class FirstClass {
public:
	FirstClass();
	void addInt(int*);
	void addString(std::string* s);
	void initVector(int*);
	int stringLength(char* s);
private:
	int digit[VECTORSIZE];
	int* vektorPekare;
};

#endif

FirstClass
=======================================
10
=======================================
20
=======================================
30
=======================================
40
=======================================
50
=======================================
Skepp o Hoj
=======================================
Skepp o Hoj =)
=======================================
Skepp o Hoj =) =)
=======================================
Skepp o Hoj =) =) =)
=======================================
Skepp o Hoj =) =) =) =)
=======================================
heltal innan = 0
=======================================
=======
0
0
=======
10
10
=======
20
20
=======
30
30
=======
40
40
=======
50
50
=======
60
60
=======
70
70
=======
80
80
=======
90
90
=======
=======================================
heltal efter = 90
=======================================
antal tecken i strängen = 15
texten = Massa Bokstäver
texten = Massa Bokstäver
=======================================
Användarvisningsbild
4kTRB
Inlägg: 18395
Blev medlem: 16 augusti 2009, 19:04:48

Re: C++ frågor

Inlägg av 4kTRB »

Om jag skapar ytterligare en klass så skapas det en tillhörande .h fil också.
Måste det vara en .h fil för varje klass?
Kunde man inte ha endast en .h för alla klasser?
Det är ju mycket att hålla reda på ändå.

Tycker C verkar vara som skapt för att skriva buggiga program.
Det gäller att vara skärpt och hålla sig till läsbar kod.
kodar-holger
EF Sponsor
Inlägg: 920
Blev medlem: 26 maj 2014, 12:54:35
Ort: Karlskoga

Re: C++ frågor

Inlägg av kodar-holger »

Man måste inte ha några .h-filer alls men det vill man oftast. (Dom behöver för övrigt inte heta .h heller utan det är bara en konvention)

C och C++ kompilatorer läser bara en källkodsfil i taget. Det är länkaren som sen gör något körbart av helheten.

När kompileringen görs kan man inte använda något som ännu inte är känt. Så om du vill använda std::string måste den klassen vara känd när du börjar använda den. Däremot behöver man inte ha detaljerna. Så vad man kan göra är en deklaration och det är den man gärna placerar i en .h-fil.

Om du inte har .h-filer utan gör #include direkt på .cpp-filen kommer den att kompileras tillsammans med "din" källkod. Det fungerar ju om du bara använder .cpp-filen en gång. Skulle ditt program vara delat på två filer och du inkluderar cpp-filen från båda kommer kompilatorn att producera samma binärkod två gånger och länkaren vet då i bästa fall inte vart den skall ta vägen.

Men man behöver ju inte nöja sig med en klassdeklaration per par av .cpp/.h Filernas namn har inget som helst med innehållet att göra även om det kan röra till det rejält för programmeraren när han vill ha tillgång till klassen LCDDriver och måste göra include på klasser.h. I synnerhet om den då samtidigt innehåller klasserna ToasterDriver, AffineTransforms, RougeOne och LightSabre.

Sen måste man ibland gör #include från en .h-fil för att komma åt deklarationer av saker. Som du redan sett ex.vis "include <string.h>". Det här gör att kompilatorn kanske måste gå igenom hierarkier av #include för att hitta allt. Och har man rört till det riktigt kan det bli loopar i beroenden. Därför bör man alltid skriva

#pragma once i sin .h-fil

Det gör att kompilatorn ser att har jag redan inkluderat den här en gång så räcker det.

P.S.
En del programmerare tror fortfarande att man skall göra #ifdef och #define runt allt i sin .h-fil. Gör inte det.
D.S.
Användarvisningsbild
4kTRB
Inlägg: 18395
Blev medlem: 16 augusti 2009, 19:04:48

Re: C++ frågor

Inlägg av 4kTRB »

Tror jag förstår en del och även minns en del från Lattice C-kompilatorn med länkning och sånt.

Jag städade i koden en del efter de tipsen och ser att det fungerar fint.

Adderade en ny klass med en minnesallokerare. Tror att den kunskapen kan vara värdefull
för kod mot Arduino. Förstår också varför de valt C++ liknande språk till Arduino när man
kan mippla med minnet direkt. Sånt funkar inte i Java med en virtuell maskin. Det är väl
bara Java-kod som kompileras där det fungerar på samma sätt.

Nu ser det ut så här:

Kod: Markera allt

//============================================================================
// Name        : MyFirstC++.cpp
// Author      : 4kTRB
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include "FirstClass.h"
#include "SecondClass.h"
using namespace std;

#define LOOPMAX 4
#define NEWLINE '\n'
#define HTAB '\t'

int main() {
	string stringA = "=======================================";

	int data = 10;
	int* pointerToData = &data;

	string text = "Skepp o Hoj";
	string* pointerToText = &text;

	int heltal = 0;
	int* pekareTillHeltal = &heltal;

	FirstClass firstClass;
	SecondClass secondClass;

	//========================================================================
	// Allokera minne för att lagra tecken
	//========================================================================
	char textAvTecken_A[] = "ABCDEFGH";
	char textAvTecken_B[] = "IJKLMNOP";
	char textAvTecken_C[] = "QRSTUVWX";
	char* pekareA = &textAvTecken_A[0];
	char* pekareB = &textAvTecken_B[0];
	char* pekareC = &textAvTecken_C[0];
	int memorySpace = 8;
	// Allokera 3 minnesområden om 8 tecken
	char* pointerToMemoryAreaStartA = secondClass.alloc(memorySpace);
	char* pointerToMemoryAreaStartB = secondClass.alloc(memorySpace);
	char* pointerToMemoryAreaStartC = secondClass.alloc(memorySpace);
	// Fyll de allokerade minnesområdena
	for(int i=0; i<memorySpace;i++){
	/*	*(pointerToMemoryAreaStartA + i) = textAvTecken_A[i];
		*(pointerToMemoryAreaStartB + i) = textAvTecken_B[i];
		*(pointerToMemoryAreaStartC + i) = textAvTecken_C[i];		*/
		*(pointerToMemoryAreaStartA + i) = *(pekareA+i);
		*(pointerToMemoryAreaStartB + i) = *(pekareB+i);
		*(pointerToMemoryAreaStartC + i) = *(pekareC+i);
	}
	// Skriv ut innehållet i de allokerade minnesområdena
	for(int i=0; i<(memorySpace * 3);i++){
		if(i % 8 == 0)
			cout << "MinnesArea " << (i+1)/8 << NEWLINE;
		cout << *(pointerToMemoryAreaStartA+i) << NEWLINE;
	}


	//========================================================================
	// Addera en int
	//========================================================================
	for(int i=0;i<LOOPMAX;i++){
		cout << stringA  << NEWLINE;
		cout << data << NEWLINE;
		firstClass.addInt(pointerToData);
	}
	//========================================================================
	// Addera text
	//========================================================================
	for(int i=0;i<LOOPMAX;i++){
		cout << stringA  << NEWLINE;
		cout << text << NEWLINE;
		firstClass.addString(pointerToText);
	}
	cout << stringA  << NEWLINE;
	//========================================================================
	// Fyll upp en vektor
	//========================================================================
	cout << "heltal innan = " << heltal << NEWLINE << stringA <<NEWLINE;

	firstClass.initVector(pekareTillHeltal);

	cout << stringA  << NEWLINE;
	cout << "heltal efter = " << heltal << NEWLINE << stringA << NEWLINE;
	//========================================================================
	// Räkna tecken i en sträng
	//========================================================================
	char textString[] = "Massa Bokstäver";
	char* vektorPekare = &textString[0];

	int antalTecken = firstClass.stringLength(vektorPekare);

	string arrayToString(textString);
	string s = textString;
	cout << "antal tecken i strängen = " << antalTecken << NEWLINE;
	cout << "texten = " << arrayToString << NEWLINE;
	cout << "texten = " << s;
	cout << NEWLINE << stringA  << NEWLINE;
	return 0;
}
/*
 * FirstClass.cpp
 *
 *  Created on: 2 feb. 2019
 *  Author: 4kTRB
 */

#include "FirstClass.h"
using namespace std;

FirstClass::FirstClass() {
	printf("FirstClass \n");
	vektorPekare = &digit[0];
}
void FirstClass::addInt(int* a){
	*a += 10;
}
void FirstClass::addString(std::string* s){
	*s += " =)";
}

void FirstClass::initVector(int* a){
	vektorPekare = &digit[0];
	*vektorPekare = *a;
	for(int v=1;v<VECTORSIZE;v++){
		*a = *a + 10;
		*(vektorPekare+v) = *a;
		//digit[v] = *(vektorPekare+v);
	}
	cout << "======="  <<  "\n";
	for(int i=0;i<VECTORSIZE; ++i){
		cout << *(vektorPekare+i) << "\n";
		cout << digit[i] << "\n";
		cout << "======="  <<  "\n";
	}
}

int FirstClass::stringLength(char* s){
	int n;
	for(n=0; *s != '\0'; s++){
		n++;
	}
	return n;
}
/*
 *  SecondClass.cpp
 *
 *  Created on: 3 feb. 2019
 *  Author: 4kTRB
 */
#include "SecondClass.h"
#include <stdio.h>

static char allocbuf[ALLOCSIZE];	// minne för alloc
static char* allocp;				// nästa fria position

SecondClass::SecondClass() {
	printf("SecondClass \n");
	allocp = allocbuf;				// peka på start av allocbuf
	// allocp = &allocbuf[0];		// samma resultat
}
/**
 * Allokera ett minnesområde för att lagra tecken.
 * Avancera pekaren allocp n steg för att peka på
 * start av återstående fritt minnesområde.
 * Returnera en pekare som pekar på start av det
 * allokerat minnesområdet om n tecken.
 */
char* SecondClass::alloc(int n){
	if (allocbuf + ALLOCSIZE - allocp >= n){
		allocp += n;
		return allocp-n;
	} else
		return 0;
}
 /**
  * Frigör minne som p pekar på
  */
void SecondClass::afree(char* p){
	if(p >= allocbuf && p < allocbuf + ALLOCSIZE)
		allocp = p;
}
/*
 * FirstClass.h
 *
 *  Created on: 2 feb. 2019
 *  Author: 4kTRB
 */
#pragma once
#define _FIRSTCLASS
#define VECTORSIZE 5
#include <iostream>

class FirstClass {
public:
	FirstClass();
	void addInt(int*);
	void addString(std::string*);
	void initVector(int*);
	int stringLength(char* s);
private:
	int digit[VECTORSIZE];
	int* vektorPekare;
};
/*
 * SecondClass.h
 *
 *  Created on: 3 feb. 2019
 *  Author: 4kTRB
 */
#pragma once
#define SECONDCLASS_H_
#define ALLOCSIZE 1000

class SecondClass {
public:
	SecondClass();
	char* alloc(int);
	void afree(char*);
private:

};
FirstClass
SecondClass
MinnesArea 0
A
B
C
D
E
F
G
H
MinnesArea 1
I
J
K
L
M
N
O
P
MinnesArea 2
Q
R
S
T
U
V
W
X
=======================================
10
=======================================
20
=======================================
30
=======================================
40
=======================================
Skepp o Hoj
=======================================
Skepp o Hoj =)
=======================================
Skepp o Hoj =) =)
=======================================
Skepp o Hoj =) =) =)
=======================================
heltal innan = 0
=======================================
=======
0
0
=======
10
10
=======
20
20
=======
30
30
=======
40
40
=======
=======================================
heltal efter = 40
=======================================
antal tecken i strängen = 15
texten = Massa Bokstäver
texten = Massa Bokstäver
=======================================
kodar-holger
EF Sponsor
Inlägg: 920
Blev medlem: 26 maj 2014, 12:54:35
Ort: Karlskoga

Re: C++ frågor

Inlägg av kodar-holger »

Nu ser du ju ut att veta vad du gör med din static men för eventuella övriga läsare vill jag påpeka att static tillsammans med class är något man skall fundera noga på.

Vitsen med att göra klasser (class) är att man sen skall kunna göra flera instanser (object) av dessa och att dessa är oberoende.
Vitsen med static är att där skall finnas bara en och den skall vara där under hela programexekveringen.

I det här fallet skapas en buffert statiskt så att där bara är en av den. Sen tar man upp bitar av den till respektive instans. Det hade också gått att använda malloc men på ett inbäddat system är detta den ultimata lösningen. Du fastslår redan från början en buffert som är dedikerad till ändamålet. Finns inte utrymmet när koden byggs kommer det att komma felmeddelanden.
--

Koden visar dock på ett annat problem. I secondclass.h finns
#define ALLOCSIZE 1000
Det gör att bufferten alltid är 1000 tecken stor. Oavsett vilket system man bygger mot. På en AVR kan 1000 vara väldigt mycket medan det på en freescale K20 kan vara som en fis i rymden. Gör man då ett bibliotek som man inte vet hur det kommer att användas kan detta vara ett problem. Samtidigt som man vill ha den statiska allokeringen.
Jag satt för några dagar sedan med exakt detta problem. I Ada hade jag löst det på 10 sekunder med generics. Motsvarande fast sämre finns i C++ och kallas Templates. Dessa har i mitt tycke så många avigsidor att de i många fall är oanvändbara. I mitt fall slutade det med att jag gjorde exakt som ovan. En #define som satte buffertstorleken.

Angående valet av C++ för arduino så kan jag förstå det också. Ada hade varit bättre men antalet Ada-kompilatorer för inbäddade processorer kan tyvärr räknas på handens alla fingrar även av den som jobbat i träindustri hela sitt liv. Java har som sagt inte direktåtkomst till minne som ofta är viktigt i inbäddade system och språk som Python, Go, BrainFuck och Whenever var kanske inte heller lämpliga.

Och som ordspråket säger. 2^30 flugar kan inte ha fel. Programmera i C++
Användarvisningsbild
4kTRB
Inlägg: 18395
Blev medlem: 16 augusti 2009, 19:04:48

Re: C++ frågor

Inlägg av 4kTRB »

Tycker mig känna att pekare och adressaritmetik är guld att
ha lite grepp om när Arduino ska programmeras så jag koncentrerar
mig på det just nu.

Skapade en klass som representerar en stack och vitsen blir ju då att
jag kan skapa så många stackar jag behöver genom att skapa en ny instans.

På det sätt jag valt i koden så blir det just nu minne som ligger oanvänt om
jag inte väljer att skapa stackar som går upp till maxgränsen som är satt.

I Arduino är det säkert fint att ha så mycket fritt minne som möjligt så
då ska jag försöka lägga till en funktion som frigör det minne som inte används.

När jag skapade klassen i Eclipse så frågas om ett namn på NAMESPACE så jag skrev in
std och då genererades en mall med klammer runt hela .h och .cpp koden. Jag fick en del
"mystiska" fel när jag skrev koden så jag hoppade tillbaka till using namespace std; som
jag använt tidigare. Nu vet jag inte om det var där felet låg men jag brydde mig inte om
att testa varianten som Eclipse skapade.

En sak här nedan som jag inte riktigt är med på är testet

if ((allocbuf + STACKSIZEMAX - stackTopPointer) >= stackSize)

stackTopPointer är ju tycker jag inte növändigt men med testet

if ((allocbuf + STACKSIZEMAX) >= stackSize)

så blir det enligt kompilatorn illegalt ?

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 ";
	cout << stackDouble_000.pop() << NEWLINE;
	cout << "pop ";
	cout << stackDouble_000.pop() << NEWLINE;
	cout << "pop ";
	cout << stackDouble_000.pop() << NEWLINE;

	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 ";
	cout << stackDouble_001.pop() << NEWLINE;
	cout << "pop ";
	cout << stackDouble_001.pop() << NEWLINE;
	cout << "pop ";
	cout << stackDouble_001.pop() << NEWLINE;

	cout << STRING << NEWLINE;


	return 0;
}

/*
 * StackDouble.h
 *
 *  Created on: 4 feb. 2019
 *      Author: 4kTRB
 */
#pragma once
#define STACKDOUBLE_H_
#define STACKSIZEMAX 20
#define NEWLINE '\n'
#define STRING "==========================================="
#include <iostream>

class StackDouble {
public:
	StackDouble(int);
	bool allocdouble();
	void push(double);
	double pop(void);
private:

};

/*
 * StackDouble.cpp
 *
 *  Created on: 4 feb. 2019
 *      Author: 4kTRB
 */

#include "StackDouble.h"

static double allocbuf[STACKSIZEMAX];
static double* stackTopPointer;
static int stackSize;
using namespace std;

StackDouble::StackDouble(int stacksize) {
	cout << "En instans av StackDouble" << NEWLINE;
	cout << STRING  << NEWLINE;
	stackSize = stacksize;
	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;
		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;
	}
}


En instans av StackDouble
===========================================
push
push
push
Stacken är full
pop 6.5
pop 5.5
pop Stacken är tom så noll returneras 0
===========================================
En instans av StackDouble
===========================================
push
push
push
pop 17.5
pop 16.5
pop 15.5
===========================================
Mr Andersson
Inlägg: 1397
Blev medlem: 29 januari 2011, 21:06:30
Ort: Lapplandet

Re: C++ frågor

Inlägg av Mr Andersson »

En sak här nedan som jag inte riktigt är med på är testet

if ((allocbuf + STACKSIZEMAX - stackTopPointer) >= stackSize)

stackTopPointer är ju tycker jag inte növändigt men med testet

if ((allocbuf + STACKSIZEMAX) >= stackSize)

så blir det enligt kompilatorn illegalt ?
Det har att göra med hur pekare fungerar.
allocbuf (double*) + STACKSIZEMAX (int) blir en ny pekare (vi kan kalla den TEMP). Du kan inte jämföra en pekare med int (dvs stackSize)
TEMP - stackTopPointer (pekare minus pekare av samma typ) blir en int. int går att jämföra med int.

Kod: Markera allt

#include <iostream>
#include <typeinfo>

int main() {
	int* POINTER;
	int INT;

	std::cout << "int* + int = " << typeid(POINTER + INT).name() << std::endl;
	std::cout << "int* - int = " << typeid(POINTER - INT).name() << std::endl;
	std::cout << "int* - int* = " << typeid(POINTER - POINTER).name() << std::endl;
}
int* + int = int *
int* - int = int *
int* - int* = int


PS. stack-variablerna i StackDouble.cpp är globala så alla stack-instanser delar på samma variabler vilket troligen inte är vad du vill här.
Gör dem till en klassmedlemmar istället.
Användarvisningsbild
4kTRB
Inlägg: 18395
Blev medlem: 16 augusti 2009, 19:04:48

Re: C++ frågor

Inlägg av 4kTRB »

Så här?
Då fungerar det att ta bort deklarationen i klassen men då blir de väl inte static?

Kod: Markera allt

/*
 * StackDouble.h
 *
 *  Created on: 4 feb. 2019
 *      Author: 4kTRB
 */
#pragma once
#define STACKDOUBLE_H_
#define STACKSIZEMAX 20
#define NEWLINE '\n'
#define STRING "==========================================="
#include <iostream>

class StackDouble {
public:
	StackDouble(int);
	bool allocdouble();
	void push(double);
	double pop(void);
private:
	double allocbuf[STACKSIZEMAX];
	double* stackTopPointer;
	int stackSize;
};
Mr Andersson
Inlägg: 1397
Blev medlem: 29 januari 2011, 21:06:30
Ort: Lapplandet

Re: C++ frågor

Inlägg av Mr Andersson »

static har många olika betydelser beroende på sammanhanget.

Jag gissar att du syftar på statisk lagring/livstid, dvs att de behåller värdet över tid. Klassmedlemmar har samma livstid som själva klassinstansen.
Som exempel i main har du StackDouble stackDouble_001(3);
Då lever alla variabler i stackDouble_001 tills main tar slut.

Sättet du använde static på är dock statisk/intern länkning. Dvs att variablerna går inte att komma åt via namn utanför TU:n som definierar dem. (Translation Unit, ungefär samma som en .cpp-fil)

En annan static är statiska klassvariabler. Det innebär att de är gemensamma för alla klassinstanser, dvs ändra i en instans och det syns i alla andra.

Den fjärde och sista static är statiska klassmetoder. Det är funktioner man kan anropa utan en klassinstans.
Användarvisningsbild
4kTRB
Inlägg: 18395
Blev medlem: 16 augusti 2009, 19:04:48

Re: C++ frågor

Inlägg av 4kTRB »

Jag behöver inte komma åt variablerna i de skapade objekten. Jag är nöjd om jag kan utföra pusha och poppa. Och att det jag lagt på stacken håller sig där. Kanske att jag kan deklarera stackTop pekaren som privat utan static eller publicerad om jag vill nå den.
Skriv svar