Permalänk
Medlem

@kundun: hmm så en instans betyder att det är en kopia? känns som allt är så jävla förvirrande och det är så svårt att lära sig tycker jag, så många nya ord samtidigt som man lär komma ihåg vad de gör typ

Permalänk
Medlem

@perost: det är så fruktansvärt svårt att förstå känns det som... har så svårt med alla nya ord och vad de gör.. känns helt omöjligt att klara detta haha

Permalänk
Medlem
Skrivet av Korvulla:

@perost: det är så fruktansvärt svårt att förstå känns det som... har så svårt med alla nya ord och vad de gör.. känns helt omöjligt att klara detta haha

Ok, vi tar och kör lite grundkurs i datateknik då, det kanske kan ge dig ett annat perspektiv. För vårt syfte kan vi se en dator som en processor och en mängd primärminne (också känt som RAM-minne). Minnet är uppdelat i bytes, där varje byte har en address (första byten har address 1, andra byten 2, osv.). Minnet kan innehålla två saker: instruktioner till processorn samt data.

När ett program ska köras så laddas det först in i minnet, sedan börjar processorn exekvera instruktionerna i den följd de ligger i minnet. Några exempel på instruktioner är t.ex. att addera två tal som är lagrade i minnet, att jämföra om ett värde i minnet har ett visst värde, eller att hoppa till en angiven plats i minnet. Detta är förstås en extrem förenkling, men hur en dator i grunden faktiskt fungerar.

Så ett exempel på ett program skulle kunna vara t.ex (siffrorna till vänster är minnesaddresser):

1: ADD $3, $4, $5 // Addera värden på address 3 och 4, och lagra resultatet på address 5. 2: END // Avsluta programmet 3: 34 // Här börjar data, detta är första värdet vi vill addera. 4: 21 // Andra värdet att addera. 5: 0 // Här kommer resultatet att lagras, d.v.s. 55.

Detta är vad som brukar kallas för assembler, vilket är den lägsta nivån som människor i regel programmerar på. Just detta är förstås väldigt förenklat, och ignorerar saker som t.ex. att ADD-instruktionen jag hittade på inte skulle få plats i en byte.

Så nu kan vi förklara vad en variabel är, det är helt enkelt en namngiven minnesaddress. När du deklarerar en variabel i din kod så kommer kompilatorn att reservera en bit minne, och när koden kompileras byter kompilatorn helt enkelt ut alla variabelnamn mot deras respektive minnesaddress. D.v.s. variabelnamnen är bara till för att göra det enkelt för oss människor, när koden väl kompilerats behövs de inte längre (annat för felsökning).

Typen som en variabel har bestämmer hur mycket minne variabeln tar upp. En vanlig int är t.ex. ofta 32 bitar stor, d.v.s. 4 bytes. I mitt kodexempel ovan antogs det att alla värden är 8 bitar, för att de skulle få plats på en minnesplats, men i praktiken tar variabler ofta upp flera minnesplatser. Men även om en variabel tar upp flera minnesplatser så är det dess första minnesplats som används som address, och det är sen upp till kompilatorn att generera rätt instruktioner så att storleken på variablerna hanteras korrekt.

En array är sedan ett sätt att namnge ett block av minne som kan addresseras som separata element. D.v.s. att deklarera en array x[3] är samma sak som att deklarera tre variabler x1, x2 och x3. Skillnaden är att en array är enklare att hantera som en enhet, och att minnet för en array är i ett sammanhängande block medan separata variabler kan vara utspridda i minnet. T.ex. skulle int x[3] kunna se ut så här i minnet (med värdena i hexadeximalt format):

33: ... 34: 0x43 // Här börjar arrayen med x[0] som har värdet 0x4325A5FE. 35: 0x25 // Andra byten i x[0] 36: 0xA5 // Tredje byten i x[0] 37: 0xFE // Fjärde och sista byten i x[0] 38: 0x23 // Här börjar nästa element x[1] som har värdet 0x23C42342 39: 0xC4 // Andra byten i x[1], etc. 40: 0x23 41: 0x42 42: 0x92 // Här börjar sista elementet x[2] som har värdet 0x920EF3D3 43: 0x0E 44: 0xF3 45: 0xD3 // Slut på arrayen. 46: ...

Anledningen till att jag angav värdena i hexadecimalt format är för att man då kan slå ihop dem för att få hela värdet. D.v.s. värdet på x[0] är inte summan av fyra byte, utan fyra byte som ligger på rad efter varandra i minnet och ses som ett värde.

Funktioner fungerar genom att man sparar vart man är någonstans på en särskilt plats (ett så kallat register), lagrar funktionsargumenten på en överenskommen plats, och sedan hoppar till funktionen. Ta denna enkla C++-kod t.ex.:

int add(int x, int y) { return x + y; } int main() { int nr1 = 4; int nr2 = 43; int sum = add(nr1, nr2); }

Den koden skulle i vår psuedoassembler bli ungefär (vi låtsas för enkelhetens skull att en int är 1 byte stor):

// Start på main. 1: STORE $9, $S1 // Lagra värdet på variabel nr1 ($9) i register S1 2: STORE $10, $S2 // Lagra värdet på variabel nr2 ($10) i register S2 3: STORE 5 $RET // Lagra värdet på den address vi vill fortsätta på efter att funktionen är klar. 4: JUMP $7 // Hoppa till funktionen add, som börjar på address 7. 5: STORE $S3, $11 // Lagra värdet på register S3 i variabeln sum ($11) 6: END // Avsluta programmet. // Slut på main. // Start på funktionen add. 7: ADD $S1, $S2, $S3 // Addera S1 och S2 och spara resultatet i S3. 8: JUMP $RET // Hoppa tillbaka till addressen som lagrats i register RET. // Slut på add, start på data. 9: 4 // nr1 10: 43 // nr2 11: 0 // sum

Ok, det börjar bli sent, så det här får räcka som introduktion. Säg till om det här är till någon som helst hjälp, så kan jag fortsätta och förklara andra koncept på samma sätt senare om du vill.

Permalänk
Medlem

Programmering är väldigt mycket hantverk, så jag hade inte lagt så stor vikt vid alla nya ord, utan fokuserat på att leka och experimentera med koden.
Fokusera också på kurskraven, läs och förstå dom. Ignorera saker som ligger utanför dom kraven, om du inte redan förstått dom.

Har du kunnat stryka något från listan och vilket av dom tycker du fortfarande är svårast att förstå?

Skickades från m.sweclockers.com

Visa signatur

Oldschool [å:ldsku:l] adj. Användandet av datorprodukter som är äldre än 3 månader.

Permalänk
Medlem

@perost: Tack så mycket, detta var lättare för mig att förstå, verkligen. Jag tror det sket för mig totalt när jag började lära mig c# sen insåg jag att allt ska vara till c++..

Permalänk
Medlem

@kundun: Alltså jag skulle kunna säga att jag förstår principen till allt förutom get,set.. men ett stort problem för mig också är att jag gör allt för komplicerat när jag bestämmer mig för att bara koda i fantasi, jag glömmer bort vad man kan använda och är bra att använda och tappar bara motivationen då för jag tycker allt blir för svårt typ..

Även fast jag lärt mig typ allt till principen, så kan jag fortfarande inte memorera hur koden ska se ut.. speciellt när det kommer till linjär sökning, binär sökning och sen bubblesort som vi använde för sorteringsalgoritm vet inte hur jag ska nöta in det i mitt huvud så när jag sitter och kodar så ska jag kunna det utantill typ, det är mitt största problem med allt, speciellt när jag ska behöva lära mig hela nya termer samt dess kod och hur och när den ska användas typ

Permalänk
Medlem

Det tar tid att lära sig, och ingen kommer ihåg allt. Alla googlar, det är nästan så att hur bra utvecklare du är beror på hur bra du kan googla fram den bästa lösningen

Propertys/egenskaper med get/set är lite speciella, dom är som ett mellanting mellan en variabel och en metod.
Tänk dig en klassen Person med variabeln name och propertyn Age:

class Person{ public string name; public int Age{ get{ } set{ } } }

Vi skapar en ny instans av Person, en ny person helt enkelt:

var p = new Person();

Vi ger värden till personens name och age:

p.name = "Kalle"; p.Age = 200;

Variabeln name kan vi sätta till vilken sträng vi vill och behöver vi veta namnet så kallar vi bara på p.name igen.
På samma sätt använder vi Age-propertyn, vi kan sätta den och kalla på den precis som en variabel.
Men, det fina med en property är att vi kan kontrollera dom bitarna om vi vill, så att en användare inte kan ge Age ett värde på tex 200. Och det gör vi genom get och set.

En person kan inte vara 200 år så vi vill förhindra att det värdet kan sättas:

class Person{ public string name; public int Age{ get{ } set{ if(value < 120){ this.Age = value; } } } }

Nu har vi gjort så att man bara kan sätta Age till värden under 120!

På samma sätt kan man styra vilket värde som man får när man kallar på en property.
Säg att Kalle är en hund, och när vi vill veta hans ålder så vill vi ha åren i hundår, inte människoår:

class Person{ public string name; public int Age{ get{ return this.Age / 7; } set{ if(value < 120){ this.Age = value; } } } }

Så nu får vi hur många hundår Kalle är istället!

p.Age = 200; // set-metoden ser att value inte är under 120 och kommer inte att ge Age ett värde p.Age = 35; // funkar eftersom det är under 120 print(p.Age); // returnerar 5, eftersom get returnerar Age delat med 7

Man kallar alltså inte själv på get/set utan det görs automagiskt när man ger eller hämtar ett värde från en property.

En get ska alltid returnera ett värde, precis som en metod.
En set får alltid in ett värde (value) som den ska spara.

Hoppas det hjälpte lite!

Visa signatur

Oldschool [å:ldsku:l] adj. Användandet av datorprodukter som är äldre än 3 månader.

Permalänk
Medlem
Skrivet av Korvulla:

@perost: Tack så mycket, detta var lättare för mig att förstå, verkligen. Jag tror det sket för mig totalt när jag började lära mig c# sen insåg jag att allt ska vara till c++..

Ok, vi fortsätter på samma spår då. Du verkar redan ha koll på saker som if-satser och loopar, men vi kan ta det lite snabbt ändå. En if-else-sats skulle t.ex. kunna se ut så här (exemplet visar if(x == 5) { ... } else { ... }, där x har address 43):

1: JUMPEQ $43, 5, $3 // Om värdet på x (d.v.s. $43) är lika med 5, hoppa till $3. 2: JUMP $5 // Annars, hoppa till $5 3: ... // Någon kod som ska köras om x == 5. 4: JUMP $6 // Hoppa till slutet av if-satsen. 5: ... // Någon kod som ska köras om x != 5. 6: ... // Start på kod efter if-satsen.

En loop är väldigt lika, så här skulle t.ex. while(x == 5) { ... } kunna se ut:

1: JUMPEQ $43, 5, $3 // Om värdet på x är lika med 5, hoppa till $3. 2: JUMP $5 // Annars hoppa till slutet av loopen. 3: ... // Någon kod som ska köras i loopen. 4: JUMP $1 // Hoppa tillbaka till början av loopen. 5: ... // Start på kod kod efter while-loopen.

Och en for-loop är i stort sett samma sak.

Så, låt oss tackla klasser. Vi kan börja med strukturer, som i C (och i C++/C#, men jag tar det senare) är ett sätt att gruppera variabler. T.ex.:

struct MyStruct { int i; float f; char c; };

Att bara deklarera en sån struct gör ingenting, d.v.s. bara för att MyStruct har en deklaration av int i; så allokeras inget minne för någon variabel i någonstans. Det är först när man deklarerar variabler som har typen MyStruct som minne allokeras:

MyStruct ms; ms.i = 44925; // 0x0000AF7D i hexadecimalt format. ms.f = 0.24f; // 0x3E75C28F (enligt IEEE-754) ms.c = 'a'; // 0x61 (enligt ASCII)

Detta kommer få kompilatorn att allokera minne för variabeln ms (ms sägs vara en instans av MyStruct), vilket skulle se ut så här i minnet efter att ovanstående tilldelningar utförts:

1: 0x00 // Början på ms, och även ms.i 2: 0x00 3: 0xAF 4: 0x7D // Slut på ms.i 5: 0x3E // Början på ms.f 6: 0x75 7: 0xC2 8: 0x8F // Slut på ms.f 9: 0x61 // Hela ms.c, en char tar bara upp en byte.

En struct är med andra ord rätt lik en array, bara att elementen kan vara av olika typer och att elementen har unika namn. Som vanliga variabler kan man så klart deklarera flera variabler av typen MyStruct, där alla skulle få ett eget block på 9 byte allokerat i minnet.

En klass är sen en struct på steroider, åtminstone i teorin. I C++ är det faktiskt ingen skillnad på en struct och en class, förutom att allt i en struct är public om inget annat anges medan allt i en class är private (inte så viktigt nu, du kommer stöta på det förr eller senare om du använder klasser). I C++ kan man alltså använda structs som klasser och klasser som structs, men normalt använder man struct just för att gruppera variabler och klasser för mer komplexa objekt (d.v.s. som har metoder). C# har också struct, men där är de lite mer specialiserade (vi hoppar den förklaringen, den är inte relevant för ämnet och skulle bara krångla till det).

Så i C++ skulle vi alltså kunna deklarera följande klass, som skulle fungera precis som MyStruct ovan:

class MyClass { public: int i; float f; char c; };

Den har inga metoder, det enda den gör är att gruppera tre variabler. Varje instans av MyClass vi deklarerar kommer vara som att deklarera tre separata variabler, där varje instans har sitt eget minnesblock för dess variabler:

MyClass c1; c1.i = 4; // Sätt c1.i till 4. MyClass c2; c2.i = 6; // Sätt c2.i till 6, c1.i påverkas inte på något sätt och är fortfarande 4.

Ett sätt att programmera på ett objekt-orienterat sätt i C, som inte har klasser, är att använda structs och skicka dem som argument till funktioner (detta är så klart C++, C har t.ex. inte cout):

void print_i(MyStruct ms) { std::cout << "i has the value " << ms.i << std::endl; } int main() { MyStruct ms1; ms1.i = 5; MyStruct ms2; ms2.i = 9; print_i(ms1); // Kommer skriva ut "i has the value 5". print_i(ms2); // Kommer skriva ut "i has the value 9". }

Instansmetoder fungerar som sagt på samma sätt, förutom att instansen man anropar metoden på automatiskt skickas som argument till metoden (via den speciella variabeln this):

class MyClass { public: // Skriver ut värdet på i som tillhör instansen som metoden anropas via. // Här använder jag uttryckligen this, men skulle man bara skriva i // så skulle kompilatorn förstå att det är this->i som menas. void print_i() { std::cout << "i has the value " << this->i << std::endl; } int i; ... }; int main() { MyClass mc1; mc1.i = 5; MyClass mc2; mc2.i = 9; mc1.print_i(); // Anropar MyClass::print_i med this = mc1. mc2.print_i(); // Anropar MyClass::print_i med this = mc2. MyClass::print_i(); // Fel, print_i kan inte anropas utan någon instans. }

Klasser har sen som bekant konstruktorer, för att man ska kunna tilldela värden till alla variabler i en instans och göra annat som behövs för att initiera en instans. De kan även ha destruktorer, som automatiskt anropas när en instans "dör". Tänk dig t.ex. en klass som representerar en TCP/IP-socket som kan användas för att hantera nätverkstrafik (återigen med onödig användning av this för demonstrationens skull):

class IPSocket { public: // Konstruktor för IPSocket, tar en IP-address och en port. IPSocket(int address, int port) { // Spara address och port, även fast de egentligen inte behövs i detta enkla exempel. // Notera att användningen av this gör att vi kan ha samma namn på klassvariablerna // och funktionsparametrarna här utan att få konflikter. this->address = address; this->port = port; // Öppna en TCP/IP-anslutning, och spara identifieraren för anslutningen. this->handle = ipopen(address, port); } // Destruktor för IPSocket. ~IPSocket() { // Stäng TCP/IP-anslutningen. ipclose(this->handle); } // Metod för att skicka en sträng med data. void send(string data) { ipsend(this->handle, data); } int address; int port; int handle; }; int main() { // Denna deklaration kommer allokera minne för en IPSocket-instans, // och sedan anropas konstruktor för IPSocket med this = socket. IPSocket socket(2130706433, 80); // 2130706433 = 127.0.0.1 socket.send("Hello World", 11); // Anropar send med this = socket. // Här tar main slut, och sockets allt för korta liv lika så. // Här anropas alltså destruktorn för IPSocket med this = socket automatiskt. }

Lite överkurs men värt att nämna är att man i C++ normalt föredrar att använda en s.k. member initializer list i konstruktorn, se t.ex. denna sida (under "Member initialization in constructors").

Och därmed var dagens test av hur långa inlägg Sweclockers tillåter slut

Permalänk
Medlem

Herregud, hen går programmering 1 och har problem att begripa get/set och så introducerar du struct och minnesallokeringar?!

Skickades från m.sweclockers.com

Visa signatur

Oldschool [å:ldsku:l] adj. Användandet av datorprodukter som är äldre än 3 månader.

Permalänk

Hej. Jag håller på med programmering 1 och har ett Litet problem med ett program från csharpskolan.

"Skriv ett program som läser in ett positivt heltal. Lista sedan alla tal från 1 till det inmatade talet som är jämt delbart med både 3 och 7. Om inga tal hittats så skall detta skrivas ut. Se exempel nedan.

Tips: Använd operatorn %."

Okej här är min kod :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp6
{
class Program
{
static void Main(string[] args)
{
Console.Write("Skriv ett positivt heltal: ");
string str = Console.ReadLine();
int i = Convert.ToInt32(str);

for (; 1 < i; i--)

if (i % 3 == 0 && i % 7 == 0)
{
Console.WriteLine(i);

}
else if (i<19)
{
Console.WriteLine("Inga tal hittades");
break;
}
}
}
}

Felet är att "Inga tal hittades" skrivs ut även när den träffar på första IF.

Jag har spenderat alldeles för många timmar att försöka lösa de här nu och vore Väldigt tacksam över svar. Övningen hör inte ens till skolan men kan fan inte släppa de här.

Permalänk
Medlem

if (i % 3 == 0 && i % 7 == 0)

Berätta vad denna raden faktiskt gör 😉

Skickades från m.sweclockers.com

Visa signatur

Oldschool [å:ldsku:l] adj. Användandet av datorprodukter som är äldre än 3 månader.

Permalänk
Medlem

@surrelito: Just nu skriver du ut att inga tal hittades och avbryter loopen så fort som ett tal som inte är jämnt delbart med 3 och 7 och mindre än 19 (varför?) hittas. D.v.s. istället för att gå igenom alla tal mellan 1 och det inmatade talet så går du bara igenom alla tal mellan det inmatade talet och det första talet som är mindre än 19 och som inte är jämnt delbart med 3 och 7.

Vad du istället borde göra är att gå igenom alla tal och hålla koll på om något matchande tal hittades i loopen (d.v.s. med en variabel, t.ex. en bool), och sen först efter loopen skriva ut att inget tal kunde hittas om så är fallet.

Permalänk
Medlem
Skrivet av kundun:

if (i % 3 == 0 && i % 7 == 0)

Berätta vad denna raden faktiskt gör 😉

Skickades från m.sweclockers.com

Först kollar den om variabeln i går att dela på 3 (utan rest) och därefter så kollar den om variabeln i går att dela 7 jämt ut.

Just % brukar kallas modulus, och det man gör är att försöka dela talet första talet med det andra (e.g 6 % 3) för att sedan kolla om det blir någon rest eller ej (är talet delbart).

Exempelvis, skulle du köra dessa två rader:

Console.WriteLine(string.Format("6 % 2 = {0}", 6 % 2)); Console.WriteLine(string.Format("7 % 3 = {0}", 7 % 3));

Så skulle du få följande svar:
6 % 2 = 0
7 % 3 = 1

Permalänk
Medlem

@asabla: Du vet att du bara får träff på 21, 42 osv?

Tänk igenom steg för steg vad koden ska göra enligt beskrivningen, och jämför med vad den faktiskt gör.
Kolla perost's kommentar!

Visa signatur

Oldschool [å:ldsku:l] adj. Användandet av datorprodukter som är äldre än 3 månader.

Permalänk
Medlem
Skrivet av kundun:

@asabla: Du vet att du bara får träff på 21, 42 osv?

Det är ju det uppgiften går ut på, att lista tal som är jämnt delbara med både 3 och 7.

Fast nu när jag tänker på det är det ju ett ganska dåligt tips som övningstexten ger att använda %, det är ju betydligt mer effektivt att bara lista alla tal 3*7*n som är mindre än det inmatade talet.

Permalänk
Medlem
Skrivet av kundun:

@asabla: Du vet att du bara får träff på 21, 42 osv?

Tänk igenom steg för steg vad koden ska göra enligt beskrivningen, och jämför med vad den faktiskt gör.
Kolla perost's kommentar!

Absolut, men det var inte det du frågade efter, jag svarade på din fråga utan att ange vilka tal som ger träff på båda. Och din fråga var: "Berätta vad denna raden faktiskt gör"

Skrivet av perost:

Det är ju det uppgiften går ut på, att lista tal som är jämnt delbara med både 3 och 7.

Fast nu när jag tänker på det är det ju ett ganska dåligt tips som övningstexten ger att använda %, det är ju betydligt mer effektivt att bara lista alla tal 3*7*n som är mindre än det inmatade talet.

Jo men exakt, jag svarade bara på vad raden gör, inte vilka tal som faktiskt kommer passa in på de båda villkoren.

Sedan huruvida modulus är det rätta sättet att gå i denna typ av övning låter jag vara osagt Den har sina användningsfall, även om jag själv personligen använder den otroligt sällan (både i jobbet och privat)