Avatar billede tangveje Nybegynder
17. juli 2004 - 19:38 Der er 18 kommentarer og
2 løsninger

Arrays, pointers og funktioner

Jeg har følgende funktion, som finder det laveste tal i et array, og ændrer det til et 0. Da jeg er forholdsvist uerfaren i C++, og dette oprindeligt var en javascript funktion, er jeg ikke helt sikker på det er den bedste måde at gøre det på, men anyway...

Mit problem er at den skal ændre det oprindelige array (det som jeg sendte til funktionen) og ikke funktionens lokale kopi, eller hvordan man nu skal sige det. Jeg går ud fra jeg skal bruge pointers til det formål, men ingen af de adskillige tutorials/bøger jeg har læst har formået at forklare pointers på en måde jeg forstår :(

Har søgt på google, og forsøgt mig frem på utallige måder, men kan ikke få det til at virke, så jeg håber nogen her kan forstå hvad jeg ævler om og forklare hvordan jeg gør :)

void RemoveLowest( int arr[], int length )
{
    int minidx, min = 1000 ;

    for( int i = 0 ; length > i ; i++ )
    {
        if( min > arr[i] )
        {
            min = arr[i] ;
            minidx = i ;
        }
    }

    arr[minidx] = 0 ;
}
Avatar billede arne_v Ekspert
17. juli 2004 - 19:41 #1
Virker det ikke som det ser ud nu ?
Avatar billede arne_v Ekspert
17. juli 2004 - 19:43 #2
Det bør det gøre fordi:

int arr[]

er det samme som

int *arr

og er derfor en pointer.
Avatar billede tangveje Nybegynder
17. juli 2004 - 19:50 #3
Virker ikke nej, men jeg er ikke helt sikker på hvorfor, dette var mit første gæt :)

Havde godt nok læst at arrays teknisk set er pointers, men tænkte jeg måske havde misforstået noget.

Her er hele min kode, hvis det kan hjælpe... det er et lille program til at "kaste terninger", specielt beregnet til rollespil (D&D). Jeg bruger C++ builder 5. Problemet er at den ikke fjerner det laveste tal når jeg ber den om det, alt andet virker som det skal.

#include <vcl.h>
#include <cstdlib>
#include <ctime>
#pragma hdrstop

#include "dice.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;

void RemoveLowest( int arr[], int length )
{
    int minidx, min = 1000 ;

    for( int i = 0 ; length > i ; i++ )
    {
        if( min > arr[i] )
        {
            min = arr[i] ;
            minidx = i ;
        }
    }

    arr[minidx] = 0 ;
}

int randrange(int low, int high)
{
    int range = rand() % (high - low + 1) + low ;

    return range ;
}

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::rollbuttonClick(TObject *Sender)
{
    // Clear the previous result
    result->Caption = "" ;

    // get the number and kind of dice, converted to integers
    int num = numdice->Text.ToInt() ;
    int die = dietype->Text.ToInt() ;

    int rn, r, i = 0 ;

    int rolls[999] ;
    AnsiString tmp ;

    for ( i = 0 ; i < num ; i++ )
    {
        // Roll the dice
        rn = randrange( 1, die ) ;

        rolls[i] = rn ;

        // Add this roll to total
        r = r + rn ;
    }

    if ( removelowest->Checked )
    {
        int n = sizeof( rolls ) / sizeof( rolls[0] ) ;

        RemoveLowest( rolls, n ) ;
    }

    for ( i = 0 ; i < num ; i++ )
    {
        if ( rolls[i] != 0 )
        {
            // If this is the last roll, don't add the trailing '+'
            if ( i == num - 1 )
            {
                tmp = tmp + rolls[i] ;
            }
            else
            {
                tmp = tmp + rolls[i] + " + " ;
            }
        }
    }

    result->Caption = tmp ;

    // Write out total
    total->Caption = r ;
}
Avatar billede thomas_nj Nybegynder
17. juli 2004 - 20:03 #4
Meget grim kode men hos mig virker det som du vil have det
#include <iostream>
                                                                               
using namespace std;
                                                                               
void a(int arr[])
{
        arr[1]=3;
}
                                                                               
int main()
{
        int y[2];
                                                                               
        a(y);
        cout<<y[1]<<endl;
        return 0;
}
Avatar billede tangveje Nybegynder
17. juli 2004 - 20:07 #5
Heh, ja jeg indrømmer det nok ikke er det kønneste, som sagt er jeg ikke så skrap til det endnu :)

Men så må det jo være noget andet i koden der giver problemet... men hvad
Avatar billede thomas_nj Nybegynder
17. juli 2004 - 20:08 #6
#include <iostream>
                                                                               
using namespace std;
                                                                               
void RemoveLowest( int arr[], int length )
{
    int minidx;
    int  min = 1000;
                                                                               
    for( int i = 0 ; length > i ; i++ )
    {
        if( min > arr[i] )
        {
            min = arr[i] ;
            minidx = i ;
        }
    }
                                                                               
    arr[minidx] = 0 ;
}
                                                                               
int main()
{
        int y[2];
        y[0]=4;
        y[1]=7;
                                                                               
        RemoveLowest(y, 2);
        cout<<y[0]<<endl;
        return 0;
}
Avatar billede thomas_nj Nybegynder
17. juli 2004 - 20:10 #7
Skal lige siges jeg hentydede til min egen kode da jeg sagde grim :)
ovenstående virker for mig. Det eneste jeg har ændret i din funktion er    int minidx, min = 1000;
Avatar billede arne_v Ekspert
17. juli 2004 - 20:13 #8
int rolls[999] ;

int n = sizeof( rolls ) / sizeof( rolls[0] ) ;

        RemoveLowest( rolls, n ) ;

fjerner den laveste ud af de 999 - skal du ikke kun fjerne den laveste
ud af dem der er "slået" (altså num) ?
Avatar billede tangveje Nybegynder
17. juli 2004 - 20:16 #9
thomas > Tak, nu regner den rigtigt :)

arne > Jo, jeg ville også meget gerne lave mit array dynamisk istedet for at sætte det til 999, men så vidt jeg har forstået er det ikke lige til i C++ :( Kender du en bedre løsning?
Avatar billede arne_v Ekspert
17. juli 2004 - 20:20 #10
Det er ikke så svært i C++.

Brug en STL vector.
Avatar billede thomas_nj Nybegynder
17. juli 2004 - 20:20 #11
du kan vel bruge en vector.
  Tror du kan læse noget du kan bruge her: http://www.cplus.about.com/library/weekly/aa050102a.htm
Avatar billede tangveje Nybegynder
17. juli 2004 - 20:48 #12
OK, det vil jeg kigge nærmere på. Men tak for hjælpen i hvert fald :)

Lægger i nogen svar?
Avatar billede arne_v Ekspert
17. juli 2004 - 20:58 #13
ok
Avatar billede thomas_nj Nybegynder
18. juli 2004 - 15:45 #14
held og lykke med spillet
Avatar billede dilleberg Nybegynder
18. juli 2004 - 16:05 #15
Hvis dit array indeholder følgende værdier:
1001, 1002, 1003
får du problemer, fordi minidx så er uinitaliseret.

void RemoveLowest(int arr[], int length)
{
  if (length > 0)
  {
    int minidx = 0, min = arr[0];

    for (int i = 1; length > i; i++)
    {
      if (min > arr[i])
      {
        min = arr[i];
        minidx = i;
      }
    }

    arr[minidx] = 0;
  }
}

er efter min mening mere sikker.
Måske kan værdierne i arr ikke være større end 1000, men det skriver du ikke noget om.

db
Avatar billede arne_v Ekspert
18. juli 2004 - 16:10 #16
Nu har jeg en formodning om at arrayet indeholder værdier 1-6 (sådan plejer
terninger at være).

Men du har selvfølgelig fuldstændigt ret.
Avatar billede dilleberg Nybegynder
18. juli 2004 - 18:38 #17
arne_v: Hvis length er 0 ville minidx stadig være uinitaliseret.
For at være 100% sikker bør iøvrigt også testes om arr == NULL .

db

PS: Jeg har set terninger med 20 sider :-)
Avatar billede olennert Nybegynder
20. juli 2004 - 10:33 #18
Hvis du skifter fra array til std::vector bliver koden lidt pænere:

#include <vector>
#include <algorithm>
typedef std::vector<int> IntVec;
using std::min_element;
void RemoveLowest(IntVec& vec) {
    IntVec::iterator least = min_element(vec.begin(), vec.end());
    if (least != vec.end())
        *least = 0;
}
Avatar billede blackautt Nybegynder
21. juli 2004 - 15:28 #19
Hvis det er en terningefunktion du skal bruge, kan du evt. gøre som følger (den fjerner ikke det laveste tal, men du kan selv definere præcist hvilken tal række du vil bruge, så hvis du vil sortere 1'ere fra, så bruger du bare (2,6) ) :

int diceRoller(int min_value, int max_value)
{
  int random;
  srand ( static_cast <unsigned> (time(0)) );
  while(1)
  {
    random = rand();
    if((random >= min_value)&&(random <= max_value))
      break;     
  }
  return random;
}

Jeg bruger selv denne funktion i mit "prisvindende" ascii rpg :)

Den er måske ikke så avanceret, men den er lille, let at overskue og virker :)
Avatar billede tangveje Nybegynder
23. juli 2004 - 17:05 #20
Undskyld tiden, er lige flyttet og er derfor uden internet for tiden :(

Tak for alle kommentarerne, vil prøve at kigge på det når jeg kommer hjem og se hvad jeg kan finde ud af :)

PS. I D&D har man terninger med op til 20 sider, men man regner med terninger helt op til 100 sider, og det ville ikke undre mig at nogen kunne finde på at bruge endnu større terninger til diverse besynderlige formål :)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester