jaha har börjat prova c++ nu och detta är väl kanske en lite "noobig" fråga. hehe. Men frågar man ingenting får man inget veta. hmm allltså - jag förstår att jag skulle kunna utöka parameterlistan med en int som jag binder whileslingan. Men detta kan väl inte vara det enda sättet att hitta slutet på slingan? Det här är arrayer, inte vektorer; stor skillnad! okej Jag skall förklara lite bättre. Jag tar även med pyttelite kod den här gången. Jag har kommit en bit på mitt problem och har förstått att jag måste använda pekare för det jag vill göra. Pekare är HELT nytt för mig :). Men jag har förstått att *pekVar = värdet som finns i variabeln, och att &pekVar = adressen där värdet finns lagrat. hmm. Sedan skall man omsätta detta till arrayer och funktioner. För det första ska funktionen ta emot en pekare till den array du vill nollställa. I din NollStallVektor funktion tar du emot en pekare till en pekare (eftersom x[] är samma sak som *x), vilket är fel. En sak till, när du kontrollerar om talet är noll använd inte '\0' som kontrollvärde utan helt enkelt bara 0. Japps, Håller som bäst på att försöka förstå de där grundstenarna med hjälp av ett par enkla exempel. >Ett tips är att läsa på mer om hur pekare och dubbelpekare fungerar, de är väldigt viktiga att kunna i hmmm... stör mig på detta nu hehe... Martin, du har rätt i att man i C++ använder referenser (helst), men som jag tidigare angav är att referenser är en typ av pekare. <b>Både memsetfunktionen och forslingan levererar mycket riktigt samma resultat. Men det blir inte "0" i utskriften? utan: <b>//så är här test1 = 4 och test2=8 - varför följer inte '64' med hit?</b> <b>//så är här test1 = 4 och test2=8 - varför följer inte '64' med hit?</b> Jag har testat lite nu med memset funktionen och det ska fungera som jag skrev... Ja, men du ska skicka in sizeof(tal) / sizeof(double) för att få antalet element, även kallat length. sizeof(x) returnerar bara storleken av arrayer med konstant storlek som är känd vid kompileringstillfället. Jag håller fortfarande fast vid att pekare är en bra sak att kunna, även om det finns färdiga template klasser för att bädda in användningen av dem. <b>>En fråga angående detta, finns vector templaten alltid tillgänglig i alla miljöer?</b> Ja, man är nog lite skadad för livet med den låga kvaliteten på kurserna som erbjuds på skolan. ;) Så alltså, här är samma program, skrivet med standardbiblioteket:Hitta null i en doublevektor?
jag försöker förstå hur returer, funktioner, vektorer hänger ihop med en enkel applikation som skall beräkna medelvärdet av tre tal.
som det ser ut nu:
#include <iostream>
using namespace std;
double NollStallVektor(double x[])
{
int n = 0;
while (x[n] != '\0')
x[n] = 0;
return x[n];
}
double LaddaTal(double x[])
{
int n=0;
while (x[n] != '\0')
{
cout << "Ange ett tal: > ";
cin >> x[n];
n++;
}
return x[n];
}
double BeraknaMedel(double x[])
{
int n=0;
double summa=0, medel=0;
while (x[n] != '\0')
{
summa += x[n];
n++;
}
medel = summa/n;
return medel;
}
void utskrift(double x)
{
int Hold;
cout << "Medelvärdet av talen är: " << x << endl;
cin >> Hold;
}
void main ()
{
double tal[2], medel=0;
tal[2] = NollStallVektor(tal);
tal[2] = LaddaTal(tal);
medel = BeraknaMedel(tal);
utskrift(medel);
}
Koden genererar en konstig utskrift. :D
Jag tror mitt problem ligger i min koll efter 'null' i while-looparna är fel. om så är fallet... Hur gör man där isåfall?
Vidare - är tilldelningen till tal[2] korrekt?
Sv: Hitta null i en doublevektor?
Sv:Hitta null i en doublevektor?
Beskriv vad du vill göra i två-tre korta meningar, så är det lättare att beskriva hur man bör göra och vad som är fel.
Det troliga felet i din kod är nog att du hanterar arrayer på fel sätt. Det finns inget Null-värde för double, är det korta svaret.Sv: Hitta null i en doublevektor?
Jag tar min lilla funktion som helt enkelt skall kunna anropas enligt (i princip):
double dTal[2];
NollStallVektor(dTal);
sedan skall dTal betraktas som en array med 0 i alla sina element.
Vidare har jag även hittat en trevlig funktion som heter "sizeof". Den har jag förstått returnerar storleken på de element man skickar med i funktionen. Man måste i den ta hänsyn till vilken datatyp man använder, tex en array med double returnerar antalelement*8. Eftersom varje Doubleposition är 8 byte stor.
Detta har jag ju då använt när jag skall bestämma hur många varv min loop skall snurra.
Vi tar in lite kod.
double NollStallVektor(double* x[])
{
for(int i=0; i<sizeof(x)/8;i++)
x[i] = 0;
return x;
}
Koden ovan klagar kompilatorn på. Det verkar dessutom som det är return-satsen som ställer till problem;
error C2440: 'return' : cannot convert from 'double *' to 'double'
under main ser det ut enligt:
void main ()
{
double tal[3];
double* pTal = &tal;
pTal = NollStallVektor(tal);
}
Här får jag klagomål enligt:
error C2440: 'initializing' : cannot convert from 'double (*__w64 )[3]' to 'double *'
samt:
error C2664: 'NollStallVektor' : cannot convert parameter 1 from 'double [3]' to 'double *[]'
Som sagt, hehe, vet inte hur rätt/fel ute jag är?
Sv:Hitta null i en doublevektor?
En modifierad variant av din funktion kan se ut såhär:
void NollStallVektor(double x[])
{
for(int i=0; i<sizeof(x)/sizeof(double);i++)
x[i] = 0;
}
Det finns dessutom en funktion som du kan använda för att sätta ett visst värde i ett visst utrymme i minnet, nämligen memset. Denna kod gör samma sak som ovan:
void NollStallVektor(double x[])
{
memset(x, 0, sizeof(x));
}
För mer information om memset och andra mem... funktioner se till exempel http://www.cplusplus.com/reference/clibrary/cstring/memset.html
Din main funktion ska se ut som:
void main ()
{
double tal[3];
NollStallVektor(tal);
// Nu innehåller tal enbart nollor med index 0, 1 och 2
}
Ett tips är att läsa på mer om hur pekare och dubbelpekare fungerar, de är väldigt viktiga att kunna i C++ programmering och en väldigt bra sak att kunna då man ska till exempel optimera kod etc.
Det är dessutom en av byggstenarna i C och C++ och man kan inte undvika dem. Kolla också in referenser i C++ (anges med & istället för * eller []) som gör samma sak som pekare, alltså pekar på ett ställe i minnet, men som "agerar" som om de vore deklarerade på normalt sätt. Svårt att förklara, så om någon annan kan förklara bättre är det bra.
void exempel(int &tal)
{
tal *= 2;
}
int main()
{
int testtal = 2;
exempel(testtal);
}
gör samma sak som
void exempel(int *tal)
{
*tal *= 2;
}
int main()
{
int testtal = 2;
exempel(&testtal);
}
Sv:Hitta null i en doublevektor?
Sv: Hitta null i en doublevektor?
Hursomhelst, hehe detta verkar ju fungera. Försöker sätta breakpoints och följa med variablerna så gott jag kan.
Både memsetfunktionen och forslingan levererar mycket riktigt samma resultat. Men det blir inte "0" i utskriften? utan:
tal[i] -9.2559592117431994e+061 double
Alla får samma värden... och antalet positioner blir rätt om jag skulle ändra vektorlängden på tal[].
När jag använder mig av forslingan så hoppar den direkt från { till } utan att passera raden där emellan? Skall det vara så?Sv: Hitta null i en doublevektor?
>C++ programmering och en väldigt bra sak att kunna då man ska till exempel optimera kod etc.
>Det är dessutom en av byggstenarna i C och C++ och man kan inte undvika dem.
Jag skulle säga tvärtom. Undvik pekare, du behöver dem inte i C++. Det du skall göra är att lära dig referenser.
Det kan dock ändå vara bra att förstå hur pekare fungerar eftersom andra språk som C# använder dem flitigt (I C# kallas de dock referenser bara för att förvilla).Sv:Hitta null i en doublevektor?
void main ()
{
double tal[8];
int test1 = sizeof(tal), test2 = sizeof(double);
//I debuggen nu, så är variablerna test1= 64 och test2=8 so far so good.
//Eftersom 64/8 ju blir 8 varv i den loopen jag skall köra.
NollStallVektor(tal);
}
Tittar vi sedan i funktionen igen.
void NollStallVektor(double x[])
{
int test1 = sizeof(x), test2 = sizeof(double);
//så är här test1 = 4 och test2=8 - varför följer inte '64' med hit?
//resultatet nu blir ju att forslingan nedan inte kommer snurra ett endaste varv... eftersom 4/8 = 0,5
for(int i=0; i<=(sizeof(x)/sizeof(double));i++)
{
x[i] = 0;
}
}
hmm. Man skall inte ropa hej för tidigt.
Sv:Hitta null i en doublevektor?
Om man ser på funktioner som ska tilldela en pekare ett värde, ofta förekommande i COM programmering (jag är ingen expert) kräver funktioner att man skickar in en pekare till en pekare som funktionen i sin tur tilldelar ett värde. Nu säger jag detta efter att ha tittat lite på DirectShow och hur det görs där.
Så jag skulle säga att använd referenser så långt det går, men undvik absolut inte pekare om de kommer väl till hands.
Kan man förresten ens gå igenom en array med hjälp av en referens som man kan med en pekare?Sv:Hitta null i en doublevektor?
tal[i] -9.2559592117431994e+061 double</b>
Det beror på att en double representeras på ett annat sätt än ett vanligt heltal.
Så memset fungerar inte i detta fall, i alla fall inte utan modifikation. Men vid array med andra typer där heltal används, strängar och heltal, fungerar det utmärkt!
Om du vill kontrollera hur en double sparas kan du köra något i stil med följande:
<code>
int main()
{
double tal = 0;
unsigned char * b = (unsigned char *) &tal;
do
{
cout << (int) *b << " ";
} while((int) ++b != (int) (&tal + 1));
cout << endl;
}
</code>
Ovanstående är skrivet direkt från huvudet och inte testat så jag kan inte garantera att det direkt går igenom. Men när det körs kommer den att skriva ut hur 0 representerat som ett flyttal sparas i minnet på datorn. Intel PC och MAC skulle ge ut olika resultat eftersom de sparar data på olika sätt. Intel baserade datorer sparar i "Little Endian" och Mac med Motorola processorer sparar i "Big Endian". http://www.cs.umass.edu/~verts/cs32/endian.htmlSv: Hitta null i en doublevektor?
Detta problem har jag faktiskt också stött på, och det häner bara när man har parametrar som tar emot en pekare ([] = * = pekare). Det är pekarens storlek du får fram med en sizeof och inte storleken på array.
Lösningen är att göra som alla funktioner gör, ta emot en extra parameter som säger hur många element som finns i array.
Varför det fungerar i main och inte i funktionen beror på att tal är deklarerat där och då får sizeof fram den totala storleken på tal.
Fråga mig inte exakt hur det fungerar, för det vet jag inte ;)Sv:Hitta null i en doublevektor?
<i>Lösningen är att göra som alla funktioner gör, ta emot en extra parameter som säger hur många element som finns i array.</i>
Ok. Detta är alltså det generella arbetssättet för att lösa detta - skicka med en extra parameter enligt sizeof(tal) i det här fallet. - :) hmm hade hoppats på att det räckte att skicka med arrayen som den är :) Nåja... får väl köra på detta då.Sv:Hitta null i en doublevektor?
#include <iostream>
using namespace std;
int main()
{
double tal[8];
double *t = tal;
unsigned char * b;
for(int j = 0; j < 2; j++)
{
b = (unsigned char *) tal;
t = tal;
if(j)
memset(tal, 0, sizeof(tal));
for(int i = 0; i < 8; i++)
{
do
{
cout << (int) *b << " ";
} while((int) ++b != (int) (t + 1));
cout << '\t' << *t << endl;
++t;
}
cout << endl;
}
system("PAUSE");
}
Om du kör denna kod visar den först vad som finns i minnet på de platser som reserverats för double array och sedan kör den andra varvet en memset på hela array och nollställer alla byte och skriver därefter ut allting igen.
Det sista värdet på varje rad är värdet på double.
<b>EDIT</b>
Utskriften hos mig blir:
204 204 204 204 204 204 204 204 -9.25596e+061
204 204 204 204 204 204 204 204 -9.25596e+061
204 204 204 204 204 204 204 204 -9.25596e+061
204 204 204 204 204 204 204 204 -9.25596e+061
204 204 204 204 204 204 204 204 -9.25596e+061
204 204 204 204 204 204 204 204 -9.25596e+061
204 204 204 204 204 204 204 204 -9.25596e+061
204 204 204 204 204 204 204 204 -9.25596e+061
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
Tryck ned valfri tangent för att fortsätta...
Sv: Hitta null i en doublevektor?
Sv:Hitta null i en doublevektor?
Men pekar-historien är, precis som Martin säger, ganska poänglös. Använd vector<double> istället, så slipper du alla problem. Sen kan du steg för steg introducera pekare och dynamiska arrayer.Sv: Hitta null i en doublevektor?
Kanske är ett stort fel på C++ kursen jag gått, som med mycket annat på min utbildning, men vi har aldrig gått djupare in i att använda de färdiga klasserna i bibliotek som std utan alltid gjort allting från grunden.
I kursen gjorde vi en helt egen string klass för att arbeta med strängar till exempel. Ok, man lär sig C++ grunderna men får inte så bra insikt i hur man "gör i verkligheten"...
Dessutom började vi programmeringen med två kurser i C och sedan gick vi över till en kurs i C++ och sedan en "programmeringsomgivning" kurs där "omgivningen" var Visual C++ 6, lite WIN32 och resten MFC.
Så det är förklaringen till varför jag föredrar att arbeta med pekare istället för med de färdiga klasserna...
En fråga angående detta, finns vector templaten alltid tillgänglig i alla miljöer?Sv:Hitta null i en doublevektor?
Ja, har du en C++-kompilator (= uppfyller standarden) så är den det.
Naturligtvis är det bra att förstå pekare, om inte annat för att det är grunden till hur nästan allt är uppbyggt i alla programmeringsspråk...
Men bättre att först lära sig språket, och hur man skriver snygg och oftast optimal kod (std::string är ofta potentiellt betydligt snabbare än en char *, om reference counting är implementerat). Och hur man får tag på andra bibliotek, hur man gör klasser, etc., etc. Sen kan man börja lära sig hur pekare i detalj fungerar.
Jag skulle nog säga att det faktiskt <b>är</b> ett stort fel med C++-kursen du har gått.Sv: Hitta null i en doublevektor?
Vi går aldrig in djupare på något utan lär oss bara grunder, om ens det.
Håller med dig Niklas att man nog ska lära sig språkets egenskaper först och sedan gå djupare in i hur pekare etc fungerar. Men eftersom vi började med C och gick över till C++ var vi vana vid att använda pekare och vi fick inte se en skymt av string eller andra klasser i standardbiblioteket.
Vi lärde oss nog att skapa egna klasser och templates men med dessa kunskaper fick vi uppgifter där vi skulle skapa länkade listor och den egna string klassen som jag nämnde om tidigare...
Nå, hur som haver, pekare är bra att förstå och kunna eftersom utan den kunskapen kan man inte skapa egna klasser liknande vector och string, i alla fall inte på ett optimalt sätt.Sv:Hitta null i en doublevektor?
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
//Behövs vid den alternativa fill-metoden
//#include <iterator>
//template-klass för att läsa T's från en stream
template<class T>
class read{
private:
std::istream& is;
public:
read(std::istream& i):is(i){}
T operator()(){
T tmp;
is >> tmp;
return tmp;
}
};
void fill(std::vector<double>& vek);
double average(const std::vector<double>& vek);
int main(){
std::vector<double> vek(3);
//Starta med 3 element.
//Om du använder den alternativa fill-metoden kan du använda:
//std::vector<double> vek;
fill(vek);
double medel=average(vek);
std::cout << "Medelvärde: " << medel;
return 0;
}
void fill(std::vector<double>& vek){
std::generate(vek.begin(),vek.end(),read<double>(std::cin));
//Eller, med frivilligt antal inskrivningar
//std::copy(std::istream_iterator<double>(std::cin),
// std::istream_iterator<double>(),std::back_inserter(vek));
}
double average(const std::vector<double>& vek){
return std::accumulate(vek.begin(),vek.end(),0.0)/vek.size();
}
Som man märker är det mycket enklare att använda standard-faciliteter, än att skriva alla loopar osv. själv. Man behöver egentligen nästan inte functionerna, eftersom de är så enkla!