Toon posts:

[c] array uitlezen en daaruit vergelijken

Pagina: 1
Acties:
  • 590 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
Ik heb hier twee arrays met alleen maar integers.
Nu wil ik bij deze twee arrays de waardes uitlezen, en deze mogelijk met elkaar vergelijken.

Bijvoorbeeld of allebei in de array een 1 voorkomt. (zo dus ook de andere 9 getallen kunnen checken)

Ik weet niet of er zo'n soort functie ervoor is, heb zelf namelijk niets kunnen vinden.

[ Voor 10% gewijzigd door Verwijderd op 21-09-2004 17:17 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 13:55
In C zul je hier een eigen functie voor moeten schrijven, waarschijnlijk met een paar for-lusjes. De vraag is echter wat je onder 'vergelijken' verstaat. Vergelijken of ze identiek zijn kan in principe nog wel met memcmp(), maar verder zul je zelf verschillende code voor verschillende doeleinden moeten schrijven.

Verwijderd

Topicstarter
bijvoorbeeld heb ik hier twee variabele a en b:

a=[1,2,5,4,8,5,6]
b=[0,0,0,0,0,0,2,3,1]

Hier zie je dus dat 2 en 1 in allebei de variabele voorkomt.
Zoiets bedoel ik

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 13:55
Voor zover ik weet is de standaardmanier om dat op te lossen, eerst het sorteren van beide arrays en vervolgens de elementen te vergelijken. Als je ze gesorteert hebt, doe je iets van:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
x = begin van a;
y = begin van b;
herhaal zolang x of y nog geldig zijn:
{
  als x == y:
  {
    print x // (of y natuurlijk)
    x = volgende element uit a
    y = volgende element uit b
  } 

  als x < y:
  {
    x = volgende element uit a
  }

  als y < x:
  {
    y = volgende element uit b
  }
}

Dat dit werkt is misschien niet direct duidelijk, maar als je het op papier uittekent voor een paar voorbeelden kun je het wel inzien, denk ik. Op deze manier kun je ook dubbele elementen verwerken (als het getal 3 in a twee keer voor komt en in b drie keer, dan wordt hij dus twee keer geprint).

Een andere mogelijkheid, als elementen in de arrays uniek zijn, is de arrays samenvoegen en sorteren en dan dubbelen tellen (dat is voor een gesorteerde array makkelijk, omdat de dubbelen achter elkaar staan).

Verwijderd

Topicstarter
[qoute]
Een andere mogelijkheid, als elementen in de arrays uniek zijn, is de arrays samenvoegen en sorteren en dan dubbelen tellen (dat is voor een gesorteerde array makkelijk, omdat de dubbelen achter elkaar staan).[/qoute]

Hoe kan ik die arrays dan samenvoegen en gelijk sorteren....
Je stopt dan die a en b in de variabele c.

Maar hoe kan ik ze uitlezen op dubbele waarde?
zoiets als
code:
1
2
3
4
5
6
7
8
if (c[i] <2 & c[i] >0)
{
printf("geen dubbele");
}
else
{
printf("wel dubbele");
}

dit is heel wel heel gekke code, maar ala O-)

[ Voor 5% gewijzigd door Verwijderd op 22-09-2004 17:12 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 13:55
Die tweede methode werkt alleen als de elementen uniek zijn. (Vaak is dat het geval als je met verzamelingen werkt en de vereniging zoekt, zoals hier.) Je kunt ze niet 'tegelijkertijd' samenvoegen en sorteren en je zult dus een kopie moeten maken.

Bijvoorbeeld:
a = [ 1, 2, 3, 4, 5 ]
b = [ 3, 7, 1, 0, 2 ]

Je concateneert:
ab = [ 1, 2, 3, 4, 5, 3, 7, 1, 0, 2 ]

En sorteert: (qsort in de C standard library is prima geschikt)
ab = [ 0, 1, 1, 2, 2, 3, 3, 4, 5, 7 ]

En vervolgens loop je er doorheen:
code:
1
2
3
4
5
6
7
for(n = 1; n < [lengte van ab]; ++n)
{
    if(ab[n] == ab[-1])
    {
        /* ab[n] is dubbel en zat dus in beide sets! */
    }
}

De eerste methode is naar mijn idee beter, omdat hij ook werkt voor arrays waarin elementen dubbel kunnen voorkomen.

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Wat is nu de vraag van de TS? Vraagt hij om een algoritme, of weet hij welk algoritme er nodig is en vraagt hij om de naam van een algoritme in C? De [C] tag suggereert het laatste, dus we kunnen beter de TS laten uitleggen hoe het algoritme werkt.

miej, kun je in pseudo-code of zo uitleggen wat er moet gebeuren? Je voorbeeld is duidelijk, ik snap wat het resultaat moet zijn. Maar hoe zou je dat doen als ik je twee stapels kaarten zou geven en ik je vraag welke kaarten er in beide stapels voorkomen?

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Verwijderd

Topicstarter
Ik zou dan de 1ste kaart van stapel 1 pakken, en met die kaart alle kaarten van de andere stapel mee vergelijken.

Maar ik heb nu een stuk code geproduceerd, maar naar mijns inzien zou hij moeten werken, maar het is niet helemaal goed denk ik (anders post ik dit ook niet)

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <stdio.h>

#define BUFFER 10

int main()
{

int aantalvar1;
int aantalvar2;

printf("Hoeveel inhoud mag A hebben?\t");

scanf("%i", &aantalvar1);

    if (aantalvar1 > BUFFER)
        {
                printf("A Mag niet groter als %d zijn", BUFFER);
                return 1;
        }

printf("\nHoeveel inhoud mag B hebben?\t");

scanf("%i", &aantalvar2);
    
    if (aantalvar2 > BUFFER)
        {
                printf("B Mag niet groter als 10 zijn");
                return 1;
        }

printf("\nInhoud van A =  %i", aantalvar1);
printf("\nInhoud van B =  %i\n\n", aantalvar2);

aantalvar1 = aantalvar1 + 1;
aantalvar2 = aantalvar2 + 1;
aantalvar1 en aantalvar2
int var1[aantalvar1];
int var2[aantalvar2];
int i;
 
 printf("Voer nu %i keer een variabele voor A in:\n",  (aantalvar1 - 1));
 for(i = 0; i < (aantalvar1 - 1); i++)
   {
     scanf("%i", &var1[i]);
       if(var1[i] > 9)
              {
                            printf("Deze variabele mag maar 1 integer bevatten");
                            return(1);
              } 
   }
 
 printf("Voer nu %i keer een variabele voor B in:\n",  (aantalvar2 - 1));
       
 for(i = 0; i < (aantalvar2 - 1); i++)
  {
    scanf("%i", &var2[i]);
     if(var2[i] > 9)
              {
                             printf("Deze variabele mag maar 1 integer bevatten");
                            return(1);
              } 
     }  
printf("%i", var1[i]);
i = 0;
printf("\n\n\n");

while(i < (aantalvar1 - 1) )
    {
        printf("A[%i]\t=\t%i\t\n",(i + 1),var1[i]);
     i++;
     }
i = 0;
printf("\n");
while(i < (aantalvar2 - 1) )
    {
        printf("B[%i]\t=\t%i\n",(i + 1),var2[i]);
     i++;
     }
    

int hit[aantalvar1];
i = 1;
int ii = 0;

while(i < aantalvar1)
    {
        while(ii < aantalvar2)
                {
                    if(var1[i] == var2[ii])
                    {
                        hit[i] = 1;
                    }    
                ii++;
                }
     ii = 0;
     i++;                   
                                    
    }
  
for(i=1; i < aantalvar1; i++);
{
if (hit[i] = 1)
    {
        printf("%d", var1[i]);
}         
}      
}

En dan gaat het me eigenlijk vooral om het gedeelte na " int hit[aantalvar1];". Het deel ervoor werkt namelijk gewoon goed. Hij print namelijk niets (goeds) neer.

P.s. let niet op de 'nette' code. O-)

Verwijderd

Topicstarter
Nu heb ik het onder linux geprobeerd en daar krijg ik een segmentation fault.
Nu heb ik dus wat geprobeerd en het ligt aan het laatste stukje code...

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
int hit[aantalvar1];
i = 1;
int ii = 0;

while(i < aantalvar1)
    {
        while(ii < aantalvar2)
                {
                    if(var1[i] == var2[ii])
                    {
                        hit[i] = 1;
                    }    
                ii++;
                }
     ii = 0;
     i++;                   
                                    
    }
  
for(i=1; i < aantalvar1; i++);
{
if (hit[i] = 1)
    {
        printf("%d", var1[i]);
}         
}      
}

Dit is de boosdoener, maar ik kan er geen enkele fout inzien.
Als mij iemand de goede richting in zou willen sturen... :O

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 13:55
Als je onder Linux werkt, compileer dan eens met -g (dus bv. gcc -g -o test test.c) en start 'm dan eens onder de GNU debugger (bv. met gdb test en dan run typen). Als het goed is krijg je dan ook een segfault en laat de debugger de regel zien inclusief de preciese expressie waar het fout gaat.

Verwijderd

Topicstarter
Aangezien ik nooit met gdb werk (en vanaf nu ga ik me erin verdiepen) heb ik iets gevonden, waarmee hij ophield

code:
1
2
3
4
B[4]    =       3

Program exited with code 0170.
(gdb)

Die B[4] = 3 is de laatste regel...dan komt hij met de fout.

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 13:55
Er is geen fout; je programma wordt gewoon uitgevoerd (die "B[4] = 3" print je zelf immers) en daarna sluit je programma af.

Die code 0170 komt doordat je geen return statement in main() hebt staan. Je krijgt dan een min of meer willekeurige return value. Een "return 0;" op de een na laatste regel zou dat moeten verhelpen.

Maar blijkbaar crasht je programma niet. Misschien dat je andere invoer kunt proberen?

Verwijderd

Topicstarter
andere invoer heb ik al gedaan

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
while(i < aantalvar1)
    {
        while(ii < aantalvar2)
                {
                    if(var1[i] == var2[ii])
                    {
                       aap[i] = 1;
                    }
                ii++;
     ii = 0;
     i++;

}return 0;                }

het is nu dit. Het ligt aan dit stuk, want als ik die eruit gooi, doet het programma het wel (krijg alleen rare uitvoer..maar dat is al meer als niets 8))

Maar met deze return 0; is niet de oplossing denk ik

Verwijderd

Verwijderd schreef op 24 september 2004 @ 18:35:
Aangezien ik nooit met gdb werk (en vanaf nu ga ik me erin verdiepen)
Voordat je jezelf volledig op gdb stort zou ik ook nog even naar KDevelop kijken. Kost niets en debugt super. Je hebt alleen X nodig.

Verwijderd

Ik zie nog wel een foutje in je code (al zat die niet tot de segfout leiden, tenzij aantalvar = 1), namelijk je initialisatie:

C:
1
int i = 1;


Je bedoelt natuurlijk te beginnen indexeren bij 0. Verder is een for loop "veul hendiger".

Een brute-force algoritme (loopt dus in kwadratische tijd) om te zien of twee arrays een waarde delen kan er zo uitzien:

C:
1
2
3
4
5
6
7
8
9
10
int len1 = ...;
int len2 = ...;
int arr1[len1] = ...;
int arr2[len2] = ...;

for (int i = 0; i < len1; i++) {
  for (int j = 0; j < len2; j++) {
    if (arr1[i] ==  arr2[j]) printf("%d komt in arr1 voor op positie %d en in arr2 op positie %d\n", arr[i], i, j);    
  }
}


Dit is dus erg naïef, en voor grote arrays moet je slimmere algoritmes gaan gebruiken (zoals ze eerst sorteren, zoals Soultaker heeft aangedragen). Het kan allemaal best eenvoudig dus.

[ Voor 17% gewijzigd door Verwijderd op 24-09-2004 21:44 ]


Verwijderd

Topicstarter
Bedankt voor de tips allemaal. Heb het nu op kunnen lossen.
www.mo-corp.nl/c/wis2.c.html
Hier staat de bron code voor de nieuwsgierige.
Nu wil ik graag nog de code opschonen van fouten en onzuiverheden. Als iemand iets tegen komt, laat het me weten... :z

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 13:55
Ik denk dat de code een stuk leesbaarder zou zijn als je 'm fatsoenlijk zou inspringen; je kunt dan beter zien hoe lusjes en if-statements in elkaar steken. Er zijn verschillende manieren omdat dat te doen en welke je kiest maakt niet heel veel uit (het is een beetje een religieuze kwestie) zolang je de gekozen methode tenminste consistent door voert. Ik snap bijvoorbeeld niet hoe je de laatste paar regels van je programma kan begrijpen; ik kan het tenminste niet zonder ze opnieuw te formatteren en ik ben toch een ervaren C-programmeur.

Een gangbare keuze is: accolades ( { en } ) staan altijd alleen op een legel regel. Alle tekst tussen een paar accolades wordt extra ingesprongen. Er zijn verder varianten waarbij er wel code voor de openende accolade mag staan op een lege regel wordt geplaatst (zoals OneOfBorg bijvoorbeeld doet) waarmee ruimte bespaard wordt. Er loopt hier ook iemand rond die de accolades zelf ook al inspringt.

Verder zou je wel wat zinnigere namen voor je variabelen kunnen kiezen. Daarmee kun je je code veel begrijpelijker maken (en dan hoef je weer minder commentaar toe te voegen). Namen als 'aap' en 'aap1' slaan nergens op. 'var1' en 'var2' ook niet trouwens; natuurlijk zijn het variabelen. Als je echt niets beters weet, noem ze dan tenminste array1 en array2 ofzo.

Tenslotte gebruik je een aantal constructies die ongeldig zijn in C. Je gebruikt waarschijnlijk een vergevende C++ compiler die ze wel pikt, maar dat soort constructies gebruiken is vragen om moeilijkheden.
• In C kun je geen commentaarregel beginnen met //. Commentaar moet tussen /* en */ staan.
• In C moeten alle variabele-declaraties bovenaan de scope (dus direct na een openende accolade: { ) staan. Je moet dus ofwel meer scopes introduceren of als je variabele-declaraties naar bovenin je main() functie verplaatsen.
• In C (en ik dacht ook C++) is het niet toegestaan om de grootte van een array met een variabele te intialiseren; je gebruikt zo'n constructie:
C:
1
2
3
4
5
6
7
int lengte;

scanf("%d", &lengte);

{
    int array[lengte]; /* MAG NIET! */
}

Je moet een constante (in C++) of zelfs een letterlijke waarde (in C; bijvoorbeeld '10' of een definitie zoals jouw BUFFER die naar een letterlijke waarde omgezet wordt) gebruiken. Als je echt een dynamische lengte wil hebben, moet je de array dynamisch alloceren.

[ Voor 3% gewijzigd door Soultaker op 25-09-2004 17:27 ]

Pagina: 1