C. Void funktioner, hjälp! (grovt nybörjare)

Permalänk

C. Void funktioner, hjälp! (grovt nybörjare)

Förstår ej void funktioner i C, känns så sjukt ointuitivt att ha en funktion som ej skickar tillbaka ett värde, skulle upskattas enormt om någon kunde hjälpa mig förstå. För en gångs skull hjälper ej google.

Permalänk
Medlem

Du får nog utveckla dig lite, varför tycker du att det är konstigt med en funktion som inte returnerar något?

Permalänk
Medlem

Har inte jobbat med just C men en void funktion kan vara användbar av flera olika anledningar, t ex om den endast ska skriva ut ett värde med en viss formatering i konsolen eller liknande.

Visa signatur

Processor: R5 2600 Moderkort: X470-F Gaming Grafikkort: Nvidia 3080 FE Ram: Trident Z Neo 16gb Nätaggregat: CM 850V Chassi: FD Meshify C Lagring: Corsair MP510 1TB, Crucial MX300 750gb

Permalänk
Medlem

@lesscool10: En void kan vara bra om du vill få saker gjort utan att få tillbaka något eller vill checka av saker. Och som ovan nämnde att kunna skriva ut saker. T.ex.

void print_number(int numer) { printf("The number is: %d", number); } Eller t.ex.: void check_system(char a) { // Borde man starta systemet? Om användaren matade in y (yes) så startas systemet. // Om inte 'y' matades in så stoppas systemet. if(a == 'y') { // Kallar på en till funktion som startar hela programmet eller systemet start_system(); } else { stop_system(); // Kallar på en funktion som stoppar hela programmet. } }

Där har du 2 exempel på hur void kan användas. Det är när man vill att något "ska hända", utan att du nödvändigtvis behöver få tillbaka något.

Har ingen formatering alls så ni får ursäkta om det blev en space för mycket/lite

Permalänk

@Alotiat: Förstår lixom inte hur funktionen skall skrivas, skulle du kunna visa någon sjukt basic void funktion som är lätt att förstå? som typ denna fast void?

#include <stdio.h>

int divide(int a, int b);

int main(int argc, char** argv) {
int a, b = 3;

printf("enter\n" );
scanf("%d\n",&a );

int n = divide(a, b);

printf("%d\n", n);

return 0;
}
int divide (int a, int b){
int c = a / b;

return c;
}

Permalänk
Hedersmedlem
Skrivet av lesscool10:

@Alotiat: Förstår lixom inte hur funktionen skall skrivas, skulle du kunna visa någon sjukt basic void funktion som är lätt att förstå? som typ denna fast void?

#include <stdio.h>

int divide(int a, int b);

int main(int argc, char** argv) {
int a, b = 3;

printf("enter\n" );
scanf("%d\n",&a );

int n = divide(a, b);

printf("%d\n", n);

return 0;
}
int divide (int a, int b){
int c = a / b;

return c;
}

Det finns sätt att skriva divide som en void-funktion men det är väl ett fall där det vore olämpligt.

Men säg att du vill skriva ut en gångertabell eller något baserat på ett tal. Ja då kan du ju göra en void-funktion PrintMultiplicationTable som tar in en siffra som säger vilken tabell och sen gör void-funktionen hela arbetet med att räkna fram alla värden i tabellen och skriva ut. Det behövs ju inte returvärde då.
Det gäller helt enkelt att anpassa användandet efter när det är lämpligt.

Permalänk

@Shimonu: Tog bara detta som exempel för att visa vilken nivå de rör sig om. Men t,ex ett program som läser in en sträng, och sen räknar hur många och vilka vokaler strängen innehåller, och gör detta med en void funktion.

Permalänk
Medlem

@lesscool10 Läs in strängen i "main()", skicka den strängen som argument till "void vocal()" och bestäm där vilka tecken som är vokaler, och skriv ut dessa.
Du behöver således inte returnera något till main() utan allt löses i vocal()

Visa signatur

FD Define Mini C | ASRock Z97E-ITX | Intel i7 4790k | Asus STRIX GTX 1070Ti OC
Adata 16GB 1600MHz | Samsung 850 Evo 500GB | OCZ 240GB | EVGA G2 650W
Huawei Honor8 | Lenovo Y14ISK

Permalänk
Medlem
Skrivet av lesscool10:

@Shimonu: Tog bara detta som exempel för att visa vilken nivå de rör sig om. Men t,ex ett program som läser in en sträng, och sen räknar hur många och vilka vokaler strängen innehåller, och gör detta med en void funktion.

I ditt exempel som du tar upp kan man kanske tänka sig två scenarion.
1. Du vill räkna ut antalet vokaler i en sträng och använda dig av resultatet.
2. Du vill räkna ut antalet vokaler i en sträng utan att faktiska behöva använda dig av resultatet ytterligare, utan endast vill visa vad svaret faktiskt vad.

Tar detta i lite mera pseudokod:

function main() { String userInput = readInputFromUser(); // Läs in någon sträng // 1. Här returnerar vi för att vi behöver ha svaret för att kunna räkna ut antalet konsonanter i strängen. Int vowels = calculateVowels(userInput); Int consonants = userInpt.length() - vowels; print("Number of consonats" + consonants.toString()); // 2. Vi kanske bara behövde skriva ut antalet vokaler, så vi anropar bara funktionen som räknar och skriver ut det. showVowels(userInput); } Int function calculateVowels(String userInput) { Int numberOfVowels; // Do some calculation return numberOfVowels; } void function showVowels(String userInput) { Int numberOfVowels; // Do some calculation print("Number of vowels: " + numberOfVowels.toString()); }

Funktioner i allmänhet är bra för att dels göra koden mer lättlast. Flödet i koden och vad som händer blir tydligare genom att dela upp sin kod i metoder/funktioner som redan i namnet beskriver vad som händer. Sedan är inte void-funktioner till för att endast printa ut saker, utan kan såklart användas för mera saker, men detta kanske hjälper dig i dina tankar.

Permalänk

Det är inte alltid viktigt att returnera data, void-funktioner kan returnera data genom att skicka in en pekare som argument vars data du ändrar på.

Till exempel såhär:

void dogYearsToHuman(unsigned short dogYears, unsigned short* humanYears) { // formula is dog age times seven is human age. *humanYears = dogYears * 7; } .... unsigned short dogYearsToHuman(unsigned short dogYears) { return dogYears * 7; }

Den undre kommer skapa en unsigned short på stacken för resultatet, medans den ovan kommer ha skapats en gång i förväg på stacken.

Vidare läsning:
http://www-cs-students.stanford.edu/~sjac/c-to-cpp-info/refer...

Permalänk
Medlem
Skrivet av LinusNeuman:

Det är inte alltid viktigt att returnera data, void-funktioner kan returnera data genom att skicka in en pekare som argument vars data du ändrar på.

Men då säger man inte att den returnerar något, utan man säger att den har en "sido-effekt" ("side effect").

Att en funktion returnerar "void" är bara en notation.
En matematisk funktion returnerar ju alltid något... så då fick det bli "void" för att beteckna avsaknad av ett returvärde.

I en del andra programmeringsspråk som t.ex. Pascal så delades det upp i "function" som alltid returnerar något och "procedure" som inte har returvärde.

Visa signatur
Permalänk
Medlem

Du kanske inte alltid behöver ett returvärde som resultat?
Reboot () är ju ett exempel. Även om det ofta är snyggare att köra med returvärden för att kunna hantera fel, loggning osv.

Skickades från m.sweclockers.com

Permalänk
Medlem
Skrivet av lesscool10:

Tog bara detta som exempel för att visa vilken nivå de rör sig om. Men t,ex ett program som läser in en sträng, och sen räknar hur många och vilka vokaler strängen innehåller, och gör detta med en void funktion.

Du verkar tänka lite bakvänt, funktioner som inte returnerar något uppstår naturligt när man kodar. Istället för att fundera på hur du löser ett visst problem med en void-funktion så är det bättre att fundera på i vilka situationer void-funktioner är lämpliga att använda. Du har redan fått massvis av exempel i tråden, men fortsätter du koda C så kommer du förr eller senare stöta på fallet där du har en funktion som inte har något vettigt att returnera.

Permalänk
Skrivet av Findecanor:

Men då säger man inte att den returnerar något, utan man säger att den har en "sido-effekt" ("side effect").

Att en funktion returnerar "void" är bara en notation.
En matematisk funktion returnerar ju alltid något... så då fick det bli "void" för att beteckna avsaknad av ett returvärde.

I en del andra programmeringsspråk som t.ex. Pascal så delades det upp i "function" som alltid returnerar något och "procedure" som inte har returvärde.

Jag tänker mer "returnera genom att" för att personen lättare ska förstå men det är ju helt rätt att det egentligen vore fel att säga att den returnerar data. Aldrig hört den termen side effect dock, spännande!

Permalänk
Medlem
Skrivet av lesscool10:

@Shimonu: Tog bara detta som exempel för att visa vilken nivå de rör sig om. Men t,ex ett program som läser in en sträng, och sen räknar hur många och vilka vokaler strängen innehåller, och gör detta med en void funktion.

Om du ska använda värdet för antalet vokaler senare i programmet så är det bäst att helt enkelt returnera värdet, alltså så ej returnera void. Men låt säga att du bara ska printa ut värdet efter att det är uträknat, du ska inte använda det till något annat senare. Då skulle det finnas två approaches:

Antingen returnerar din funktion värdet, så printar du ut det i main.

Men, du skulle ju lika gärna kunna göra print-delen i själva funktionen, det finns egentligen ingen anledning att göra denna del i main. Faktum är att jag själv tycker det är mycket snyggare med en så "clean" main som möjligt, så jag skulle nästan föredra att printa ut värdet i själva funktionen. Om man nu skulle printa ut värdet i funktionen, då finns det inget behov av att returnera något, uppgiften är redan slutförd. Det är här du kan returnera void.

Permalänk

@jH0Ni: förstår lixom inte ens hur funktionen skall skrivas, då den ej returnerar något, ta exemplet nedan, hur skulle man rätta det?

#include<stdio.h>

void count_vowels(char str[]);

int main ( int argc, char** argv) {

char i, vowels[] = {'a','o','u','e','i','y'};
int j, count[] = {0, 0, 0, 0, 0, 0};
char str[10];

printf("enter\n" );
scanf("%s", str);

for (int i = 0; str[i] !='\0'; i++){
for (int j = 0; j < 6; j++){
if (str[i] == vowels[j]){
count[j]++;
break;
}
}
}
for (int i=0; i<6; i++){
printf("Num of %c %d\n",vowels[i], count[j] );
}

return 0;

}
void count_vowels(char str[]){

return ;
}

Permalänk
Medlem

@lesscool10: Oftast i nybörjar sammanhang använder man endast void funktioner om man har en funktion som INTE ska returnera någonting. Så att skriva om en funktion som ska returnera nånting till en void funktion är inte relevant för nybörjare.

Tänk dig istället att du har en funktion som räknar ut någonting, vi använder den funktionen flera gånger och sparar svaren i en vektor. Vi kan då använda en void funktion för att enkelt skriva ut alla våra svar.

void printAns(int answers[], int arraySize){ for(i=0; i < arraySize; i++){ printf("%d", answers(i)); } }

Om du fortfarande är intresserad av hur du ska lösa ditt senaste exempel titta på tidigare svar som rör pointers. Du kan ändra variablers värde utanför funktionen med hjälp av pointers. Många tidigare svar här som använder pointers

Permalänk
Hedersmedlem
Skrivet av lesscool10:

@jH0Ni: förstår lixom inte ens hur funktionen skall skrivas, då den ej returnerar något, ta exemplet nedan, hur skulle man rätta det?

#include<stdio.h>

void count_vowels(char str[]);

int main ( int argc, char** argv) {

char i, vowels[] = {'a','o','u','e','i','y'};
int j, count[] = {0, 0, 0, 0, 0, 0};
char str[10];

printf("enter\n" );
scanf("%s", str);

for (int i = 0; str[i] !='\0'; i++){
for (int j = 0; j < 6; j++){
if (str[i] == vowels[j]){
count[j]++;
break;
}
}
}
for (int i=0; i<6; i++){
printf("Num of %c %d\n",vowels[i], count[j] );
}

return 0;

}
void count_vowels(char str[]){

return ;
}

Du behöver slappna av ditt tänkande lite. Du försöker tvinga in en fyrkantig kloss genom ett runt hål och behöver inse att det inte är så det fungerar.
En funktion count_vowels vore lämplig att ha returnera ett värde. Men säg din for-loop i slutet av main, den skulle kunna stoppas i en funktion som är void. Gör en funktion print_result som tar in arrayer vowels och count och sen klistrar du bara in din for-loop. Med reservation för att jag bara slängt ett öga på din kod.

Permalänk
99:e percentilen
Skrivet av lesscool10:

Förstår ej void funktioner i C, känns så sjukt ointuitivt att ha en funktion som ej skickar tillbaka ett värde

Du slår huvudet på spiken mycket mer än du anar.

Det finns goda skäl att argumentera för att funktioner med returtypen void i imperativa språk inte borde kallas funktioner alls, eftersom de i praktiken inte är sådana. En void-funktions användbarhet ligger nämligen i praktiken alltid i dess sidoeffekter, och sidoeffekter tenderar allt som oftast att bli ett fruktansvärt gissel när ett program växer.

Den bästa rekommendationen jag kan ge dig om du vill bli en bra programmerare är att bygga din mjukvara av så många pure functions som möjligt, och att undvika sidoeffekter i så stor utsträckning du kan (utan att överdriva). (Det finns undantag, beroende på språk, prestandakrav och så vidare.)

Det jag säger är alltså inte att du aldrig ska använda sidoeffekter, utan att du ska försöka undvika dem när en pure function gör jobbet minst lika bra, och att du ska undvika att bygga ett helt program som "består" av en massa sidoeffekter. Här är ett exempel på vettig användning av sidoeffekter:

#include<stdio.h> void printInt(int x) { printf("%i", x); } int main() { printInt(5); return 0; }

Det tål att nämnas att i de flesta imperativa språk kan sidoeffekter förekomma i såväl "funktioner" med ett returvärde som i void-"funktioner". Till exempel är detta ett exempel på (i allmänhet) dålig kod:

int globalVariable = 0; int f(int x) { globalVariable++; return 2*x; }

Och här är ett liknande exempel utan sidoeffekter:

int f(int x) { return 2*x; }

En funktion utan sidoeffekter är mycket enklare att förstå, verifiera och förbättra.

Visa signatur

Skrivet med hjälp av Better SweClockers