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

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
sodjan
EF Sponsor
Inlägg: 43247
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

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

Inlägg av sodjan »

Rent teoretiskt går det att skriva kod som gör en "windup" på stacken
och bygger ett "call-tree" bakåt, men det är mest debuggers och
crasch-dump analyzers som brukar hålla på ed sådant.

Enklast är ju att göra precis så som du visar, man skickar med en
parameter som visar *vad* som ska göras. Däremot så vet man
(alltså funktionen) ju inte *vem* som bad om att det skulle göras,
men spelar det någon roll? Om du vill det så kan du ha en extra
parameter där du skickar med något annat, men det finns inget
enkelt sätt att automatisera det. Kanske med någon precompiler
parameter... (?).


I objektorienterade miljöer (t.ex Javascript) är det däremot ganska
vanligt att man vill att funktioner ska agera på objekt som finns
i kontexten hos den som anropande. Även Python har en sådan
struktur. Men då talar vi mer om klasser, metoder o.s.v. än det
som vi normalt kallar för "funktioner" i icke-OO språk...
Mr Andersson
Inlägg: 1409
Blev medlem: 29 januari 2011, 21:06:30
Ort: Lapplandet

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

Inlägg av Mr Andersson »

> Kanske med någon precompiler parameter... (?)

Man skulle kunna använda __func__, t.ex.

Kod: Markera allt

#include <iostream>

void __doSomething_impl(const char* caller, int arg1, int arg2)
{
	std::cout << "Called by " << caller << std::endl;
}

#define doSomething(arg1, arg2) __doSomething_impl(__func__,arg1,arg2)

int main()
{
	doSomething(1, 2);
	return 0;
}
Men det är väl inget jag skulle rekommendera. Dels för att __func__ kräver C99 eller nyare, och dels för att det finns ju inget som hindrar användaren från att anropa __doSomething_impl direkt med ett påhittat funktionsnamn.

edit: const-correctness
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 »

sodjan skrev: I objektorienterade miljöer (t.ex Javascript) är det däremot ganska
vanligt att man vill att funktioner ska agera på objekt som finns
i kontexten hos den som anropande. Även Python har en sådan
struktur. Men då talar vi mer om klasser, metoder o.s.v. än det
som vi normalt kallar för "funktioner" i icke-OO språk...
I C skickar man bara med en pekare så löser det sig.
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 »

Oj vad svar. Tack!

Det känns skönt att höra att det inte är helt vansinne att göra som jag påbörjat. Det lät ju vettigt att göra enligt Mr Andersson's exempel och göra enums av argumenten som ska vidare. Det borde bli överskådligt.

Anledningen till att jag frågade är för att jag sökte runt lite först och hittade exempel på det här med "skicka pekare" men visste om det var en "accepterad" metod och om det skulle fungera för mitt ändamål.
Pratar alltså om det exempel Jan Almqvist skriver void someFunction( CObject *sender );.

@sodjan:
Det där låter avancerat det där med windup etc men du har helt rätt i att det blir ju snarare att man skickar med en parameter om vad som ska göras, inte vem som skickar den.

@Mr Andersson angående precompiler förslaget:
Jättetack :tumupp:
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 har deklarerat variablen i som static i for-loopen för att jag vill återgå till samma ställe i loopen när jag kallar doSegmentCalcMachines() igen.
Men när "nollas" denna då?

Idén med funktionen är att varje gång den kallas så ska den gå igenom "ethernetBuffer" bit för bit och så fort den träffar en etta så kommer switch-funktionen göra sitt och sedan avbryta for-loopen.
Men då vill jag att när doSegmentCalcMachines() kallas igen så ska for-loopen återta sitt tidigare värde men också rulla om när den nått 15.

Ber om ursäkt redan nu om det är oförståeligt men jag hoppas koden kan tala lite för mig här.

Kod: Markera allt

uint16_t doSegmentCalcMachines() {
	
	uint16_t ethernetBuffer = 0;				// ..... ta in ethernetbuffern här
	uint16_t machineBuffer = 0;
	
	for(static uint8_t i=0; i<16; i++) {
		
		if(ethernetBuffer & (1<<i)) {
			
			switch (i) {
				case 0:
					machineBuffer |= L_NUMBER[0] << 8;
					machineBuffer |= R_NUMBER[1];
				break;
				case 1:
					machineBuffer |= L_NUMBER[0] << 8;
					machineBuffer |= R_NUMBER[2];
				break;
				
				...

				default:
				break;
			}
		}
		break;
	}
	return machineBuffer;
}
sodjan
EF Sponsor
Inlägg: 43247
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

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

Inlägg av sodjan »

Med tanke på villkoret i if satsen så kan väl i inte vara både 0 och 1?
D.v.s. att för att komma till case satsen över huvud taget så måste
väl i vara antingen 0 eller 1 (vilket det nu är).

För övrigt är koden ett bra exempel på att det ofta är onödigt
och olämpligt att ha variabler som heter "i". Se min första
fråga ovan... :-)

Men, i kommer ju att sättas till 0 vad varje anrop av funktionen.
Det står ju så i for satsen. "Static" just där har nog ingen funktion.
Om jag inte fattar helt fel...

Du får nog ha en annan variabel som är "static" och en for sats
med for(uint8_t i=tmp; i<16; i++) och inne i loopen sätta "tmp=i".
På det sätter borde du kunna starta om loopen från föregående i.
Värdet på tmp är ju "static" och överlever mellan olika anrop.

Sedan kan du kolla värdet på tmp i början (före for(...)) och ställa
tillbaka tmp till 0 om det behövs.
Användarvisningsbild
adent
Inlägg: 4245
Blev medlem: 27 november 2008, 22:56:23
Ort: Utanför Jönköping
Kontakt:

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

Inlägg av adent »

Hej!

Jag fick inte min kompilator att köpa det, vilket väl kan anses som vettigt.
Det här blir dock samma sak:

Kod: Markera allt

#include <stdio.h>

int foo(void)
{
  static int i=0;

  for(;i<3;i++)
  {
    printf("%d\n",i);
  }
  printf("foo done\n");
}

int main(void)
{
  foo();
  foo();
}
Utskriften blir då:

Kod: Markera allt

0
1
2
foo done
foo done
Eftersom i blir 3 efter första anropet till foo() kommer loopen inne i foo() inte att köras vid andra anropet. Villkoret i<3 fallerar direkt vid andra anropet just för att i redan är 3.
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 »

Hej!
och tack för engagemanget!

Sitter och testar sodjan's förslag med att använda en tmp-variabel. Det borde väl bli ungefär som nedan va?

Kod: Markera allt

#include <stdio.h>

int foo(void)
{
  static int tmp_i=0;

  for(int i=tmp_i;i<3;i++)
  
  tmp_i = i;

  {
    printf("%d\n",i);
  }
  printf("foo done\n");
}

int main(void)
{
  foo();
  foo();
}
sodjan
EF Sponsor
Inlägg: 43247
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

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

Inlägg av sodjan »

Förrutom att adents förslag kanske är bättre (även om jag personligen har lite
svårt med for satser utan startvärde), så borde väl tmp_i = i; ligga inom klamrarna...

Du bör väl även ha någon metod att återställa startvärdet...

Kod: Markera allt

    #include <stdio.h>
     
    int foo(void)
    {
      static int tmp_i=0;
      if (tmp_1 == 2) tmp_1 = 0;
      for(int i=tmp_i;i<3;i++)
      {
        tmp_i = i;
        printf("%d\n",i);
      }
      printf("foo done\n");
    }
     
    int main(void)
    {
      foo();
      foo();
    }
Nu så har ju just det exemplet inget som avbryter for loopen,
så det hela haltar ju lite...

> Sitter och testar...

Kanske bäst att du testar färdigt först... :-)
sodjan
EF Sponsor
Inlägg: 43247
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

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

Inlägg av sodjan »

Här är ett exempel som gör ungefär det du vill.
Den bryter loopen på 4 och 8 och startar om vid 10.

Kod: Markera allt

    #include <stdio.h>

    void foo(void)
    {
      static int tmp_i=0;
      if (tmp_i == 10) tmp_i = 0;
      for(int i=tmp_i+1; i<11; i++)
      {
        tmp_i = i;
        printf("%d\n",i);
        if (i % 4 == 0 )
        {
          break;
        }
      }
      printf("foo done\n");
    }

    int main(void)
    {
      foo();
      foo();
      foo();
      foo();
      foo();
      foo();
      foo();
      foo();
    }

Kod: Markera allt

$ cc for
$ link for
$ run for
1
2
3
4
foo done
5
6
7
8
foo done
9
10
foo done
1
2
3
4
foo done
5
6
7
8
foo done
9
10
foo done
1
2
3
4
foo done
5
6
7
8
foo done
$
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 »

Har sagt det innan men säger det igen: Uppskattar verkligen tiden ni lägger ni på att hjälpa till!

Det som löser det fint för mig blir att använda en tmp-variabel och lägga till en if-sats (innan for-loopen) som nollar den om den nått max.

Tack än en gång :bravo:
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 »

Använd while istället så behöver du inte krångla med två variabler.
Användarvisningsbild
Jan Almqvist
Inlägg: 1652
Blev medlem: 1 oktober 2013, 20:48:26
Ort: Orust

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

Inlägg av Jan Almqvist »

Jag tycker att man ska undvika 'static' så långt det är möjligt i funktioner. Risken är att man får problem förr eller senare t.ex. om samma funktion anropas från flera olika trådar eller vid rekursion. Man kan istället skicka variabeln som parameter "by reference".
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 »

Håller med dig att man ska tänka sig för noga.
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:
Låter intressant! Tack för tipset!

@Jan Almqvist:
Projektet börjar lida mot sitt slut och har lagt med det här i punkten att-gå-igenom när det är "klart". Ska göra mitt bästa att kunna rensa lite static's :tumupp:
Skriv svar