Blandade C++ frågor, nybörjarnivå

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
Användarvisningsbild
lillahuset
Gått bort
Inlägg: 13969
Blev medlem: 3 juli 2008, 08:13:14
Ort: Norrköping

Re: Blandade C++ frågor, nybörjarnivå

Inlägg av lillahuset »

Argumentet heter showData och då kan du inte komma åt den globala variabeln.

Ett tips är att ha någon form av "policy" om hur du döper olika variabler. Jag har fyra regler jag brukar följa hyfsat som ger ledtrådar om vad jag pysslar med:

Ett MACRO har ett namn bestående av enbart versaler. Till exempel #define BUFSZ 80.
En Global variabel har alltid en versal som första tecken.
En lokal variabel har alltid en gemen som första tecken.
Mr Andersson
Inlägg: 1397
Blev medlem: 29 januari 2011, 21:06:30
Ort: Lapplandet

Re: Blandade C++ frågor, nybörjarnivå

Inlägg av Mr Andersson »

ShowOnDisplay showData = displayMachines;

void doButtonDebounce(uint8_t showData) {
showData i doButtonDebounce() gömmer den globala showData
Alla variabler som är deklarerade i en funktion, inklusive funktionsargument, är lokala för den funktionen.
Är det tänkt att båda ska hänvisa till samma värde så kan du bara ta bort showData från argumentslistan. Annars om det är två olika variabler och du behöver använda båda i funktionen så måste du byta namn på en av dem.
Eller om du bara vill använda den showData som skickas som argument och inte behöver den globala behöver du inte ändra nånting. Varningar är inte alltid fel. De är mer som att kompilatorn informerar dig om att koden kanske inte kommer fungera som du tror att den ska göra.

Edit: lillahusets tips är väldigt bra att följa och jag brukar göra ungefär samma. Enda skillnaden är att jag använder g_ som prefix istället för versaler. Men detaljerna är inte det viktiga. Det viktiga är att du själv (och de du arbetar med om ni är flera som arbetar på samma kod) förstår vad det betyder, och att ni är konsekventa med att använda det systemet.
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Re: Blandade C++ frågor, nybörjarnivå

Inlägg av Magnus_K »

@lillahuset: Försöker "forma" en policy nu. Jobbar på det :wink:


Jo, det är meningen att det ska hänvisa till samma värde och jag vill att doButtonDebounce() ska använda den globala showData.
När jag tar bort allt inom parantesen så är det inte möjligt att använda showData++ längre.
Ok, tänkte jag, då måste jag importera den variabeln först genom extern ShowOnDisplay showData; eller extern showData; men kompilatorn nöjer sig inte.
Error nu för no 'operator++(int)' declared for postfix '++' [-fpermissive]
Mr Andersson
Inlägg: 1397
Blev medlem: 29 januari 2011, 21:06:30
Ort: Lapplandet

Re: Blandade C++ frågor, nybörjarnivå

Inlägg av Mr Andersson »

showData (den globala) är en enum så den har inga standard increment operators.
Cast'a till int eller överlagra operatorerna själv.
Om jag förstår koden rätt så vill du att showData ska hoppa till nästa steg för varje knapptryckning, och när den är på displayError ska den slå runt till displayMachines?
Du skulle kunna göra t.ex.

Kod: Markera allt

// Prefix increment (++val)
ShowOnDisplay& operator ++ (ShowOnDisplay& val)
{
	int newval = (static_cast<int>(val) + 1);
	if (newval > static_cast<int>(displayError))
		newval = static_cast<int>(displayMachines);

	val = static_cast<ShowOnDisplay>(newval);
	return val;
}

// Postfix increment (val++)
ShowOnDisplay& operator ++ (ShowOnDisplay& val, int)
{
	return ++val;
}
Men det kanske är att överkomplicera saken lite. Men poängen är att bara för att du har en enum så är det i grund och botten bara en vanlig integer och alltså inte begränsad till de värden du definierar. Den kommer inte slå runt av sig själv tills du kommer till maxvärdet för den integern. Jag vet inte om det står i standarden hur stor en enum normalt är om man inte anger någon bastyp och jag orkar inte leta upp det just nu :) Men det är garanterat mer än 2 bitar. (På x86 är det 32 bitar t.ex.)
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Re: Blandade C++ frågor, nybörjarnivå

Inlägg av Magnus_K »

Jag är jätteledsen Mr Andersson, men jag förstår faktiskt inte en rad av koden du skrivit. Det fungerar säkert kanon men det känns som att det är långt kvar tills jag är på din nivå. Fram tills dess vill jag bara skriva sånt jag själv fattar.

Du har förstått funktionen helt rätt.

Har gett enum en till chans innan jag gav upp och fick det faktiskt att fungera, efter 3000 kompileringar....

Så här ser det ut nu och spottar jag ut showData på terminalfönstret så vandrar det mellan 0-3 för varje knapptryckning.
Frågan är väl om ni ser något som jag inte ser? Några risker att göra så här?

Kod: Markera allt

enum ShowOnDisplay {
	displayMachines,
	displayTemp,
	displayHVRail,
	displayError,
	displayNull
};

void doButtonDebounce() {
	
	uint8_t reading = digitalRead(BUTTON_PIN);
	
	
	uint32_t debounceDelay = 50;
	
	if (reading != lastButtonState) {
		lastDebounceTime = millis();
//		
	}
	if ((millis() - lastDebounceTime) > debounceDelay) {
		

		if (reading != buttonState) {
			buttonState = reading;
			
			if (buttonState == HIGH) {
				extern ShowOnDisplay showData;           
				showData = ShowOnDisplay(showData +1);
				
				if (::ShowOnDisplay(showData) == 4) {
					showData = displayMachines;
				}
			}
		}
	}
	lastButtonState = reading;
}
kodar-holger
EF Sponsor
Inlägg: 922
Blev medlem: 26 maj 2014, 12:54:35
Ort: Karlskoga

Re: Blandade C++ frågor, nybörjarnivå

Inlägg av kodar-holger »

Ja du är ganska konsekvent med att använda variabler innan dom är initierade. Det brukar vara ett bra sätt att få huvudvärk.
Användarvisningsbild
Jan Almqvist
Inlägg: 1587
Blev medlem: 1 oktober 2013, 20:48:26
Ort: Orust

Re: Blandade C++ frågor, nybörjarnivå

Inlägg av Jan Almqvist »

Några tips:

Inga globala variabler, allt skickas som parametrar till funktionerna.

En egen funktion som gör "debounce" och returnerar true på positiv flank.

En annan egen funktion som räknar upp, eller ner, en variabel och hanterar att variabeln "slår runt".

Döp alla funktioner bör till något som börjar med ett verb.

Döp alla variabler till något som börjar med ett substantiv.

F.ö. fungerar väl inte kontruktionen 'if ((millis() - lastDebounceTime) > debounceDelay) ...' när millis() slår runt?
Användarvisningsbild
lillahuset
Gått bort
Inlägg: 13969
Blev medlem: 3 juli 2008, 08:13:14
Ort: Norrköping

Re: Blandade C++ frågor, nybörjarnivå

Inlägg av lillahuset »

F.ö. fungerar väl inte kontruktionen 'if ((millis() - lastDebounceTime) > debounceDelay) ...' när millis() slår runt?
Jo det fungerar utmärkt om inblandade variabler är unsigned och lika stora.
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Re: Blandade C++ frågor, nybörjarnivå

Inlägg av Magnus_K »

kodar-holger skrev:Ja du är ganska konsekvent med att använda variabler innan dom är initierade. Det brukar vara ett bra sätt att få huvudvärk.
Njoo, det var jag som klantade mig när jag försökte "rensa" koden för att göra den mer läsbar för er. Om jag inte missat någon så är dessa initierade så här:

Kod: Markera allt

uint8_t lastButtonState = LOW;
uint8_t buttonState = LOW;
uint32_t lastDebounceTime = 0;
ShowOnDisplay showData = displayMachines;
@Jan Almqvist:
Bra förslag!
Ska absolut dela på debounce-funktionen och uppräkningen. Döpa om funktionerna och variablerna kommer jag fundera lite mer på.
Precis som lillahuset säger så returnerar millis() en uint32 och dom två andra variablerna är också 32-bitar och unsigned. Det jag inte är riktigt hundra på är om det blir ett mini-fel om man trycker på knappen precis när den slår runt men det är ett mycket litet problem som jag inte bryr mig om.

Hur gör man när man "skickar parametrar till funktionerna"? Har det här något med "flytta pekaren" att göra?
Användarvisningsbild
lillahuset
Gått bort
Inlägg: 13969
Blev medlem: 3 juli 2008, 08:13:14
Ort: Norrköping

Re: Blandade C++ frågor, nybörjarnivå

Inlägg av lillahuset »

Det är en helt säker metod att göra som du gör sålänge variablerna är lika.

Allt inom parenteserna i funktionsanropet är "parametrar".
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Re: Blandade C++ frågor, nybörjarnivå

Inlägg av Magnus_K »

Ahaa ok!
Om jag initierar en variabel utanför main-loopen så blir väl denna global?
Om jag då inte bör ha några globala variabler, hur initierar jag dessa om dom ska ligga i en funktion? Då kommer väl deras värde alltid återgå varje gång den funktionen körs?
Användarvisningsbild
lillahuset
Gått bort
Inlägg: 13969
Blev medlem: 3 juli 2008, 08:13:14
Ort: Norrköping

Re: Blandade C++ frågor, nybörjarnivå

Inlägg av lillahuset »

Om du vill ha en lokal variabel som behåller sitt värde mellan anropen deklarerar du den "static" tex "static uint16_t magnus".
Då hamnar den inte på stacken utan i "vanliga" minnet alltså som globala variabler som definieras utanför funktionerna med den stora skillnaden att det inte går att komma åt den annat än i den funktion där den är definierad. Inte helt sant, man kan ha en pekar som "pekar åt helvete" och då kan vad som helst hända. :D
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Re: Blandade C++ frågor, nybörjarnivå

Inlägg av Magnus_K »

Hmm, ok. Förstår nog inte riktigt ändå, tyvärr.
Om jag har en lokal variabel som inte är statisk, blir det inte samma med den? Dvs att det enda som kan ändra värdet är just den specifika funktionen?

Om du läser detta Icecap, och minns ungefär vad du skrev så uppskattar jag verkligen om du har lust att göra ett till försök.
Vet att det var något bra men hann inte läsa igenom det noga innan det försvann.
zealotry
Inlägg: 918
Blev medlem: 9 oktober 2004, 22:28:40
Ort: Västerås

Re: Blandade C++ frågor, nybörjarnivå

Inlägg av zealotry »

Jo gällande den biten så är det ingen skillnad på static eller ej, båda varianterna kan bara manipuleras inifrån funktionen i fråga. Skillnaden är att en static behåller sitt värde mellan funktionsanropen.

Så om du har en variabel som du enbart vill använda inuti en specifik funktion men som samtidigt ska minnas det värde den hade förra gången funktionen anropades så ska du deklarera den som static.

Här är det förklarat lite mer med exempel:
http://stackoverflow.com/questions/5725 ... -c-program
Användarvisningsbild
Icecap
Inlägg: 26181
Blev medlem: 10 januari 2005, 14:52:15
Ort: Aabenraa, Danmark

Re: Blandade C++ frågor, nybörjarnivå

Inlägg av Icecap »

Kod: Markera allt

void Function_Something(int Parameter)
  {
  int Work;
  static int Counter;
  ... bla bla, programming stuff
  }
1: Work & Counter kan enbart "ses" av Function_Something().
2: Counter "stannar kvar" i det läge du lämnade den då den är static. Den tas inte heller från heap och ingen kan göra anspråk på den minnesplats som den använder.
3: Work finns när Function_Something() körs men kan återanvändas (platsen alltså) av andra rutiner så du vet aldrig vad den är när Function_Something() börjar.

heap är det "arbetsminne" som kompilern har att jobba med till diverse uppgifter. Den gör med heap lite som den vill varför man måste vara petnoga när man deklarerar variabler.

Om vi tar ovanstående exempel och utgår ifrån ANSI C (inte C++) kan Counter vara ett problem. Platsen avsätts permanent åt Function_Something() - men du vet inte vilket värde den har när programmet starter. Och då Function_Something() är den enda som "ser" den variabel kan man inte göra en initiering av den heller ju.

Men ponera att du gör en egen .C-fil som innehåller Function_Something() men att du sedan flyttar deklarationen av Counter ut från Function_Something():

Kod: Markera allt

static int Counter;

void Function_Something(int Parameter)
  {
  int Work;
  ... bla bla, programming stuff
  }

void Function_Something_Init(void)
  {
 Counter = 0;
  }
Vid att Counter är deklarerat "globalt" i den filen men är deklarerat som static betyder det att alla funktioner i den filen kan komma åt den utan knasigheter men att ingen andra delar av projektet (andra C-filer) vet om att den finns.

Det betyder att man kan dela upp ett program i en del underfunktioner som har var sin fil, dom man behöver tar man med i projektet och sedan är saken biff.

I C++ skapar man istället en klass och kan göra det samma fast mer avancerat.

Till detta ska läggas till att vissa kompilers har en funktion som nollställer arbetsminnet vid uppstart efter power-off men det är inget man ska räkna med, se det bara som en udda grej!!!
Skriv svar