C++ Funktioner - behöver vägledning

Permalänk

C++ Funktioner - behöver vägledning

Program som ska fråga efter ett antal tal, sedan skriva ut summa, medelv, största talet och näst största talet. Programmet skall skrivas ut med ett antal funktioner. (detta är skillnaden på min tråd mot andra med samma sorts program)

Jag har löst det utan funktioner, men så fort dom jäklarna ska inkluderas så blir det kaos.
Förstår principen tror jag men det är ngt eller massor jag missar...

Vill gärna ha lite tips som kan begripas av en nybörjare
(Hur skapar jag en box runt koden?)

#include<iostream> #include<string> #include<conio.h> #include<math.h> #include<iomanip> using namespace std; using namespace std; const char oe = char(148); const char ae = char(132); void inlasning(float inp); float utr(float antal, float nh_varde, float h_varde, float sum); float utskr(float antal, float nh_varde, float h_varde, float sum); int main() { float inp = 0, antal = 0, nh_varde = 0, h_varde = 0, sum = 0; inlasning(inp); utr(antal, nh_varde, h_varde, sum); utskr(antal, nh_varde, h_varde, sum); return 0; } void inlasning(float inp){ cout << "Ange värden" << endl; cin >> inp; } float utr(float antal, float nh_varde, float h_varde, float sum, float inp){ while (cin >> inp) { if (inp == 0) break; { if (inp > h_varde) { nh_varde = h_varde; h_varde = inp; } } if (inp > nh_varde && inp < h_varde) nh_varde = inp; sum += inp; antal++; return antal, nh_varde, h_varde, sum; } } float utskr(float antal, float nh_varde, float h_varde, float sum) { cout << "Summan = " << sum << endl; cout.setf(ios::fixed); cout << setprecision(1); cout << "Medelv" << ae << "rde = " << (double)sum / antal << endl; cout << "St" << oe << "rsta talet = " << h_varde << endl; cout << "N" << ae << "st st" << oe << "rsta talet = " << nh_varde << endl; _getch(); return antal, nh_varde, h_varde, sum; }

Permalänk
Legendarisk
Skrivet av skalman_08:

(Hur skapar jag en box runt koden?)

Med [code]...[/code]-taggar. Har redigerat in det åt dig.

Visa signatur

Abstractions all the way down.

Permalänk
Medlem
Skrivet av skalman_08:

Program som ska fråga efter ett antal tal, sedan skriva ut summa, medelv, största talet och näst största talet. Programmet skall skrivas ut med ett antal funktioner. (detta är skillnaden på min tråd mot andra med samma sorts program)

Jag har löst det utan funktioner, men så fort dom jäklarna ska inkluderas så blir det kaos.
Förstår principen tror jag men det är ngt eller massor jag missar...

Vill gärna ha lite tips som kan begripas av en nybörjare
(Hur skapar jag en box runt koden?)

Tja, för att kunna hjälpa bättre vore det bra om du skrev vad problemet är, att det blir kaos är inte superspecifikt

Men om jag vore du skulle jag ta en kik på hur dina funktioner är deklarerade. Börja där och se om du kan hitta nå problem. Du kan ju också kika på konceptet function overloading så kanske saker blir klarare.

Permalänk
Medlem

Några basic-saker som du verkar ha missat:
- typen som anges före funktionsnamnet anger vilken typ funktionen returnerar. Funktionen ska då returnera precis den typen, inget annat. Om funktionen inte behöver returnera något, använd typen void.
- funktionsargument blir normalt kopior i c++. För att kunna modifiera en variabel som kommit in som argument till en funktion så att ändringen kan ses i scopet där funktionen anropades så behöver du passa argumentet som en referens.

Visa signatur

h170i-plus i5 6600 2x8gb ddr3l 850 pro 256gb
Don't argue with an idiot. He will drag you down to his level, and beat you with experience.

Permalänk
Medlem
Skrivet av skalman_08:

void inlasning(float inp){ cout << "Ange värden" << endl; cin >> inp; }

Den här funktionen gör inte vad du tror att den gör. I C++ så skickas funktionsargument som värden, inte som referenser som i vissa andra språk. Det betyder att när du anropar funktionen som inlasning(inp) i main så kommer du att skicka inp:s värde som argument till funktionen. Alla ändringar du gör i inlasning på inp kommer därmed att göras på en lokal variabel i funktionen. Dvs:

int main() { float f = 2.0; inlasning(f); // Samma som inlasning(2.0). } void inlasning(float inp){ // inp är en lokal variabel i funktionen. Den existerar endast i funktionen. cout << "Ange värden" << endl; cin >> inp; // Här tilldelas inp. } // Här slutar inp att existera.

Så din funktion läser med andra ord in ett värde från användaren, och slänger sedan bort värdet utan att göra något med det. Vad du vill göra är antingen att returnera värdet från funktionen, eller skicka en referens/pekare till variabeln som argument. Även referenser och pekare skickas som värden i C++, men en kopia av t.ex. en referens pekar fortfarande på samma variabel som ursprungsreferensen.

float inlasning() { return 2.0; } ... float f = inlasning(); // f = 2.0 void inlasning(float &inp) { inp = 2.0; // inp är en referens till variabeln som skickades som argument till funktionen. När du ändrar på inp så ändrar du på den variabeln istället. } ... inlasning(f); // f = 2.0

I ditt fall så är det första sättet att skriva funktionen förmodligen bäst, eftersom du ändå inte använder värdet av inp som skickas in till funktionen. Det andra sättet tillåter dock att du har flera variabler som du kan ändra på, medan det första sättet endast låter dig att returnera ett värde.

Skrivet av skalman_08:

float utr(float antal, float nh_varde, float h_varde, float sum, float inp){ while (cin >> inp) { .... return antal, nh_varde, h_varde, sum; } }

Detta fungerar inte, C++ tillåter endast att du returnerar ett värde från en funktion, inte flera. Om du behöver returnera flera värden så får du antingen klumpa ihop dem i en datastruktur, eller låta funktionen ta referenser eller pekare till variabler.

Permalänk
Medlem
Skrivet av skalman_08:

Program som ska fråga efter ett antal tal, sedan skriva ut summa, medelv, största talet och näst största talet. Programmet skall skrivas ut med ett antal funktioner. (detta är skillnaden på min tråd mot andra med samma sorts program)

Jag har löst det utan funktioner, men så fort dom jäklarna ska inkluderas så blir det kaos.
Förstår principen tror jag men det är ngt eller massor jag missar...

Vill gärna ha lite tips som kan begripas av en nybörjare
(Hur skapar jag en box runt koden?)

..Kod..

Ser bra ut för en nybörjare, men där är några skönhetsmissar
Har inte jätte mycket tid då jag måste iväg o jobba snart men vad jag kan se, har du två(2) "inskrivning(float inp)".
Sedan så måste funktionerna vara ovanför Main samt ovanför andra funktioner som använder sig av andra funktioner.
Låter rörigt, kan förklara bättre ikväll om ingen har förtydligat min rappakalja.

Visa signatur

Dator: Ett metall chassi med varierande komponenter på insidan.

Permalänk
Medlem

Fixar

Det viktigaste du har missförståt är hur du flyttar värden mellan funktioner. Sen försöker du inte riktigt dela upp så mycket som du borde.

Vi börjar från start. Du ska läsa in värden på ett ställe och sen använda det. Inte göra som du och ha cin på flera ställen. Jag gör det lätt för mig och använder vector. Så funktionen nedan skapar en vector med typen floats och sen läser jag in så länge man skriver ett värde precis som du gjorde i utr. Vektorn returneras sen med hjälp av return.

vector<float> inlasning(){ cout << "Ange värden, avsluta med s" << std::endl; //funkar med vilken bokstav som helst men bara för att ge något ;) vector<float> oVals; float tmpIn; while (cin >> tmpIn) { oVals.push_back(tmpIn); } return oVals; }

i utr funktionen är det endast in och ut information du har problem med. return skickar bara tillbaka ett object. Du kan skapa upp en struct men enklare att använda referenser som såhär. Du kan googla på referens och rangebased loop eller bara använda en vanlig for loop

void utr(float& antal, float& nh_varde, float& h_varde, float& sum, vector<float>& iVals){ for (auto inp : iVals) { if (inp == 0) break; { if (inp > h_varde) { nh_varde = h_varde; h_varde = inp; } } if (inp > nh_varde && inp < h_varde) nh_varde = inp; sum += inp; antal++; } }

main och topp har bara små ändringar som gör att det funkar med de nya funktionerna

#include<iostream> #include<string> #include<conio.h> #include<math.h> #include<iomanip> #include <vector> using namespace std; const char oe = char(148); const char ae = char(132); vector<float> inlasning(); void utr(float& antal, float& nh_varde, float& h_varde, float& sum, vector<float>& iVals); void utskr(float antal, float nh_varde, float h_varde, float sum); int main() { float inp = 0, antal = 0, nh_varde = 0, h_varde = 0, sum = 0; auto vals = inlasning(); utr(antal, nh_varde, h_varde, sum, vals); utskr(antal, nh_varde, h_varde, sum); return 0; }

Man kan även göra din utr funktion mer enkel och mycket snabbare på stora mänged genom att att använda std funktioner

#include <algorithm> #include <functional> void utr(float& antal, float& nh_varde, float& h_varde, float& sum, vector<float>& iVals){ sort(iVals.begin(), iVals.end(),std::greater<float>()); antal = iVals.size(); if(antal<2) return; h_varde = iVals[0]; nh_varde = iVals[1]; sum = 0; for (auto inp : iVals) sum += inp; }

Permalänk

Jag får allt att fungera med din kod. Nu måste jag bara förstå den också

Skrivet av MrGorgar:

Det viktigaste du har missförståt är hur du flyttar värden mellan funktioner. Sen försöker du inte riktigt dela upp så mycket som du borde.

Vi börjar från start. Du ska läsa in värden på ett ställe och sen använda det. Inte göra som du och ha cin på flera ställen. Jag gör det lätt för mig och använder vector. Så funktionen nedan skapar en vector med typen floats och sen läser jag in så länge man skriver ett värde precis som du gjorde i utr. Vektorn returneras sen med hjälp av return.

vector<float> inlasning(){ cout << "Ange värden, avsluta med s" << std::endl; //funkar med vilken bokstav som helst men bara för att ge något ;) vector<float> oVals; float tmpIn; while (cin >> tmpIn) { oVals.push_back(tmpIn); } return oVals; }

Nej, jag fattar inte riktigt hur värdena vet var dom ska och hur man skickar dom dit. Är det return som skickar själva värdet?
Skulle du kunna förklara vector-blocket mer utförligt?
Sen skulle jag vilja att användaren kan avsluta med 0 istället för valfri bokstav.
Var i koden ändrar jag detta?

Citat:

void utr(float& antal, float& nh_varde, float& h_varde, float& sum, vector<float>& iVals){ for (auto inp : iVals) { if (inp == 0) break; { if (inp > h_varde) { nh_varde = h_varde; h_varde = inp; } } if (inp > nh_varde && inp < h_varde) nh_varde = inp; sum += inp; antal++; } }

}

Har läst om referenser nu och jag förstår hur det fungerar i de enkla exemplen att man skapar flera variabler som egentligen är samma sak eller att dom följer varandra om värdet ändras.. men svårare att förstå i min kod.

Varför behöver jag referenser?? Känns som man komplicerar till allt bara...
Varför kan man inte bara använda samma variabler istället?

Skulle du kunna förklara for-loopen?

Citat:

main och topp har bara små ändringar som gör att det funkar med de nya funktionerna
[code]
#include<iostream>
#include<string>
#include<conio.h>
#include<math.h>
#include<iomanip>
#include <vector>

using namespace std;
const char oe = char(148);
const char ae = char(132);

vector<float> inlasning();
void utr(float& antal, float& nh_varde, float& h_varde, float& sum, vector<float>& iVals);
void utskr(float antal, float nh_varde, float h_varde, float sum);

int main() {

float inp = 0, antal = 0, nh_varde = 0, h_varde = 0, sum = 0;
auto vals = inlasning();
utr(antal, nh_varde, h_varde, sum, vals);
utskr(antal, nh_varde, h_varde, sum);

return 0;
}

vad är auto vals?

Är ledsen om jag kommer med jobbiga/dumma frågor.
Läser en kurs nu på distans men min lärare är helt värdelös och borde inte ens kalla sig för lärare...
Ingen kursliteratur...
Inga svar på mina frågor om div problem/uppg...
Ingen feedback på något...
Så detta gör det extremt svårt och jag har i princip fått lära mig själv helt och hållet.

Tack för svar!

Permalänk
Skrivet av Creatooz:

Ser bra ut för en nybörjare, men där är några skönhetsmissar
Har inte jätte mycket tid då jag måste iväg o jobba snart men vad jag kan se, har du två(2) "inskrivning(float inp)".
Sedan så måste funktionerna vara ovanför Main samt ovanför andra funktioner som använder sig av andra funktioner.
Låter rörigt, kan förklara bättre ikväll om ingen har förtydligat min rappakalja.

Tackar kul.
Alltså vad jag förstått så deklarerar man ovan main och sen skriver kodblocket nedan.
Har även sett att folk deklarerar ovan main och skriver ut kodblocket direkt under.
Vet inte vad som är rätt eller enklast men såhär är så jag fått "lära" mig av min "lärare"..

Tack för svar!

Permalänk
Medlem
Skrivet av skalman_08:

Tackar kul.
Alltså vad jag förstått så deklarerar man ovan main och sen skriver kodblocket nedan.
Har även sett att folk deklarerar ovan main och skriver ut kodblocket direkt under.
Vet inte vad som är rätt eller enklast men såhär är så jag fått "lära" mig av min "lärare"..

Tack för svar!

Deklaration:

int func();

Definition:

int func() { return 42; }

En funktion måste vara deklarerad innan du kan använda den, men inte definierad (den måste så klart vara definierad nånstans). En definition räknas även som deklaration. Så du kan göra som du gjort nu, deklarera funktionerna innan du använder dem och definiera dem nedanför main. Eller så kan du bara definiera funktionerna innan du använder dem (dvs. ovanför main), så behöver du inte deklarera dem separat.

Permalänk
Medlem
Skrivet av skalman_08:

Tackar kul.
Alltså vad jag förstått så deklarerar man ovan main och sen skriver kodblocket nedan.
Har även sett att folk deklarerar ovan main och skriver ut kodblocket direkt under.
Vet inte vad som är rätt eller enklast men såhär är så jag fått "lära" mig av min "lärare"..

Tack för svar!

Ja precis det jag menade, om man skall vara helt korrekt skall man dekla ovan Main och skriva under.
Själv är jag på tok för lat för att göra detta, vilket resulterar i att jag skriver Main sist så att säga.

Sedan med hur man skickar värden och vad som retuneras, kan hjälpas med ett exempel.

#include "stdafx.h" #include <iostream> using namespace std; int addera(int varde1, int varde2); int main() { int summa; int tal1 = 10; int tal2 = 20; summa = addera(tal1, tal2); <-- Eftersom "addera" kräver två int's, skickar vi två tal till funktionen. cout << "Summan av 10 och 20 = " << summa << endl; cin.get(); return 0; } int addera(int varde1, int varde2) { <-- I Funktionen kallar vi variablerna för varde1 och varde2. return varde1 + varde2; <-- Funktionen vet vad varde1 och varde2 är, eftersom vi skickade tal1 och tal2 till den innan, funktionen gör en "return" på vad varde1 och varde2 är, eller om vi tar bort det och skriver 10, kommer funktionen alltid att skicka tillbaka 10 som svar oavsätt vad vi försöker addera. }

Dold text
Visa signatur

Dator: Ett metall chassi med varierande komponenter på insidan.

Permalänk
Skrivet av deppan:

Några basic-saker som du verkar ha missat:
- typen som anges före funktionsnamnet anger vilken typ funktionen returnerar. Funktionen ska då returnera precis den typen, inget annat. Om funktionen inte behöver returnera något, använd typen void.
- funktionsargument blir normalt kopior i c++. För att kunna modifiera en variabel som kommit in som argument till en funktion så att ändringen kan ses i scopet där funktionen anropades så behöver du passa argumentet som en referens.

Ja det där har jag inte riktigt hajat helt.

Tex.
float utr (...); som jag nu förstår ska vara void utr (...);
"returnerar" väl ett värde i funktionen i form av uträkningen?
Eller är det endast när man skriver return; i slutet av kodblocket? Hur ska jag tänka med användandet av return?

fattar inte riktigt när man tex ska använda void utr(void) kontra float utr(float)

Tack för svar!

Permalänk
Medlem
Skrivet av skalman_08:

fattar inte riktigt när man tex ska använda void utr(void) kontra float utr(float)

"void utr()" är en funktion som inte returnerar något värde, medan "float utr()" är en funktion som returnerar en float. return bestämmer vad som ska returneras från funktionen. En funktion som deklarerar att den ska returnera något måste göra det, annars får man odefinierat beteende (dvs. precis vad som helst kan hända). Så t.ex.:

int f() { return 4; }

f är här en funktion som returnerar en int med värdet 4. Den kan användas t.ex. för att tilldela en variabel det värdet:

int i = f(); // i = 4

return betyder också att funktionen avslutas, så eventuell kod efter return kommer inte att köras (s.k. död kod). Man kan också ha flera return i en funktion om man så vill:

// Denna funktion returnerar true om n är udda, false om n är jämnt. bool udda(int n) { if (n % 2 == 0) { // Om n är jämnt delbart med två => n är inte udda. return false; } else { return true; cout << "Jag är död kod och kommer aldrig att skrivas ut!\n"; } }

Permalänk
Medlem

Ursäkta sent svar men här kommer svar på dina frågor

Skrivet av skalman_08:

Jag får allt att fungera med din kod. Nu måste jag bara förstå den också

Nej, jag fattar inte riktigt hur värdena vet var dom ska och hur man skickar dom dit. Är det return som skickar själva värdet?

När du definierar en funktion definierar du retur typen också, t.ex
float utr(..)
där du då har sagt att ett returvärde av typen float skickas tillbaka genom "return". Notera att bara ett värde/object kan skickas tillbaka och det är orelaterat till vad du skickar in. Vi kan gå runt denna begränsning genom att använda referens i input variablerna.

Skrivet av skalman_08:

Skulle du kunna förklara vector-blocket mer utförligt?
Sen skulle jag vilja att användaren kan avsluta med 0 istället för valfri bokstav.
Var i koden ändrar jag detta?

i while loopen kan du kontrolera om "tmpIn" är lika med 0 och i så fall använda "break;" för att hoppa ur while loopen. Skriver inte exakt för att lämna lite som övning
Angående vector, det finns bra guider där ute för just vector t.ex. Vector guide

Skrivet av skalman_08:

Har läst om referenser nu och jag förstår hur det fungerar i de enkla exemplen att man skapar flera variabler som egentligen är samma sak eller att dom följer varandra om värdet ändras.. men svårare att förstå i min kod.

Varför behöver jag referenser?? Känns som man komplicerar till allt bara...
Varför kan man inte bara använda samma variabler istället?

Det är din sista mening som vi följer genom att använda referenser. En referens ger oss möjligheten att använda samma variabel/objekt inne i funktionen som utanför. I normalfallet skapas en kopia vilket gör att alla ändringar du gör förstörs i slutet av funktionen. I java och c# är referens default, så var inte rädd att använda det i c++.
Så kort, vi använder referens för att kunna ändra på variablerna som skickades in och att detta påverkar koden som anropade funktionen.

Skrivet av skalman_08:

Skulle du kunna förklara for-loopen?

vad är auto vals?

auto låter kompilatorn bestämma typen beroende på högersidan. Så om utrycket på höger sida ger double skulle auto deklarera double. I vårt fall ger den float.

for loopen går igenom alla värden i vektorn på ett enkelt sätt. Det blir samma effekt som nedan fast utan index problem

for(size_t i=0; i<iVals.size(); i++) { auto inp = iVals[i]; }

Skrivet av skalman_08:

Är ledsen om jag kommer med jobbiga/dumma frågor.
Läser en kurs nu på distans men min lärare är helt värdelös och borde inte ens kalla sig för lärare...
Ingen kursliteratur...
Inga svar på mina frågor om div problem/uppg...
Ingen feedback på något...
Så detta gör det extremt svårt och jag har i princip fått lära mig själv helt och hållet.

Tack för svar!

Det kan vara jobbigt att läsa en kurs på distans med lärare som kanske inte är så intresserade. En bra nybörjar guide som förklarar allt som vi har tagit up här finns på den utmärkta sidan cplusplus
cpp guide

Permalänk
Medlem

Det är inte så krångligt egentligen tänk så här:

1. Först initierar/deklarerar du dina funktioner som du har gjort. Vanligtvis ovanför Main.

T.ex.
int funktion(int a, int b); Använder du inte typen void så måste ett värde returneras. I detta fall ett värde av typen int.

2. inuti main kan du sedan anropa funktionen genom att skriva funktionens namn & inkludera eventuella parametrar.

T.ex.
funktion(a, b); eller om du vill returnera ett värde från en funkltion så: värde = funktion(a,b);

3. Men innan du kan göra det så måste du skapa funktionerna. Detta görs vanligvis utanför & nedanför main(){};

T.ex.
int funktion(int a, int b){
// dina uträkningar

return uträknat_värde;
}

4. vid anropet av funktionen(i main(){} eller från funktion till funktion) sätter du en variabel som fångar det returnerade värdet från funktionen.

T.ex:
värde = funktion(a,b);

5. nu är värdet returnerat & du kan använda det inuti main(){}.

Där var lite basics !

Lycka till.

Visa signatur

[IT-Dept]
Ryzen 1700 OC - 32 - 1070