[C++] één element in char array aanpassen

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Dinnesch
  • Registratie: September 2009
  • Laatst online: 22-08 11:01
Ik moet van een programmeerboek dat ik gebruik om C++ te leren(Deitel C++ how to program) een recursieve functie mazeTraverse schrijven om door een doolhof heen te werken. Dit doolhof staat in de vorm van een 12x12 char array.
De functie moet met een "*" aangeven waar het zich in het moment bevindt, alleen ik kom er niet uit hoe ik de functie slechts één karakter uit de array aan laat passen. Het is eigenlijk een tweedimensionale array, maar bijvoorbeeld
C++:
1
 maze[xpos][ypos] = "*";
werkt niet omdat de tweede dimensie met een pointer gemaakt wordt(niet zeker hoe je dit noemt). Dit:
C++:
1
 maze[ypos] = "*";
werkt bijvoorbeeld wel, alleen wordt de dan de hele reeks overschreven en niet één van de karakters.

Weet iemand dus hoe je wel één element in zo'n array aan kunt passen? Hopelijk is de vraagstelling zo een beetje duidelijk.
Hieronder is mijn (nog niet complete) code, de relevante functie begint op regel 36.
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
#include "stdafx.h"
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <Windows.h>


using namespace std;

void mazeTraverse(char* maze[12], int mazeSize, int start, int xpos, int ypos);


int _tmain(int argc, _TCHAR* argv[])
{
    const int mazeSize = 12;
    char * maze[mazeSize] = {
        "############", 
        "#...#......#",
        "..#.#.####.#",
        "###.#....#.#",
        "#....###.#..",
        "####.#.#.#.#",
        "#..#.#.#.#.#",
        "##.#.#.#.#.#",
        "#........#.#",
        "######.###.#",
        "#......#...#",
        "############"
    };

    mazeTraverse(maze,mazeSize,0,0,3);

    return 0;
}

void mazeTraverse(char* maze[12], int mazeSize, int start,int xpos, int ypos)
{
    maze[ypos] = "*"; //Dit overschrijft dus de hele x-as van de char array :(

    for(int i = 0; i < mazeSize; i++)
        cout << maze[i] << endl;

    Sleep(2000);    
}

Acties:
  • 0 Henk 'm!

  • WVL_KsZeN
  • Registratie: Oktober 2002
  • Laatst online: 20:48
Volgens mij gaat het mis doordat je een string in een element probeert te stoppen, terwijl het een char moet zijn.

code:
1
maze[xpos][ypos] = '*';


zou volgens mij moeten werken, dus ' gebruiken ipv "

/me heeft eindelijk ook een icoontje.. woef.. boeien..


Acties:
  • 0 Henk 'm!

  • Dinnesch
  • Registratie: September 2009
  • Laatst online: 22-08 11:01
WVL_KsZeN schreef op zondag 23 oktober 2011 @ 15:24:
Volgens mij gaat het mis doordat je een string in een element probeert te stoppen, terwijl het een char moet zijn.

code:
1
maze[xpos][ypos] = '*';


zou volgens mij moeten werken, dus ' gebruiken ipv "
Klinkt op zich logisch, maar het werkt niet. Ik krijg een oninformatieve error "Unhandled exception at 0x00241f2c in 8.exe: 0xC0000005: Access violation writing location 0x002478d3." elke keer dat ik het programma draai.
Ik heb geprobeerd het statement uit te voeren in main(waar maze ook wordt gedeclareerd) met vaste waarden( maze[0][3] = '*'; ) maar ik blijf deze error krijgen.
En het gaat boven mijn kennis waar ik hier de fout in ga omdat mijn compiler(Visual C++ 2010 Express) geen verdere waarschuwingen geeft(maze[0][3] is ten slotte in het 'bereik' van de array)

Acties:
  • 0 Henk 'm!

  • WVL_KsZeN
  • Registratie: Oktober 2002
  • Laatst online: 20:48
In je void mazetraverse vraag je in je header om maze[12], maar dat is dus maar een array van 12 chars, en geen matrix! Moet je die 12 niet weghalen en vragen om char* maze[][]?

/me heeft eindelijk ook een icoontje.. woef.. boeien..


Acties:
  • 0 Henk 'm!

  • NATStudent
  • Registratie: Augustus 2008
  • Laatst online: 14-08 13:46
WVL_KsZeN schreef op zondag 23 oktober 2011 @ 16:00:
In je void mazetraverse vraag je in je header om maze\[12], maar dat is dus maar een array van 12 chars, en geen matrix!
Nee, het is een array van char pointers.

Het vreemde is dat maze[ypos][xpos] niet werkt bij Dinnesch. De volgende code output hier namelijk keurig de inhoud van de tweede regel van het doolhof (gecompiled met g++):

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
#include <iostream>
#include <stdio.h>
#include <math.h>

using namespace std;

int main(int argc, char* argv[])
{
    const int mazeSize = 12;
    char * maze[mazeSize] = {
        "############",
        "#...#......#",
        "..#.#.####.#",
        "###.#....#.#",
        "#....###.#..",
        "####.#.#.#.#",
        "#..#.#.#.#.#",
        "##.#.#.#.#.#",
        "#........#.#",
        "######.###.#",
        "#......#...#",
        "############"
    };

    for(int xpos = 0; xpos < 12; xpos++)
        cout << maze[1][xpos];
        
    cout << '\n';
    cin.get();

    return 0;
}

Acties:
  • 0 Henk 'm!

  • Dinnesch
  • Registratie: September 2009
  • Laatst online: 22-08 11:01
WVL_KsZeN schreef op zondag 23 oktober 2011 @ 16:00:
In je void mazetraverse vraag je in je header om maze\[12], maar dat is dus maar een array van 12 chars, en geen matrix! Moet je die 12 niet weghalen en vragen om char* maze[][]?
Dat keurt mijn compiler niet goed("an array may not have elements of this type"), en van mijn eigen C++ kennis begrijp ik dat een array ook als een pointer werkt als deze naar een andere functie wordt gestuurd, echter is dit dus een soort 'dubbele pointer' waar ik echt geen raad mee weet gezien de access violation error die ik krijg.
NATStudent schreef op zondag 23 oktober 2011 @ 16:23:
[...]


Nee, het is een array van char pointers.

Het vreemde is dat maze[ypos][xpos] niet werkt bij Dinnesch. De volgende code output hier namelijk keurig de inhoud van de tweede regel van het doolhof (gecompiled met g++):

snip
Het 'lezen' van de array op deze manier lukt bij mij ook prima, echter zodra ik een element(1 karakter) probeer aan te passen krijg ik de access violation errors. Het lijkt er dus op dat de zowel mazeTraverse als _tmain niet de rechten hebben om de array te veranderen? Dit snap ik niet omdat:
- mouseTraverse een referentie krijgt naar de array
- de array niet const is

Kan iemand mij dus uitleggen wat ik verkeerd doe, ik vind werken met pointers zo ingewikkeld :9

BTW, ik werk met Visual C++ Express 2010, heb het ook in CodeBlocks+GCC geprobeerd.
De volledige code waarbij ik de access violation krijg is:

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
#include "stdafx.h"
#include <iostream>
#include <Windows.h>


using namespace std;

void mazeTraverse(char* maze[], int mazeSize, int start, int xpos, int ypos);


int _tmain(int argc, _TCHAR* argv[])
{
    const int mazeSize = 12;
    char * maze[mazeSize] = {
        "############", 
        "#...#......#",
        "..#.#.####.#",
        "###.#....#.#",
        "#....###.#..",
        "####.#.#.#.#",
        "#..#.#.#.#.#",
        "##.#.#.#.#.#",
        "#........#.#",
        "######.###.#",
        "#......#...#",
        "############"
    };

    mazeTraverse(maze,mazeSize,0,0,3);

    return 0;
}

void mazeTraverse(char* maze[], int mazeSize, int start,int xpos, int ypos)
{
    
    maze[0][3] = '*';
    for(int i = 0; i < mazeSize; i++)
        for(int j = 0; j < mazeSize; j++)
        {
            if(j == 0)
                    cout << endl;
            if(i != xpos && j != ypos)
                cout << maze[i][j];
            
                
        }

    Sleep(5000);
}

[ Voor 25% gewijzigd door Dinnesch op 23-10-2011 18:06 ]


Acties:
  • 0 Henk 'm!

  • eek
  • Registratie: Februari 2001
  • Laatst online: 06-04-2020

eek

@MagickNET

Volgens mij maakt de compiler van:
C++:
1
char* maze[mazeSize]

Het volgende:
C++:
1
const char maze[mazeSize]

En probeer je dus een constante variable aan te passen wat natuurlijk niet mag

Skill is when luck becomes a habit.


Acties:
  • 0 Henk 'm!

  • DataGhost
  • Registratie: Augustus 2003
  • Laatst online: 19-09 21:26

DataGhost

iPL dev

$ g++ -Wall -static -O2 -pipe faalgot.cpp -o faalgot
faalgot.cpp: In function 'int main(int, char**)':
faalgot.cpp:25: warning: deprecated conversion from string constant to 'char*'
<tig keer>

Let heel erg op je warnings. Bedenk je ook eens hoe je array geinitialiseerd wordt en waar precies heen wordt gewezen na initialisatie.

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
[.....]
.rodata:00000000004F1880 ; ===========================================================================
.rodata:00000000004F1880
.rodata:00000000004F1880 ; Segment type: Pure data
.rodata:00000000004F1880 ; Segment permissions: Read
.rodata:00000000004F1880 ; Segment alignment '32byte' can not be represented in assembly
.rodata:00000000004F1880 _rodata         segment para public 'CONST' use64
.rodata:00000000004F1880                 assume cs:_rodata
.rodata:00000000004F1880                 ;org 4F1880h
.rodata:00000000004F1880                 public _IO_stdin_used
.rodata:00000000004F1880 _IO_stdin_used  dd 20001h
.rodata:00000000004F1884 asc_4F1884      db '############',0     ; DATA XREF: main+4o
.rodata:00000000004F1884                                         ; main+A2o
.rodata:00000000004F1891 a_________      db '#...#......#',0     ; DATA XREF: main+1Do
.rodata:00000000004F189E a_____          db '..#.#.####.#',0     ; DATA XREF: main+28o
.rodata:00000000004F18AB a______         db '###.#....#.#',0     ; DATA XREF: main+42o
.rodata:00000000004F18B8 a_______        db '#....###.#..',0     ; DATA XREF: main+4Eo
.rodata:00000000004F18C5 a____           db '####.#.#.#.#',0     ; DATA XREF: main+5Ao
.rodata:00000000004F18D2 a_______0       db '#..#.#.#.#.#',0     ; DATA XREF: main+66o
.rodata:00000000004F18DF a______0        db '##.#.#.#.#.#',0     ; DATA XREF: main+72o
.rodata:00000000004F18EC a__________0    db '#........#.#',0     ; DATA XREF: main+7Eo
.rodata:00000000004F18F9 a__             db '######.###.#',0     ; DATA XREF: main+8Ao
.rodata:00000000004F1906 a__________1    db '#......#...#',0     ; DATA XREF: main+96o
[.....]

[ Voor 70% gewijzigd door DataGhost op 23-10-2011 21:09 . Reden: nja, spoiler werkt niet met monospace :( ]


Acties:
  • 0 Henk 'm!

  • WVL_KsZeN
  • Registratie: Oktober 2002
  • Laatst online: 20:48
Ach ja.. stom :)

Je komt er denk ik wel uit als je bedenkt wat maze[xpos] precies is :)

/me heeft eindelijk ook een icoontje.. woef.. boeien..


Acties:
  • 0 Henk 'm!

  • Dinnesch
  • Registratie: September 2009
  • Laatst online: 22-08 11:01
Bedankt voor de uitleg, de inhoud van een 2-dimensionele char array kan dus alleen bij de declaratie ingesteld worden. :)
Ik maak de opdracht verder wel met if-statements om te bepalen of het element in de array is waar de functie zich bevindt in de puzzel. Lijkt me wat verspilde cpu-cycles maar daar komt het leerboek later vast op terug.

Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 22:43
eek schreef op zondag 23 oktober 2011 @ 19:06:
Volgens mij maakt de compiler van:
C++:
1
char* maze[mazeSize]

Het volgende:
C++:
1
const char maze[mazeSize]

En probeer je dus een constante variable aan te passen wat natuurlijk niet mag
Dat is het niet. Het punt is dat string literals simpelweg in read-only geheugenlocaties gealloceerd worden (ook al hebben ze, om historische redenen, char* als type). Dat ze char* zijn betekent nog niet dat je er ook naar kunt schrijven.

Om het probleem op te lossen moet je niet een array van character pointers alloceren, maar een array van arrays van characters. Dit werkt wel:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const int mazeSize = 12;
char maze[mazeSize][mazeSize + 1] = {
        "############",
        "#...#......#",
        "..#.#.####.#",
        "###.#....#.#",
        "#....###.#..",
        "####.#.#.#.#",
        "#..#.#.#.#.#",
        "##.#.#.#.#.#",
        "#........#.#",
        "######.###.#",
        "#......#...#",
        "############"
    };

Wanneer je een character array initialiseert met een string literal, dan zorgt de compiler ervoor dat de character data naar de array gekopieerd wordt (en die is gewoon writeable). De +1 is nodig omdat zo'n string literal uit 12 karakters plus een terminating zero character bestaat.
Pagina: 1