C programmering, söka efter värde i array

Permalänk
Medlem

C programmering, söka efter värde i array

Hej!

Jag har precis börjat lära mig c programmering och har stött på lite problem när det kommer till arrayer och funktioner. Jag ska skapa ett program som slumpar fram 10 tal mellan 0 och 10 och spar dessa i en array. Jag ska sedan kunna räkna antalet förekomster av ett givet tal i denna array.

Jag har skapat 3 funktioner, en för att skapa arrayen med slumpade tal, en för att skriva ut arrayen samt en som ska göra själva sökningen. Jag tror jag har kommit en bit på vägen men det fungerar inte riktigt med sökningen. Summan fungerar inte alls och räknar helt tokigt. Jag tror det har att göra med att jag inte returnerar arrayen på rätt sätt. Hur ska jag göra detta för att få det att fungera?

#include <stdio.h> #include <stdlib.h> #include <time.h> int * rand_array(); int print_arr(int numbers[]); int search(); int main() { srand((time(NULL))); print_arr(rand_array()); printf("\n\nTalet 2 f\x94rekommer %i g\x86nger\n", search()); return 0; } int * rand_array(){ int i; static int numbers[10]; for(i=0; i<10; i++) numbers[i] = rand() % 11; return numbers; } int print_arr(int numbers[]){ int i; int *p; p = rand_array(); for (i = 0; i < 10; i++ ) printf("Tal: %i\n", *(p + i)); } int search(){ int i, *sum = 0; int *numbers = rand_array(); for (i=0; i <= 10; i++) { if (*(numbers + i) == 2) sum++; } return sum; }

Permalänk
Medlem

Nu är jag ingen programmerare och koden är snudd på rappakalja för mig
Men behöver du inte spara undan resultatet av det första anropet av rand_array() för att samma nummerlista ska kunna användas i de senare funktionerna?
Varje anrop av funktionen bör ju slumpa ut en helt ny lista av siffor.

Dvs något i still med.
list_of_numbers = rand_array()

print_array(list_of_numbers)

search_array(list_of_numbers)

Permalänk
Medlem

I funktionen search så deklarerar du sum som "int *sum = 0", dvs. en pekare till int som pekar på addressen 0. Eftersom sum är en pekare till int så kommer sum++ därför att öka sum med storleken på en int (förmodligen 4). Så låt helt enkelt bli att deklarera sum att vara en pekare så kommer det nog att fungera bättre.

Din kompilator borde dessutom ge dig en varning när du försöker returnera sum som en int, eftersom det inte är så bra att implicit konvertera en pekare till int (en address kan vara större än en int på t.ex. 64-bitars OS). Så om du inte får en varning för det så bör du nog kolla om det går att slå på lite mer varningar i din kompilator. Som nybörjare bör du aldrig ignorera varningar eftersom de nästan alltid indikerar buggar i din kod.

Permalänk
Datavetare

Två huvudproblem:

  1. du genererar 10 nya tal i varje delfunktion då du anropar rand_array() totalt 3 gånger

  2. variabel sum har typen int* vilket betyder att den ökas med antal bytes en int tar i minnet (i praktiken 4 på alla "normal" CPUer) varje gång du kör "++". sum borde nog heta cnt eller liknande då den räknar något och den ska ha typen int eller unsigned i stället för int*.

Rent generellt bör man undvika statiska variabler då det lätt blir oönskade effekter, bättre att allokera minnet för din array på ett specifikt stället och skicka in den + storlek (eller ännu hellre skapa en array struktur) till varje funktion.

Här en början till programmet

.... void rand_array(int *arr, size_t arr_sz); int print_arr(int *arr, size_t arr_sz); int search(int *arr, size_t arr_sz, int what); #define ARR_SZ 10 int main() { int numbers[ARR_SZ]; srand((time(NULL))); rand_array(numbers, ARR_SZ); print_arr(numbers, ARR_SZ); printf("\n\nTalet 2 förekommer %i gånger\n", search(numbers, ARR_SZ, 2)); } void rand_array(int *arr, size_t sz) { int i; for(i = 0; i < sz; i++) arr[i] = rand() % 11; } ....

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk
Medlem

Tack så mycket för svaren!

Yoshman, jag förstår inte riktigt varför man ska skicka in int *arr, size_t sz i rand_array funktionen. Varför ska det vara invärden i den funktionen? Den funktionen ska väl enbart returnera ett värde? Eller har jag fel?

Hur ska jag göra istället för att anropa rand_array() utan att värdena ändras?

I koden som du skrev Yoshman så returneras inget värde vad jag förstår på rand_array?

Permalänk
Datavetare
Skrivet av Kallgard:

Tack så mycket för svaren!

Yoshman, jag förstår inte riktigt varför man ska skicka in int *arr, size_t sz i rand_array funktionen. Varför ska det vara invärden i den funktionen? Den funktionen ska väl enbart returnera ett värde? Eller har jag fel?

Hur ska jag göra istället för att anropa rand_array() utan att värdena ändras?

I koden som du skrev Yoshman så returneras inget värde vad jag förstår på rand_array?

Om du tar pekar till något så kan det används som in- och ut-värden. Vidare, om man använder automatiskt variabler, "allokerar på stacken", som numbers är i mitt fall så måste man se till att alla funktioner som använder detta minne anropas av den som allokerat minne för att det ska vara giltigt.

Anledningen att jag skickar in en pekare och en längd är för att det inte finns något generellt sätt att ta reda på hur stort utrymmet är som en viss pekare pekar på.

En pekare refererar till en eller flera minnesceller i dator. Är därför man kan använda pekare som in/ut-data, det man skriver i utrymmet som pekaren refererar till kan även läsas/skrivas av andra funktioner som får samma pekare.

Dåligt exempel rent designmässigt, men för att belysa hur pekare kan använda som ut-data

int mul_by_two_by_val(int n) { return n * 2; } void mul_by_two_by_ptr(int n, int *result) { *result = n * 2; } int main() { int n; int n_times_two; n = 3; n_times_two = mul_by_two_by_val(n); /* 'n_times_two' is now 6 n = 5; mul_by_two_by_ptr(n, &n_times_two); /* 'n_times_two' is now 10 */ }

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk
Medlem

Okej tack! Tror jag förstod lite bättre med ditt exempel! Ska se ifall jag kan få ordning på programmet

Permalänk
Medlem

Försök också att tänka på när du loopar att du inte får "Array index out of bound".

Visa signatur

Corsair 16GB (4x4096MB) CL9 1600Mhz | Asus P8Z77-V PRO |
Samsung SSD Basic 830-Series 256GB | Intel Core i7 3770K 3,5Ghz |
Asus Xonar Essence STX | Noctua NH-U9B SE2 | Antec Performance One P280 | Corsair HX 850W 80+ Gold Modulär | MSI GTX 770

Permalänk
Medlem

Det är väl samma princip som funktionen scanf använder sig av. Man skickar pekare till variabeln som ska uppdateras genom att sätta & framför variabeln (om det inte redan är en pekare). Men ska man uppdatera en sträng så sätter man inget & framför strängen i scanf eftersom arrayer (en sträng i C är ju en array av char) egentligen är pekare från början. Vet inte om det var ett jättebra exempel men ofta får man lära sig om scanf innan man lärt sig om pekare och då säger de typ "så är det bara, det förklarar vi senare" när man undrar varför det ska vara & framför variabeln men inte framför en sträng.

Så det blir samma sak om man skriver egna funktioner som ska uppdatera en array. Då skickar man pekare till arrayens första värde till funktionen och arrayens storlek alternativt arrayens maximala storlek om det ska fyllas på med fler värden. Så länge en funktion endast ska returnera ett enda värde så kan man ju skicka tillbaka en kopia av värdet med return i funktionen men när man ska uppdatera många värden i funktionen får man skicka pekare till de värden som ska uppdateras in till funktionen som parametrar. En array är ju en pekare till en början av många värden i minnet. Men själva pekaren är ett enda värde.

Kanhända jag fattat en del saker fel, håller själv på att uppdatera mina C-kunskaper efter många års uppehåll. Läste C på högskolan runt år 1990 men sedan har det legat lite i träda och nu försöker jag uppdatera kunskaperna.