[C++] Array omkeren

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

  • Chip.
  • Registratie: Mei 2006
  • Niet online
Hallo,

Ik heb een prog. gemaakt dat wanneer je een woord intypt de functie het woord omkeert... Maar ik krijg nu de error:
arrayomkeren.cpp(41) : error C2664: 'woordOmkering' : cannot convert para
meter 1 from 'char' to 'char []'
Conversion from integral type to pointer type requires reinterpret_cast,
C-style cast or function-style cast

Nu is mijn vraag of iemand me kan helpen met het oplossen van de error hierboven...
C++:
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
int lengte(const char x[])
{
    for(int i = 0; x[i] != '\0'; i++)
    {
        return i;
    }
}

void woordOmkering(char x[], const char y[])
{
    char kopie;
    int i, j;

    j = lengte(y);
    
    for(i = 0, j = j - 1; i < j; i++, j--)
    {
        kopie = y[i];
        x[i] = y[j];
        x[j] = kopie;
    }
}

int main()
{   
    char woord[40], omgekeerdWoord[40];

    cout << "Typ een woord in: ";
    cin.getline(woord, 40, '\n');

    woordOmkering(omgekeerdWoord[40], woord[40]);

    cout << "Het orginele woord: " << woord;
    cout << "Het omgekeerde woord: " << omgekeerdWoord;
    
    return 0;
}

  • Harm
  • Registratie: Mei 2002
  • Niet online
Die functie woordOmerking geeft void terug, dus niets. Moet die niet wat teruggeven?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 07:20

.oisyn

Moderator Devschuur®

Demotivational Speaker

Wat verwacht je dan dat 'omgekeerdWoord[40]' doet? Blijkbaar snap je dat wel, aangezien je het ook in de functie woordOmkering toepast (x[i] = y[j]).

Daarnaast klopt je code niet, length() zal altijd 0 teruggeven, tenzij de string lengte 0 heeft, want dan kan ie alles teruggeven (die functie is trouwens ill-formed omdat niet alle paden een return statement hebben)

@Harm: wat moet ie teruggeven dan? Of het gelukt is oid? void lijkt mee prima returntype hier.

[ Voor 56% gewijzigd door .oisyn op 13-05-2007 17:55 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • CodeCaster
  • Registratie: Juni 2003
  • Niet online

CodeCaster

Can I get uhm...

Je bent wel lekker omslachtig bezig.

code:
1
2
3
for (i = 0; i <length(in); i++) {
 out[length(in)-i] = in[i];
}

Werkt toch veel sneller?

https://oneerlijkewoz.nl
Op papier is hij aan het tekenen, maar in de praktijk...


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 07:20

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ik hoop dat je een grapje maakt, CodeCaster. (Op voorwaarde dat length() aangepast wordt zodat die doet wat ie geacht wordt te doen.)

[ Voor 50% gewijzigd door .oisyn op 13-05-2007 17:53 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Harm
  • Registratie: Mei 2002
  • Niet online
.oisyn schreef op zondag 13 mei 2007 @ 17:49:
@Harm: wat moet ie teruggeven dan? Of het gelukt is oid? void lijkt mee prima returntype hier.
Is inderdaad niet nodig, ik zat me namelijk af te vragen hoe die omgekeerdWoord dan aan zijn waarde kwam, maar dat zie ik nu :) .

  • Chip.
  • Registratie: Mei 2006
  • Niet online
Sorry ik begrijp het eigenlijk nog steeds niet echt...

datgene wat je zei van x[i] = y[j] had ik toevallig bij een andere pagina gevonden :$...

  • alushin
  • Registratie: Augustus 2003
  • Laatst online: 07-08 19:51
Wouser schreef op zondag 13 mei 2007 @ 17:41:
C++:
1
2
3
4
5
6
7
8
9
10
int lengte(const char x[])
{
/*  for(int i = 0; x[i] != '\0'; i++)
    {
        return i; // return stopt je deelproces en is altijd 0 omdat de 1e waarde niet \0 is
    }*/

    for(int i = 0; x[i] != '\0'; i++); //nu wordt i alleen opgehoogd tot x[i] \0 is
    return i+1; // "na" de for loop. je begint bij 0 dus de lengte is +1
}
Je char "kopie" moet een pointer zijn (char *kopie; en dan aanroepen als *kopie, aanroepen als kopie wordt het adres)

Volgende keer je school opdracht zelf oplossen ;) (beetje overhaast gedaan weet niet of er verder nog iets fout is)

  • DataGhost
  • Registratie: Augustus 2003
  • Laatst online: 01-12 16:28

DataGhost

iPL dev

Lees ook je foutmelding even. Wilde gok:
C++:
1
 woordOmkering(omgekeerdWoord[40], woord[40]);

is regel 41? Verander die eens in
C++:
1
 woordOmkering(omgekeerdWoord, woord);

en kijk wat er gebeurt. Probeer het daarna te begrijpen.

Verder zit er volgens mij nog een fout in je woordOmkering functie, als ik het zo even vlug zie krijg je denk ik de laatste helft van de originele array, 1x normaal en 1x gespiegeld terug in je array.
of toch niet. De variabelenamen zijn niet erg duidelijk gekozen, leest een beetje lastig. Wellicht klopt het toch. Echter, de manier die je nu gebruikt vereist in princiepe geen tweede array.

edit2: en inderdaad is je lengte functie ook fout.

[ Voor 49% gewijzigd door DataGhost op 13-05-2007 18:36 ]


  • Chip.
  • Registratie: Mei 2006
  • Niet online
Dat wat je zei Dataghost werkt :) bedankt...

En dat van die lengte functie dat die fout was, had ik zelf al verbeterd, maar, excuses daarvoor, niet gepost.

Verwijderd

CodeCaster schreef op zondag 13 mei 2007 @ 17:50:
...
code:
1
2
3
for (i = 0; i <length(in); i++) {
 out[length(in)-i] = in[i];
}

...
Naast wat .oisyn schreef, is er nog wel meer op aan te merken. Hints:

Probleem #1 vind je door te testen met een string ter lengte 0.
Probleem #2 vind je door te testen met een string ter lengte 1.

  • CodeCaster
  • Registratie: Juni 2003
  • Niet online

CodeCaster

Can I get uhm...

Het was ook maar een rudimentair stukje psuedo-code. Niets om je een buil aan te vallen.

https://oneerlijkewoz.nl
Op papier is hij aan het tekenen, maar in de praktijk...


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 07:20

.oisyn

Moderator Devschuur®

Demotivational Speaker

Wouser schreef op zondag 13 mei 2007 @ 18:22:
Sorry ik begrijp het eigenlijk nog steeds niet echt...

datgene wat je zei van x[i] = y[j] had ik toevallig bij een andere pagina gevonden :$...
Misschien moet je dan maar gewoon eens bij het begin beginnen ipv code bij elkaar rapen en ons vragen het maar op te lossen. Koop een goed boek oid, en op het internet zijn ook zat goeie tutorials te vinden :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 07:20

.oisyn

Moderator Devschuur®

Demotivational Speaker

CodeCaster schreef op zondag 13 mei 2007 @ 19:27:
Het was ook maar een rudimentair stukje psuedo-code. Niets om je een buil aan te vallen.
Tja, als je wilt gaan bitneuken voor performance dan moet je het ook goed opschrijven :). Jouw functie is namelijk helemaal niet sneller - jij doet N iteraties 1 operatie, terwijl de topicstarter N/2 iteraties 2 operaties doet. Net zoveel dus. Echter, wat jouw implementatie gigantisch veel trager maakt dan die van de topicstarter is de aanroep naar length(), 2x per iteratie, wat al een O(N) operatie op zich is. Dat maakt jouw implementatie O(N2), itt de O(N) implementatie van de topicstarter.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Heren, was even bezig met de uitwerking. Maar heb ook wat aangecode. In C wel te verstaan aangezien Wouser alleen van de C++ console objects gebruik maakt. Ik heb de alternatieven (stdio) van C gebruikt.

Tis een beetje groter geworden dan gedacht :)
Ik heb me vooral gericht op correctheid van het algoritme, uitbreidbaarheid, elegantie en andere zaken waar docenten in mijn optiek niet per definitie naar kijken.
Ook staan er commentaar bij om novice programmeurs te begeleiden in het lezen van de code.
Pointers zijn:
- check je input (van al je programma's).
- probeer herbruikbare functies, objecten te schrijven.
- geef variabelen herkenbare namen.

De kern van het programma kan je in de volgende Ruby regel samenvatten ;)
code:
1
puts gets.reverse

Voor mensen die (om wat voor reden dan ook) niet in een modernere prog-taal werken is dit een leuk stukje referentie code.

Vragen en/of opmerkingen zijn welkom.
C:
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
108
109
110
111
112
113
114
115
116
117
#include <stdio.h>

// Some handy types
typedef unsigned char uchar;
typedef unsigned short ushort;

// Max word length
#define WOORDLEN 40

// Word buffers
// Keeps related stuff together
struct def_woordBuffer{
    uchar letters[WOORDLEN];
    ushort letLength;
    ushort letMax;
};
typedef struct def_woordBuffer WOORDBUF;

// Init buffer structure
void initBuffer(WOORDBUF *newBuffer){
    newBuffer->letters[0] = '\0';
    newBuffer->letLength = 0;
    newBuffer->letMax = WOORDLEN;
}

// Get a word from standard input and
// store it in the buffer structure.
void verkrijgWoord(WOORDBUF *wrdBuffer){
    char readChar;
    short maxChars;

    maxChars = (wrdBuffer->letMax - 1);
    while(wrdBuffer->letLength < maxChars){ // Reserve 1 byte for the null terminator
        readChar = getchar();
        // Input checking, only store printable ascii values.
        // New line (\n) signals end of input
        if(readChar == '\n'){
            break;
        }else if(readChar > 32 && readChar < 126){
            wrdBuffer->letters[wrdBuffer->letLength] = readChar;
            wrdBuffer->letLength++;
        }else{
            printf(
                "Not a valid word-character: '%c' (ascii value %d)\nI'm ignoring it.\n",
                readChar,
                readChar
            );
        }
    }
    // Append Null terminator
    wrdBuffer->letters[wrdBuffer->letLength] = '\0';
}

// Reverses the characters in a word buffer.
// The reverse is done in-place.
void woordOmkeer(WOORDBUF *wrdBuffer){
    short idxLow,idxHigh;
    char tmpChar;

    idxLow = 0;
    idxHigh = (wrdBuffer->letLength - 1);

    while(idxLow < idxHigh){ // sounds logical :)
        // Now switch lower and higher

        // save lower char
        tmpChar = wrdBuffer->letters[idxLow];
        
        // copy the higher idx's char to the lower idx
        // (Lower char is lost if we wouldn't save it)
        wrdBuffer->letters[idxLow] = wrdBuffer->letters[idxHigh];

        // copy the old lower char to the higher idx
        wrdBuffer->letters[idxHigh] = tmpChar;

        idxLow++;
        idxHigh--;
    }
}

// Main application flow.
// Purpose:
// - read input line from standard input
// - reverse input
// - print out the reversed input
int main(int argc,char* argv[]){
    // Structure and initialize memory
    WOORDBUF woord;
    WOORDBUF omgekeerdWoord;

    initBuffer(&woord);

    // Get input
    printf(
        "Typ een woord in (maximaal %d letters):\n\t",
        woord.letMax
    );
    verkrijgWoord(&woord);
    printf(
        "Het orginele woord:\t'%s'\n",
        woord.letters
    );

    // Make a copy of input
    omgekeerdWoord = woord;

    // Reverse word
    woordOmkeer(&omgekeerdWoord);

    // Print result
    printf(
        "Het omgekeerde woord:\t'%s'\n",
        omgekeerdWoord.letters
    );

    return 0; 
}


Compiled zonder warnings/errors met de PellesC compiler.

offtopic:
Owja, huiswerk voor anderen maken is natuurlijk niet een standaard onderdeel van mijn dagelijkse werkzaamheden. Echter mensen motiveren/dwingen zich te verdiepen in verouderde programmeertalen voor dergelijke triviale zaken is ook niet iets waar ik mij verplicht tot voel.

Als dit echt een huiswerk opdracht is, zou ik van de docenten liever zien dat ze toekomstige programmeurs iets relevantere oefeningen laten doen.
Tegenwoordig lijkt het mij belangrijk meer aandacht te besteden aan abstractere concepten (voor de WO richting) of de meer praktische aspecten uitdiepen in een ondernemingscontext (voor de HBO richting).

Verwijderd

Is het niet een stuk handiger om een string te returnen bij je keerOm() functie?

C++:
1
2
3
4
5
6
7
8
9
10
11
12
std::string keerOm( std::string woord )
{
    std::string droow;
    int length = woord.length();
    
    for( int i=0; i<length; i++ )
    {
        droow.append( woord[length - i] );
    }
    
    return droow;
}


(niet getest btw)

Zo verandert de functie geen variabelen. Dat is nogal een bad-practice namelijk, omdat je op een gegeven moment niet meer weet welke variabelen door welke functie veranderd worden. Door de functie een waarde te laten returnen, zal in de aanroepende code een "="-teken staan, waardoor het heel makkelijk te zien is.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 07:20

.oisyn

Moderator Devschuur®

Demotivational Speaker

Maar gebruik dan meteen std::reverse() :)

C++:
1
2
3
4
5
6
std::string s("omgekeerd");
std::reverse(s.begin(), s.end());

// of met char arrays
char s2[] = "omgekeerd";
std::reverse(s2, s2 + strlen(s2));

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

.oisyn schreef op zondag 13 mei 2007 @ 22:22:
Maar gebruik dan meteen std::reverse() :)

C++:
1
2
3
4
5
6
std::string s("omgekeerd");
std::reverse(s.begin(), s.end());

// of met char arrays
char s2[] = "omgekeerd";
std::reverse(s2, s2 + strlen(s2));
Mja, ik moet m'n kennis van de STL nog wat uitbreiden. ;)

Het ging mij er meer om dat de code een stuk duidelijker wordt als je functies altijd probeert een zinvolle waarde te laten returnen. Als je dan ook de functie-naam als imperatieve stelling formuleert, zoals "keerOm", dan krijg je code die voor zichzelf spreekt:

C++:
1
2
std::string woord = "Bladie";
std::string droow = keerOm( woord );

  • Soultaker
  • Registratie: September 2000
  • Nu online
Of, als non-destructive variant:
C++:
1
2
3
inline std::string reversed(const std::string &s) {
    return std::string(s.rbegin(), s.rend());
}

Zo, en nu mag de TS verder z'n eigen huiswerk doen. ;)

[ Voor 3% gewijzigd door Soultaker op 14-05-2007 00:35 ]


Verwijderd

hmm interessant commentaar.
Ik heb ervoor gekozen om functies geen waarde terug te laten geven, zodat deze standaard faciliteit overblijft om status codes mee aan te kunnen geven mocht dat nodig zijn. In andere programeertalen is dit niet van belang omdat daar gedegen manieren zijn om exceptions te genereren en af te vangen. Zelfs in C++ schijnt dit mogelijk te zijn, in C is dit (voor zover bij mij bekend) standaard niet mogelijk/gemakkelijk/generiek.

Ook is het verwarrend als ik een string aanmaak in de verkrijgWoord functie (met malloc bijvoorbeeld) en deze return. De bovenliggende functie zal dan zelf na moeten gaan welke buffers de geretourneerde waarde in beslag heeft genomen en deze dan op eigen houtje vrij geven wanneer het programma die geheugen locaties niet meer nodig heeft. Dit is niet gemakkelijk/intuitief en daarom sluipt er in grotere/complexere programma's op deze manier snel een memory leak.
Ik heb ervoor gekozen het aanmaken en vrijmaken op hetzelfde niveau in de functieaanroep hierarchie te plaatsen. Daarnaast maak ik gebruik van de stack om geheugen te alloceren, dit zorgt ervoor dat de compiler het aanmaken en vrijmaken voor z'n rekening neemt.

In een moderne taal is dit wederom beter afgevangen door een garbage collector en/of degelijke constructors en destructors.

Door variabelen/structs mee te geven en ze aan te passen probeer ik een meer objectgeorienteerd gevoel aan de code te geven.
In mijn ervaring lijkt een zooi functies (welke het gedrag van een object beschrijven) gecombineerd met een struct (welke de status van je object bewaard tussen methode aanroepen door) het meest op een class in talen als C. Dit levert een aantal OO voordelen op, welke voor mij het code kloppen simpler maken waardoor ik mij meer op het oplossen van het probleem kan storten dan memory leaks te pluggen etc.

Komt er dus ongeveer op neer dat ik me in een aantal bochten heb gewrongen om OO voordelen in C te krijgen :) |:(
Aan de andere kant is het alleen in C nodig om zo'n triviale functie uit te programmeren, de meeste talen hebben idd een string object met een reverse methode eraan.

Verwijderd

Dit kwam ik tegen in Google: Exceptions in C :P

C++ ondersteunt inderdaad standaard exceptions, hoewel ik .oisyn heb zien schrijven dat het in performance-kritieke applicaties soms handig kan zijn om exception-support uit te schakelen.

Verwijderd

Je hoeft in principe enkel een functie te maken die omgekeerd print. Dus van loopen van achter naar voor en je characters naar buiten gooien :)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 07:20

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op maandag 14 mei 2007 @ 00:40:
Komt er dus ongeveer op neer dat ik me in een aantal bochten heb gewrongen om OO voordelen in C te krijgen :) |:(
Of je komt onder die rots vandaan en je gaat gewoon C++ gebruiken :P ;)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
.oisyn schreef op maandag 14 mei 2007 @ 12:46:
[...]


Of je komt onder die rots vandaan en je gaat gewoon C++ gebruiken :P ;)
Moet je natuurlijk wel voor een platform programeren waar een fatsoenlijke c++ compiler voor is ;)

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 07:20

.oisyn

Moderator Devschuur®

Demotivational Speaker

Nee hoor. www.comeaucomputing.com. Fully standard C++03 compliant compiler die C++ code naar C code compileert :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Ja hoor, was ik weer eens net te laat :)

Je kunt het hier lezen.
Pagina: 1