Beräkna värdet tills summan överstinger n (C)

Trädvy Permalänk
Medlem
Registrerad
Feb 2006

Beräkna värdet tills summan överstinger n (C)

Skriv ett program som tar emot ett tal n från användaren. Programmet beräknar sedan värdet 1+2+3… tills summan överstiger n. Då ska summan samt det senast adderade talet skrivas ut.

Har kört fast totalt på denna uppgiften. (Dag 2 på Universitetet, uppgiften är inte en uppgift jag ska visa läraren)
Har aldrig gjort en while-loop tidigare, så har kollat massa youtube videos men fattar ändå inte riktigt hur jag ska lösa den. Rätt svar är iaf att den ska skriva ut två värden, dvs: 105 och 14 (om jag skriver in 100)

Här är koden (som jag rakt av kopierat genom Google.)
#include <stdio.h>
int main()
{
int n, i, sum = 0;

scanf("%d",&n);
for(i=1; i <= n; ++i)
{
sum += i; // sum = sum+i;
}
printf("%d",sum);
return 0;
}

Skriver jag in 100 får jag svaret 5050.
Dvs så stannar den när den gjort det 100 gånger och inte när den når summan 100.

Om någon har en bra guide till while loopar får ni gärna länka.
(eller om ni rent pedagogiskt kan förklara vad som sker i själva while-loopen)

Asus z270 Maximus Extreme | Intel i7 7700K | EVGA GTX 1080 FTW | 1TB WB Blue | 240GB Samsung 650 nvme | Fractal Design R6 | Corsair HX 1000W | Kingston 32GB DDR4 | Asus Swift PG278Q

Trädvy Permalänk
Medlem
Plats
127.0.0.1
Registrerad
Apr 2008

Ett tips är att lära dig använda en debugger och steppa igenom koden rad för rad och se vad som händer med de olika variablerna.

En annan variant på debug är att skriva it flera print-satser i koden. Exempelvis värdet n i loopen samt vad sum innehåller.

Skickades från m.sweclockers.com

Intel i7 8700 | ASUS Prime Z370-P | Corsair 16GB 3000MHz | ASUS GTX 1080 8 GB @ 2100MHz/11080MHz | Fractal Design Define S | Corsair RMX750x | Cooler Master Hyper 212 EVO

Trädvy Permalänk
Medlem
Plats
Småland, långt ute i mörka skogen.
Registrerad
Maj 2018

for(i=1; i <= n; ++i) denna loop snurrar så länge i <= n.

Men du vill istället att den skall snurra så länge sum < n?

Prova:

for(i=1; sum < n; ++i)

Linux och Android

Trädvy Permalänk
Medlem
Registrerad
Feb 2006
Skrivet av Adoby:

for(i=1; i <= n; ++i) denna loop snurrar så länge i <= n.

Men du vill istället att den skall snurra så länge sum < n?

Prova:

for(i=1; sum < n; ++i)

Ah, där löste det sig. Så nu att jag missat att använde for istället för while.
Vad är skillnaden mellan dessa och hur kommer det sig att båda fungerar?

Asus z270 Maximus Extreme | Intel i7 7700K | EVGA GTX 1080 FTW | 1TB WB Blue | 240GB Samsung 650 nvme | Fractal Design R6 | Corsair HX 1000W | Kingston 32GB DDR4 | Asus Swift PG278Q

Trädvy Permalänk
Medlem
Plats
Göteborg
Registrerad
Jul 2007
Skrivet av kwame:

Ah, där löste det sig. Så nu att jag missat att använde for istället för while.
Vad är skillnaden mellan dessa och hur kommer det sig att båda fungerar?

for och while går att använda till samma sak.

while(villkor) { kod }

Är enklast. Så länge villkor är sant kör kod.

För att förvilla kan man också skriva:

{ kod } while(villkor)

Vilket betyder kör kod, kolla villkoret, upprepa om det inte är uppfyllt. Dvs, kod körs alltid minst en gång.

En simpel forloop:

for(int i=0; i<10; i++) { kod }

int i=0 är en inledande deklaration/operation som körs en gång / for block. i<10 är villkoret, och i++ körs efter varje varv.

Så i princip kan man skriva en whileloop på for-form så här:

for(;villkor;) {}

och kommer i princip bete sig som det första while-exemplet.

du kan också skriva en "forloop" på whileform så här:

int i=0; while(i<10) { kod; i++; }

vilket kommer få samma beteende, och i många fall samma maskinkod, som for(int i=0; i<10; i++){kod}.

Vet inte om det hjälper eller stjälper, men lycka till!

WS: Bärbar workstation, 2 * Dell U2412M
HTPC: Intel NUC, Canton GLE 496, Yamaha RV-A830, Sanyo PLV-Z700
Server: Intel Xeon E3-1240@3.4 GHz, ESXi, 32GB RAM, 8*2TB RAID-Z2 + SSD-cache
Slösurf: MacBook Air 11,6", Samsung S8
Kamera: Canon EOS 5DII + 1DIII, Canon 100/2.8 Macro, Canon 70-200/2.8L, Canon 24-70/2.8L

Trädvy Permalänk
Medlem
Plats
Småland, långt ute i mörka skogen.
Registrerad
Maj 2018

Ett sätt att se det är att både for och while i grunden är ett förklätt test och ett goto. Egentligen är både while och for helt onödiga. De finns nog enbart för att de gör det lättare att skriva och läsa kod. På IT-stenåldern var "goto" en hädelse som kunde bestraffas med kroppsaga eller iaf. konfiskering av hålkorts-stansaren. Och man hittade på alla möjliga knep för att slippa använda goto. Allt från subrutiner, procedurer och funktioner till flödeskontrollstrukturer som for, while och switch och till och med klasser och objekt. Men goto finns fortfarande kvar i C, om du vill reta gallfeber på en lärare som var med på den tiden. Och inte är rädd för att bli underkänd med en gång.

for(i = 0; i < 10; i++) { ; // Gör något }

i = 0; while(i < 1) { ; // Gör något i = i + 1; }

Båda dessa är exakt samma sak som:

i = 0; loop: if( i < 10 ) { ; // Gör något i = i + 1; goto loop; }

En do-while blir lite annorlunda:

i = 0; do { ; // Gör något i = i + 1; } while (i < 10);

blir

i = 0; loop: ; // Gör något i = i + 1; if( i < 10 ) goto loop;

Linux och Android

Trädvy Permalänk
Medlem
Registrerad
Feb 2006
Skrivet av zyberzero:
Skrivet av Adoby:

Tack till er båda att ni tagit er tid! (och alla andra) men mycket bra och utförliga svar, klarnade upp en hel del.
Ska kolla lite extra noga på dessa senare idag! (haft fullt upp med nollningen sen jag postade inlägget)

Asus z270 Maximus Extreme | Intel i7 7700K | EVGA GTX 1080 FTW | 1TB WB Blue | 240GB Samsung 650 nvme | Fractal Design R6 | Corsair HX 1000W | Kingston 32GB DDR4 | Asus Swift PG278Q

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Sep 2006

Stort lycka till med studierna! De kan bli jobbiga till och från men det finns ett slut även om det känns långt borta. Vilken skola läser du på?

Failure is not an option. It comes bundled with your windows installation.
AMD Phenom2 X4 965 | Gigabyte GA-MA790FXT-UD5P | 4GB Corsair XMS3-12800DHX | XFX HD5870 | Asus XONAR D2 | 80GB Intel X25-M | 1TB Western Digital Caviar Green

Trädvy Permalänk
Medlem
Registrerad
Feb 2006
Skrivet av MrPasty:

Stort lycka till med studierna! De kan bli jobbiga till och från men det finns ett slut även om det känns långt borta. Vilken skola läser du på?

Tack så mycket! =D Jag läser på Karlstads Universitet, är därifrån så passade bäst på så vis.
Har en liten fundering.

"Skriv ett program som läser in n heltalsvärden från användaren och sedan skriver ut det största och det minsta av de angivna talen. n ska anges med en konstant som sätts till 10."

Hur ska jag tänka här? Vill inte ha någon färdig kod utan snarare lite tips. Står ganska still i huvudet.
Har tidigare gjort program där man kan mata in t.ex 5 tal, men här så är det ju n tal?
Sedan största fundering är ju hur man ska lösa att programmet ska förstå vilket tal som är störst och mins och sedan återkalla informationent?

(Ursäkta att jag är extremt okunnig, men är ju bara 3 dagar in på min första programmeringskurs någonsin =D)

Asus z270 Maximus Extreme | Intel i7 7700K | EVGA GTX 1080 FTW | 1TB WB Blue | 240GB Samsung 650 nvme | Fractal Design R6 | Corsair HX 1000W | Kingston 32GB DDR4 | Asus Swift PG278Q

Trädvy Permalänk
Medlem
Plats
Småland, långt ute i mörka skogen.
Registrerad
Maj 2018

Du bör nog INTE fråga här utan experimentera och testa. Det lär du dig mer på. Läs kurslitteraturen.

Linux och Android

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Sep 2006
Skrivet av Adoby:

Du bör nog INTE fråga här utan experimentera och testa. Det lär du dig mer på. Läs kurslitteraturen.

Håller med ovan. Det här är absolut saker som du kan läsa dig till och det är väldigt lätt att bli för bekväm och sluta tänka själv när man kan fråga andra. Det jag kan säga är att eftersom du verkar ha två problem föreslår jag att du löser ett i taget. Börja med att skriva ett program som bara låter användaren mata in n heltal och sedan skriver ut de heltalen. När du har gjort det är jag övertygad om att du kommer att klura ut resten ganska lätt.

Failure is not an option. It comes bundled with your windows installation.
AMD Phenom2 X4 965 | Gigabyte GA-MA790FXT-UD5P | 4GB Corsair XMS3-12800DHX | XFX HD5870 | Asus XONAR D2 | 80GB Intel X25-M | 1TB Western Digital Caviar Green

Trädvy Permalänk
Medlem
Registrerad
Mar 2010
Skrivet av kwame:

Tack så mycket! =D Jag läser på Karlstads Universitet, är därifrån så passade bäst på så vis.
Har en liten fundering.

"Skriv ett program som läser in n heltalsvärden från användaren och sedan skriver ut det största och det minsta av de angivna talen. n ska anges med en konstant som sätts till 10."

Hur ska jag tänka här? Vill inte ha någon färdig kod utan snarare lite tips. Står ganska still i huvudet.
Har tidigare gjort program där man kan mata in t.ex 5 tal, men här så är det ju n tal?
Sedan största fundering är ju hur man ska lösa att programmet ska förstå vilket tal som är störst och mins och sedan återkalla informationent?

(Ursäkta att jag är extremt okunnig, men är ju bara 3 dagar in på min första programmeringskurs någonsin =D)

Nu har det gått ett par dagar så antar att du vid detta läge redan löst uppgiften i fråga.

Vad säger uppgiften exakt? Jo följande:
1. Användaren ska skriva in tio stycken godtyckliga värden.
2. Av inmatade värden ska det högsta och lägsta värdet returneras.

D.v.s du behöver på något vis köra om samma logik i så pass många varv att användaren matat in tio värden. Do-While, While eller For -loop. Varje "varv" behöver du kunna bestämma om det nuvarande inmatade värdet är större eller mindre än "varvet" innan.

Alltså behöver du ha två stycken variabler som innehåller högsta värdet och lägsta värden (int low, high;). Här behöver du en if-sats. Om userInput är mindre än low tilldela low=userInput, om userInput är större än high tilldela high = userInput. Vid den här punkten loopar vi igen förutsatt att vi har fler "loopar" kvar att utföra. Om loopen avslutas så fallar koden vidare varpå du enkelt har en utskrivning för int'en low samt high.

Vad händer om en användare skriver in samma tal?
Vad händer om du inte tilldelar variablerna low samt high vid programstart och därefter: Vad händer om du tilldelar dessa till "0" eller liknande?

öh öh ha den äran!

Trädvy Permalänk
Medlem
Registrerad
Feb 2006

Nu börjar jag få lite mer förståelse.
Dock har jag en ny fråga, antar att jag tolkat uppgiften fel på något vis då den automatiska rättaren säger att jag har fel.
Kör jag den i min kompilator och skriver in diverse saker 3+2, 3*2, 3/2, 3^3 så räknar den helt rätt. Försöker jag dividera med 0 så får jag fram printf("NaN"); och programmet stängs ner.. så den klarar allt som begärs åtminstone.

Så antar att jag tolkat uppgiften fel på något ställe. Vad menar de t.ex med "Implementera funktionen void calc(float param1, float param2, char operator))

skappade ju en funktion som heter calc och som innehåller float param1, param2
och char operator..

Här är uppgiften:

Citat:

Implementera funktionen:

void calc(float param1, float param2, char operator)

Funktionen ska utföra den matematiska operationen operator på flyttalen param1 och param2. Funktionen ska skriva ut svaret på operationen. Programmet ska stödja operatorerna +, -, *, / och ^, där ^ är upphöjt till. Om funktionen dividerar med 0 ska NaN skrivas ut. Skriv ett program som tar två tal och en operator från användaren, kör funktionen, och skriver ut resultatet.

#include <stdio.h> #include <stdlib.h> #include <math.h> void calc() { float param1, param2, summan; char operator; scanf("%f %s %f", &param1, &operator, &param2); { if(operator == '+') { summan = param1+param2; printf("%f", summan); } else if(operator == '-') { summan = param1-param2; printf("%f", summan); } else if(operator == '*') { summan = param1*param2; printf("%f", summan); } else if(operator == '/') { if(param2 == 0) { printf("NaN"); return 0; } summan = param1/param2; printf("%f", summan); } else if(operator == '^') { printf("%f", pow(param1, param2)); } return 0; } } int main() { calc(); return 0; }

Asus z270 Maximus Extreme | Intel i7 7700K | EVGA GTX 1080 FTW | 1TB WB Blue | 240GB Samsung 650 nvme | Fractal Design R6 | Corsair HX 1000W | Kingston 32GB DDR4 | Asus Swift PG278Q

Trädvy Permalänk
Medlem
Plats
Linköping
Registrerad
Jun 2007

@kwame: Din calc-funktion tar inga parametrar, den läser in allt med scanf istället. Tanken är att du ska sköta inläsningen i t.ex. main, och sen skicka allt som calc behöver som funktionsargument.

Man bör alltid sträva efter att skriva funktioner som inte har sidoeffekter (s.k. rena funktioner), d.v.s. som alltid returnerar samma resultat för en viss kombination av argument. Rena funktioner är bl.a. enklare att återanvända, om din calc-funktion själv läser in data från användaren så kan du ju inte använda den i t.ex. ett grafiskt program eller ett program där datan läses in från en fil.

Tyvärr så snubblar uppgiften på målsnöret här eftersom den anger att calc-funktionen ska skriva ut resultatet, det hade varit bättre om calc bara returnerade resultatet istället. Men när valet står mellan att skriva bra kod eller att uppfylla kriterierna för uppgiften så har tyvärr uppgiften prioritet

Trädvy Permalänk
Medlem
Registrerad
Feb 2006
Skrivet av perost:

@kwame: Din calc-funktion tar inga parametrar, den läser in allt med scanf istället. Tanken är att du ska sköta inläsningen i t.ex. main, och sen skicka allt som calc behöver som funktionsargument.

Man bör alltid sträva efter att skriva funktioner som inte har sidoeffekter (s.k. rena funktioner), d.v.s. som alltid returnerar samma resultat för en viss kombination av argument. Rena funktioner är bl.a. enklare att återanvända, om din calc-funktion själv läser in data från användaren så kan du ju inte använda den i t.ex. ett grafiskt program eller ett program där datan läses in från en fil.

Tyvärr så snubblar uppgiften på målsnöret här eftersom den anger att calc-funktionen ska skriva ut resultatet, det hade varit bättre om calc bara returnerade resultatet istället. Men när valet står mellan att skriva bra kod eller att uppfylla kriterierna för uppgiften så har tyvärr uppgiften prioritet

Fick mail av läraren att jag skulle skicka in uppgiften igen då det var något fel på autocorrect gällande den uppgiften.
Nu fick jag helt plötsligt rätt..

Ligger ca 1.5 vecka före min kurs för att jag vill ha jobbat med det som föreläsaren går igenom - blir så mycket lättare att förstå vad han pratar om då när man är lite bekant sen tidigare. Men ja, det medför ju lite problem också att man kanske inte löser uppgifter på de smartaste sättet.

Vad menar du med att min calc-funktion inte tar några parametrar? Hur sköter man inläsningen i main och sedan skickar det som calc behöver som funktionsargument?
Håller på att kolla youtubevideos just nu gällande att skapa funktioner så kanske jag får lite mer förståelse om vad du menar haha.

Asus z270 Maximus Extreme | Intel i7 7700K | EVGA GTX 1080 FTW | 1TB WB Blue | 240GB Samsung 650 nvme | Fractal Design R6 | Corsair HX 1000W | Kingston 32GB DDR4 | Asus Swift PG278Q

Trädvy Permalänk
Medlem
Plats
Linköping
Registrerad
Jun 2007

@kwame: Här är ett enkelt exempel på en funktion som tar två värden som argument och returnerar summan av dem:

int add(int x, int y) // x och y är funktionsparametrar. { return x + y; } int main() { int r = add(1, 2); // 1 och 2 är funktionsargument. printf("1 + 2 = %d\n", r); return 0; }

Trädvy Permalänk
Medlem
Registrerad
Feb 2006
Skrivet av perost:

@kwame: Här är ett enkelt exempel på en funktion som tar två värden som argument och returnerar summan av dem:

int add(int x, int y) // x och y är funktionsparametrar. { return x + y; } int main() { int r = add(1, 2); // 1 och 2 är funktionsargument. printf("1 + 2 = %d\n", r); return 0; }

Perfekt, tack så mycket då förstår jag precis
Får bli att göra om min kod på detta viset och sätta det som rutin.

Asus z270 Maximus Extreme | Intel i7 7700K | EVGA GTX 1080 FTW | 1TB WB Blue | 240GB Samsung 650 nvme | Fractal Design R6 | Corsair HX 1000W | Kingston 32GB DDR4 | Asus Swift PG278Q

Trädvy Permalänk
Medlem
Registrerad
Feb 2006

Har nu återigen ett problem. Koden är säkerligen inte alls den snyggaste, men ja, det är i uppbyggnadsfas. Hur som helst - jag har gjort kod som först och främst visar en meny med 4 olika alternativ. Jag har ännu bara byggt kod för 2 av dessa 4 funktioner.

Problemet med min kod:
Om jag tar bort min Else-sats (som egentligen bara ska få fram menyn igen om jag trycker på något annat än 1-4)
så blir det såhär:
Jag får fram menyn, väljer 1, får slumpade tal mellan 0-900.
Sen visas menyn igen sen avslutas programmet utan att jag får göra något nytt val.
Jag vill ju göra ett nytt val, dvs 2 - att talen sorteras i ordning.

Dock har jag med else så fungerar det på samma vis förutom att jag får fram menyn två gånger och sedan kan göra ett nytt val.
else kallar ju även den på main(); men varför aktiveras main i den när jag tryckt på 1? Och varför får jag göra ett nytt val bara för att det visar två menyer?

ps. om ni har något tips i övrigt eller ser något riktigt galet med koden får ni gärna säga till.

#include <stdio.h> #include <stdlib.h> #include <time.h> #define ANTAL 10 int menu(void) { int arry[100]; char choice = 0; printf("\n/==========================================================================/\n"); printf("/=================================MENU=====================================/\n"); printf("/==========================================================================/\n"); printf("1. Alstra en talfoljd med en slumpgenerator och skriv ut talen pa skarmen.\n"); printf("2. Sortera talfoljden med bubbelsortering. Efter sorteringen skall talfoljden skrivas ut pa skarmen.\n"); printf("3. Medelvarde, median, maxvarde och minvarde skall beraknas och skrivas ut pa skarmen.\n"); printf("4. Med binarsokning skall man kunna soka efter ett valfritt tal. Om talet finns i talfoljden meddelas, pa skarmen,\n pa vilken plats i tabellen (rad och kolumn) talet finns. Annars meddelas att talet inte finns i talfoljden.\n"); printf("/==========================================================================/\n"); printf("/==========================================================================/\n"); printf("/==========================================================================/\n"); printf(">>: \n"); scanf("%c", &choice); val(choice); return 0; } void val(char x) { if(x == '1') { mrndgen(); } else if(x == '2') { sort(); } else if(x == '3') { printf("Du har valt nummer: 3"); // med(); } else if(x == '4') { printf("Du har valt nummer: 4"); // binar(); } else { menu(); } } int mrndgen(int arry[100]) { srand(time(NULL)); int i = 0; int tal = 0; for(i=1; i<=ANTAL; i++) { tal = rand() % 900; arry[i] = tal; printf("%d ", tal); } main(); return 0; } int sort(int arry[100]) { int i = 0; int j = 0; int temp = 0; for(i = 0; i <= ANTAL-1; i++) { for(j = 0; j <= ANTAL-1-i; j++) { if(arry[j] > arry[j+1]) { temp = arry[j]; arry[j] = arry[j+1]; arry[j+1] = temp; } } } printf("Sorted list: \n"); for(i=0; i<ANTAL; i++) { printf("%d \n", arry[i]); } menu(); return 0; } /* int med(int x) int binar(int x)*/ int main(void) { menu(); return 0; }

Asus z270 Maximus Extreme | Intel i7 7700K | EVGA GTX 1080 FTW | 1TB WB Blue | 240GB Samsung 650 nvme | Fractal Design R6 | Corsair HX 1000W | Kingston 32GB DDR4 | Asus Swift PG278Q

Trädvy Permalänk
Medlem
Plats
Linköping
Registrerad
Jun 2007

@kwame: Problemet är att när du matar in t.ex. 1 och trycker på enter så kommer stdin-buffern innehålla 1\n, d.v.s. enter registerar som ett nyradstecken. Så andra gången du kommer till menyn ligger redan \n i buffern, så scanf returnerar det tecknet direkt istället för att läsa in mer tecken.

Men om du läser dokumentationen för scanf så står det att ett mellanslag i format-strängen matchar vilken mängd whitespace-tecken som helst. D.v.s. om du använder " %c" istället så kommer scanf slänga bort alla whitespace-tecken i buffern innan nästan tecken läses in.

Trädvy Permalänk
Medlem
Registrerad
Feb 2006
Skrivet av perost:

@kwame: Problemet är att när du matar in t.ex. 1 och trycker på enter så kommer stdin-buffern innehålla 1\n, d.v.s. enter registerar som ett nyradstecken. Så andra gången du kommer till menyn ligger redan \n i buffern, så scanf returnerar det tecknet direkt istället för att läsa in mer tecken.

Men om du läser dokumentationen för scanf så står det att ett mellanslag i format-strängen matchar vilken mängd whitespace-tecken som helst. D.v.s. om du använder " %c" istället så kommer scanf slänga bort alla whitespace-tecken i buffern innan nästan tecken läses in.

Tänkte att det var något sådant, därav jag la till char choice = 0; och tänkte att - ja, nu borde den ju inte innehålla någonting.
Men din lösning var ju riktigt enkel! Kul att man har kliat sig i huvudet på detta i över en timme utan att hitta lösningen.
Tack så mycket, nu kan jag äntligen gå och lägga mig och fortsätta imorgon haha.

Något övrigt du tycker jag ska ändra på i koden?
Jag har gjort om till en switch-sats istället för if på de olika valmöjligheterna iaf. Mycket snyggare.

Asus z270 Maximus Extreme | Intel i7 7700K | EVGA GTX 1080 FTW | 1TB WB Blue | 240GB Samsung 650 nvme | Fractal Design R6 | Corsair HX 1000W | Kingston 32GB DDR4 | Asus Swift PG278Q

Trädvy Permalänk
Medlem
Plats
Linköping
Registrerad
Jun 2007
Skrivet av kwame:

Något övrigt du tycker jag ska ändra på i koden?
Jag har gjort om till en switch-sats istället för if på de olika valmöjligheterna iaf. Mycket snyggare.

Ja, switch är bättre i det fallet.

Men kompilerar koden du postade för dig? I så fall bör du nog se över inställningarna för din kompilator, för koden är ju inte giltig C99 i alla fall. Problemet är väl främst att du använder funktioner innan de definierats, t.ex. när du anropar val i menu. Du måste antingen lägga funktionerna i rätt ordning i filen, eller fördeklarera dem i början av filen. T.ex.:

// deklaration: void val(char x); int menu(void) { ... val(choice); } // definition: void val(char x) { ... }

D.v.s. kompilatorn behöver veta vilken signatur en funktion har innan du använder den, men den bryr sig inte om vad funktionen innehåller.

Sen anropar du mrndgen utan något argument, så arrayen med slumptal som genereras sparas ingenstans utan försvinner direkt när funktionen är klar. Den biten borde inte heller kompilera egentligen, men eftersom du använder funktionen innan den deklarerats så antar kompilatorn att den inte har några argument och returnerar int (en liten underlighet i C).

Du borde inte heller anropa main eller menu i dina funktioner som du gör nu. Vad som händer när du anropar en funktion är att bl.a. variablerna du deklarerat i funktionen allokeras på stacken, och när funktionen når slutet så frigörs minnet igen. Men eftersom alla dina funktioner bara anropar varandra och aldrig når slutet så kommer ditt program förr eller senare få slut på stack (s.k. stack overflow). Vad du bör göra istället är att t.ex. ha menyn i en while-loop.

Trädvy Permalänk
Medlem
Registrerad
Feb 2006

Jag kör codeblocks och fick massa varningar som jag inte förstod vad de var för riktigt, så jag körde på ändå. Men nu har jag byggt om koden och deklarerat funktionerna samt byggt om till en while-loop.
Får inga varningar men det fungerar inte riktigt ändå. Jag får fram menyn och får sedan möjlighet att skriva i en character men efter det så blir det process returned... Hmm.

#include <stdio.h> #include <stdlib.h> #include <time.h> #define ANTAL 10 void val(char x); void printMenu(); int mrndgen(); int sort(); int main() { int choice = 0; while(choice != 5) { printMenu(); scanf("%d", &choice); switch(choice) { case 1: mrndgen(); break; case 2: sort(); break; case 3: printf("HEJHEJ"); break; case 4: printf("CHELLO"); break; default: printf("Ogiltigt val."); } } return 0; } void printMenu() // skapar en meny { printf("\n/==========================================================================/\n"); printf("/=================================MENU=====================================/\n"); printf("/==========================================================================/\n"); printf("1. Alstra en talfoljd med en slumpgenerator och skriv ut talen pa skarmen.\n"); printf("2. Sortera talfoljden med bubbelsortering. Efter sorteringen skall talfoljden skrivas ut pa skarmen.\n"); printf("3. Medelvarde, median, maxvarde och minvarde skall beraknas och skrivas ut pa skarmen.\n"); printf("4. Med binarsokning skall man kunna soka efter ett valfritt tal. Om talet finns i talfoljden meddelas, pa skarmen,\n pa vilken plats i tabellen (rad och kolumn) talet finns. Annars meddelas att talet inte finns i talfoljden.\n"); printf("/==========================================================================/\n"); printf("/==========================================================================/\n"); printf("/==========================================================================/\n"); printf(">>: \n"); } int mrndgen() // skapar en slumpartad talföljd i en array. { static int arry[100]; srand(time(NULL)); int i = 0; int tal = 0; int *p; p = arry; for(i=1; i<=ANTAL; i++) { tal = rand() % 900; arry[i] = tal; printf("%d ", tal); } } int sort(int *arry) // sorterar den slumpartade talföljden { int i = 0; int j = 0; int temp = 0; for(i = 0; i <= ANTAL-1; i++) { for(j = 0; j <= ANTAL-1-i; j++) { if(arry[j] > arry[j+1]) { temp = arry[j]; arry[j] = arry[j+1]; arry[j+1] = temp; } } } printf("Sorted list: \n"); for(i=0; i<ANTAL; i++) { printf("%d \n", arry[i]); } return 0; } /* int med(int x) int binar(int x)*/

Asus z270 Maximus Extreme | Intel i7 7700K | EVGA GTX 1080 FTW | 1TB WB Blue | 240GB Samsung 650 nvme | Fractal Design R6 | Corsair HX 1000W | Kingston 32GB DDR4 | Asus Swift PG278Q

Trädvy Permalänk
Medlem
Plats
Linköping
Registrerad
Jun 2007
Skrivet av kwame:

Jag kör codeblocks och fick massa varningar som jag inte förstod vad de var för riktigt, så jag körde på ändå.

Ett tips är att aldrig ignorera varningar, de indikerar nästan alltid att du har något fel i din kod. Om du använder GCC som kompilator i Code::Blocks så är det även en bra idé att minst använda kompilatorflaggorna -Wall -Werror. -Wall slår på fler varningar, och -Werror behandlar varningar som fel så att de inte går att ignorera.

Skrivet av kwame:

Får inga varningar men det fungerar inte riktigt ändå. Jag får fram menyn och får sedan möjlighet att skriva i en character men efter det så blir det process returned... Hmm.

Underligt, menyn fungerar i alla fall för mig, och jag kan inte se något uppenbart fel. Dina funktionsdeklarationer stämmer dock inte med hur funktionerna faktiskt är definierade, så du anropar fortfarande mrndgen och sort utan argument. Så sorteringen görs t.ex. på det som råkar ligga på stacken istället för den framslumpade arrayen.

Trädvy Permalänk
Medlem
Registrerad
Feb 2006
Skrivet av perost:

Ett tips är att aldrig ignorera varningar, de indikerar nästan alltid att du har något fel i din kod. Om du använder GCC som kompilator i Code::Blocks så är det även en bra idé att minst använda kompilatorflaggorna -Wall -Werror. -Wall slår på fler varningar, och -Werror behandlar varningar som fel så att de inte går att ignorera.
Underligt, menyn fungerar i alla fall för mig, och jag kan inte se något uppenbart fel. Dina funktionsdeklarationer stämmer dock inte med hur funktionerna faktiskt är definierade, så du anropar fortfarande mrndgen och sort utan argument. Så sorteringen görs t.ex. på det som råkar ligga på stacken istället för den framslumpade arrayen.

Körs koden för dig om du skriver 1 och sedan 2? För mig fungerar det bara på 3 och 4 dvs att det skriver ut.

Jag kör GCC så slår på det där imorgon, och får även ändra så det körs med argument.

Asus z270 Maximus Extreme | Intel i7 7700K | EVGA GTX 1080 FTW | 1TB WB Blue | 240GB Samsung 650 nvme | Fractal Design R6 | Corsair HX 1000W | Kingston 32GB DDR4 | Asus Swift PG278Q

Trädvy Permalänk
Medlem
Registrerad
Feb 2006

Sådär, efter en natts vila så löste jag det. Ser ni något som är galet? (även om allt nu fungerar)

#include <stdio.h> #include <stdlib.h> #include <time.h> #define ANTAL 10 void printMenu(); int mrndgen(int x[]); int sort(int arry[]); int main() { int arr[100]; int choice = 0; while(choice != 5) { printMenu(); scanf("%d", &choice); switch(choice) { case 1: mrndgen(arr); break; case 2: sort(arr); break; case 3: printf("HEJHEJ"); break; case 4: printf("CHELLO"); break; default: printf("Ogiltigt val."); } } return 0; } void printMenu() // skapar en meny { printf("\n/==========================================================================/\n"); printf("/=================================MENU=====================================/\n"); printf("/==========================================================================/\n"); printf("1. Alstra en talfoljd med en slumpgenerator och skriv ut talen pa skarmen.\n"); printf("2. Sortera talfoljden med bubbelsortering. Efter sorteringen skall talfoljden skrivas ut pa skarmen.\n"); printf("3. Medelvarde, median, maxvarde och minvarde skall beraknas och skrivas ut pa skarmen.\n"); printf("4. Med binarsokning skall man kunna soka efter ett valfritt tal. Om talet finns i talfoljden meddelas, pa skarmen,\n pa vilken plats i tabellen (rad och kolumn) talet finns. Annars meddelas att talet inte finns i talfoljden.\n"); printf("/==========================================================================/\n"); printf("/==========================================================================/\n"); printf("/==========================================================================/\n"); printf(">>: \n"); } int mrndgen(int x[]) // skapar en slumpartad talföljd i en array. { srand(time(NULL)); int i = 0; int tal = 0; for(i=1; i<=ANTAL; i++) { tal = rand() % 900; x[i] = tal; printf("%d ", tal); } return 0; } int sort(int arry[]) // sorterar den slumpartade talföljden { int i = 0; int j = 0; int temp = 0; for(i = 0; i <= ANTAL-1; i++) { for(j = 0; j <= ANTAL-1-i; j++) { if(arry[j] > arry[j+1]) { temp = arry[j]; arry[j] = arry[j+1]; arry[j+1] = temp; } } } printf("Sorted list: \n"); for(i=0; i<ANTAL; i++) { printf("%d \n", arry[i]); } return 0; } /* int med(int x) int binar(int x)*/

Asus z270 Maximus Extreme | Intel i7 7700K | EVGA GTX 1080 FTW | 1TB WB Blue | 240GB Samsung 650 nvme | Fractal Design R6 | Corsair HX 1000W | Kingston 32GB DDR4 | Asus Swift PG278Q

Trädvy Permalänk
Medlem
Plats
Linköping
Registrerad
Jun 2007
Skrivet av kwame:

Körs koden för dig om du skriver 1 och sedan 2? För mig fungerar det bara på 3 och 4 dvs att det skriver ut.

Eftersom du "lurat" kompilatorn att anropa funktionerna utan argument så läser/skriver du till oallokerat minne på stacken, så lite vad som helst kan egentligen hända (s.k. odefinierat beteende).

Skrivet av kwame:

Sådär, efter en natts vila så löste jag det. Ser ni något som är galet? (även om allt nu fungerar)

Lite småsaker bara.

Varför returnerar mrndgen och sort int? Använd void istället för funktioner som inte returnerar någonting.

Varför har din arr-array storlek 100 istället för ANTAL? Personligen skulle jag också föredra att skicka in storleken på arrayerna i mrndgen och sort som argument, istället för att använda ANTAL inne i funktionerna. Det gör funktionerna flexiblare och enklare att återanvända i andra program. Det spelar egentligen ingen roll i en sån här övning, men något som är värt att fundera på.

Sen har du ändrat inläsningen med scanf till att läsa in ett tal istället för en karaktär. Det är inget problem i sig, men om användaren matar in något som inte är ett tal så kommer programmet balla ur. scanf kommer nämligen försöka läsa in ett tal, misslyckas, meny-loopen snurrar runt ett varv, scanf försöker igen, misslyckas, o.s.v. scanf returnerar dock hur många argument den lyckades fylla, så i just det här fallet kommer scanf returnera 0 när den misslyckas och 1 när den lyckas. Du kan använda det för att lägga till lite felhantering om du vill.

Trädvy Permalänk
Medlem
Registrerad
Feb 2006
Skrivet av perost:

Varför returnerar mrndgen och sort int? Använd void istället för funktioner som inte returnerar någonting.

Bra fråga haha, nu är det ändrat iaf!

Skrivet av perost:

Varför har din arr-array storlek 100 istället för ANTAL? Personligen skulle jag också föredra att skicka in storleken på arrayerna i mrndgen och sort som argument, istället för att använda ANTAL inne i funktionerna. Det gör funktionerna flexiblare och enklare att återanvända i andra program. Det spelar egentligen ingen roll i en sån här övning, men något som är värt att fundera på.

Nu har jag ändrat det till från [100] till [ANTAL].
Är lite osäker på vad du menar. Menar du att jag ska ha funktionens namn som void mrndgen(int x[ANTAL]) istället?
Hur får detta bort ANTAL inne i funktionerna? T.ex i mrndgen så är ju arrayen kallad för x[ANTAL]

Menar du att jag ska skriva om i for-loopen t.ex i < x[] och på så vis få bort antal?

Skrivet av perost:

Sen har du ändrat inläsningen med scanf till att läsa in ett tal istället för en karaktär. Det är inget problem i sig, men om användaren matar in något som inte är ett tal så kommer programmet balla ur. scanf kommer nämligen försöka läsa in ett tal, misslyckas, meny-loopen snurrar runt ett varv, scanf försöker igen, misslyckas, o.s.v. scanf returnerar dock hur många argument den lyckades fylla, så i just det här fallet kommer scanf returnera 0 när den misslyckas och 1 när den lyckas. Du kan använda det för att lägga till lite felhantering om du vill.

Ah smart där, tänkte inte alls på det!

Har nu skrivit om koden ännu en gång och lagt till en funktion som beräknar medelvärde, max och min. Ska även lägga till median senare. För median är det smartaste sättet att ta plats (50+51)/2 i arreyn? (vid 100 tal) Listan är ju sorterad.

Tack så himla mycket för att du tar din tid! Förstår att du inte kommer orka detta i all evighet dock. Grymt bra pointers iaf.

Asus z270 Maximus Extreme | Intel i7 7700K | EVGA GTX 1080 FTW | 1TB WB Blue | 240GB Samsung 650 nvme | Fractal Design R6 | Corsair HX 1000W | Kingston 32GB DDR4 | Asus Swift PG278Q

Trädvy Permalänk
Medlem
Plats
Linköping
Registrerad
Jun 2007
Skrivet av kwame:

Är lite osäker på vad du menar. Menar du att jag ska ha funktionens namn som void mrndgen(int x[ANTAL]) istället?
Hur får detta bort ANTAL inne i funktionerna? T.ex i mrndgen så är ju arrayen kallad för x[ANTAL]

Jag menar att du ska ändra till t.ex. void mrndgen(int x[], int n), där n är storleken på x, och sen använda n inne i funktionen. Funktionen blir då mer flexibel eftersom man då kan använda den för att t.ex. bara fylla en del av arrayen, och enklare att återanvända eftersom funktionen inte längre är beroende på att det finns en ANTAL-define.

Skrivet av kwame:

Har nu skrivit om koden ännu en gång och lagt till en funktion som beräknar medelvärde, max och min. Ska även lägga till median senare. För median är det smartaste sättet att ta plats (50+51)/2 i arreyn? (vid 100 tal) Listan är ju sorterad.

Ja, givet att arrayen faktiskt har blivit sorterad så är ju medianen det mittersta elementet. Ska man vara petig så finns egentligen inget mittersta element när arrayen har ett jämnt antal element, då brukar man ta medelvärdet på de två mittersta elementen istället.

Trädvy Permalänk
Medlem
Registrerad
Feb 2006

Edit: hittade felet själv.... hade inte lagt till \n i första printf-satsen och då skrevs den första talföljden (6) ut bredvid 1an (16)...

Tjenare SweC! Är tillbaks med en ny fråga - väldigt simpel (I guess).
Håller på med gamla tentor och en uppgift är "Skriv en funktion som slumpar 10 heltal mellan 1 och 6, lägger in dem i en vektor och sen skriver ut summan, medelvärdet, det största och det minsta talet. (5p)"

Mitt problem: har skrivit koden men oavsett vad jag gör så vägrar "mini" att få något annat värde än 16? Har haft samma problem tidigare under kursen när jag hållit på med liknande typ av frågor med just min-värdet. Har alltid på något vis fått det att fungera utan att riktigt se att jag gjort någon ändring. Vet inte om det är någon bugg i codeblocks eller vad jag gör galet. Har testat att lägga in if-statsen i den andra if-statsen, gjort om en av dom till en else if osv osv. Men ja, blir alltid 16, trots att den är satt till 10 och funktionen har inget större random än 6.

#include <stdio.h> #include <stdlib.h> int main() { int array[10]; int sum = 0, medel = 0, max = 0, i; int mini = 10; int tal = 0; for(i=0; i<10; i++){ tal = rand() % 6+1; array[i] = tal; if(array[i]<mini) { mini = array[i]; } if(array[i]>max) { max = array[i]; } sum = sum+array[i]; medel = sum/10; } printf("%d %d %d %d", sum, medel, max, mini); for(i=0; i<10; i++) printf("%d\n", array[i]); }

Asus z270 Maximus Extreme | Intel i7 7700K | EVGA GTX 1080 FTW | 1TB WB Blue | 240GB Samsung 650 nvme | Fractal Design R6 | Corsair HX 1000W | Kingston 32GB DDR4 | Asus Swift PG278Q

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Jan 2004
Skrivet av kwame:

Mitt problem: har skrivit koden men oavsett vad jag gör så vägrar "mini" att få något annat värde än 16? Har haft samma problem tidigare under kursen när jag hållit på med liknande typ av frågor med just min-värdet. Har alltid på något vis fått det att fungera utan att riktigt se att jag gjort någon ändring. Vet inte om det är någon bugg i codeblocks eller vad jag gör galet. Har testat att lägga in if-statsen i den andra if-statsen, gjort om en av dom till en else if osv osv. Men ja, blir alltid 16, trots att den är satt till 10 och funktionen har inget större random än 6.

Byt ut "printf("%d %d %d %d", sum, medel, max, mini);" mot "printf("%d %d %d %d\n", sum, medel, max, mini);"
Varför får du klura på själv.