Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

01.04.2009, 18:55

[C++] Konsole als Konfigurationsdialog - Problem mit fscanf

Moin Moin

Ich hab für mein Spiel eine kleine Auswahlsfunktion für Grafiktreiber, Auflösung und Volbildmodus (->Irrlicht) geschrieben. Es fragt nur die Daten ab oder liest sie, wenn möglich, aus einer Datei. Dabei verwende ich eine Variable

C-/C++-Quelltext

1
char i;

Im Debug-Modus erhalte ich einen Fehler, von wegen "stack around the variable was corrupted":


(Link)


Hier mein Code:

C-/C++-Quelltext

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
// ConfigData ist eine Struktur, die Variablen zum Speichern von 

// Treiber, Auflösung und Vollbildmodus bietet

// & ConfigManager ist eine Klasse zum verwalten der Abfrage

ConfigData ConfigManager::Get()
{
    char i = ' ';
    FILE *pFile;

    if((pFile = fopen("config.icf","r"))==NULL)
    {
        printf("Bitte waehlen sie einen Treiber aus:\n"\
        " (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
        " (d) Software Renderer\n (e) Burning's Software Renderer\n"\
        " (f) Keinen\n (andere Taste) Ende\n\n");

    
    std::cin >> i;

    switch(i)
    {
        case 'a': config.driverType = video::EDT_DIRECT3D9;break;
        case 'b': config.driverType = video::EDT_DIRECT3D8;break;
        case 'c': config.driverType = video::EDT_OPENGL;   break;
        case 'd': config.driverType = video::EDT_SOFTWARE; break;
        case 'e': config.driverType = video::EDT_BURNINGSVIDEO;break;
        case 'f': config.driverType = video::EDT_NULL;     break;
    }   

    printf("\nBitte waehlen sie ein Aufloesung:\n"\
        " (1) 640x480\n (2) 800x600\n (3) 1024x768\n"\
        " (4) 1280x1024\n (5) 1600x1200\n"\
        "\n");

    
    std::cin >> i;
    resolution = (int)i;

    switch(resolution)
    {
        case '1': config.resolution = core::dimension2d<s32>(640,480);   break;
        case '2': config.resolution = core::dimension2d<s32>(800,600);   break;
        case '3': config.resolution = core::dimension2d<s32>(1024,768);  break;
        case '4': config.resolution = core::dimension2d<s32>(1280,1024); break;
        case '5': config.resolution = core::dimension2d<s32>(1600,1200); break;
    }   

    printf("\nVollbildmodus? (y/n)\n\n");   
    std::cin >> i;
    if(i == 'y')fullscreen = true;
    else fullscreen = false;
    }
    else
    {
        fscanf(pFile,"%s",&i);
        switch(i)
    {
        case 'a': config.driverType = video::EDT_DIRECT3D9;break;
        case 'b': config.driverType = video::EDT_DIRECT3D8;break;
        case 'c': config.driverType = video::EDT_OPENGL;   break;
        case 'd': config.driverType = video::EDT_SOFTWARE; break;
        case 'e': config.driverType = video::EDT_BURNINGSVIDEO;break;
        case 'f': config.driverType = video::EDT_NULL;     break;
    }   
        fscanf(pFile,"%i",&resolution);
        switch(resolution)
    {
        case '1': config.resolution = core::dimension2d<s32>(640,480);   break;
        case '2': config.resolution = core::dimension2d<s32>(800,600);   break;
        case '3': config.resolution = core::dimension2d<s32>(1024,768);  break;
        case '4': config.resolution = core::dimension2d<s32>(1280,1024); break;
        case '5': config.resolution = core::dimension2d<s32>(1600,1200); break;
    }   
        fscanf(pFile,"%s",&i);
        if(i == 'y') fullscreen = true;
        else fullscreen = false;
        fclose(pFile);
    }
    
    config.Fullscreen = fullscreen;
    #ifdef _DEBUG
    config.Fullscreen = false; // zu Debug Zwecken

    #endif
    return config;
}


Liegt es an fscanf?
Weiß jemand warum der Fehler auftritt?
Im Debug-Modus kann man ihn noch "wegklicken", bei Release hängt sich das Programm auf.

Schon mal Danke im Voraus,

mfg DoubleM

[Edit:] Das Bild ist jetzt auch da ;)
[Edit 2:] Im Debug-Modus meldet er den Fehler erst am Ende der Methode, bei der geschweiften Klammer, und das kann ja irgendwie nicht sein *am Hinterkopf kratz*

2

01.04.2009, 19:03

Versuchs mal ohne das kaufmännische Und (&) bei fscanf.
Zumindest bei char.
fka tm

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

3

01.04.2009, 19:25

Mein Tipp: nutz den irrlicht xmlwriter/reader oder nimm fstream. Weil da kannst du einfach >> bzw << nutzen.
Zum Problem: %c und ohne & ist für einzelne char. Oder du nutzt ein char i[10] o.ä.
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

4

01.04.2009, 19:26

Oh, verlesen :roll:

5

01.04.2009, 19:29

Ja, ein bisschen blöd formuliert. :?

So

C-/C++-Quelltext

1
fscanf(pFile,"%c", i);


Und ich schließe mich Nox' Vorschlägen an. ;)
fka tm

6

01.04.2009, 19:32

Nee, ohne & funktioniert es nicht, anfangs wollte ich es auch weglassen, nur zu Laufzeit hat er sich dann ziemlich verheddert.
Und bei %c kommt eine Speicherzugriffsverletzung.

Werde ich es wohl mit etwas anderem versuchen (fstream...)

trotzdem danke, leute

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

7

01.04.2009, 19:41

C-/C++-Quelltext

1
fscanf(pFile,"%s",&i);


TrikkieMikkie hat das Problem schon richtig lokalisiert. Allerdings liegts net an dem &. Du liest hier nen string in einen char ein. Das geht natürlich nicht (außer der string ist leer). Entweder %c verwenden (wenn du eigentlich nur ein zeichen lesen wolltest) oder richtig mit buffer usw. (dann könntest du aber auch gleich fgets() verwenden statt fscanf()) oder statt dem C Kram C++ string und streams verwenden...

8

01.04.2009, 20:17

So, jetzt funktionierts(mit fstream) und auch im Release-Modus.
Hier zu vollständigkeit nochmal den Code:

C-/C++-Quelltext

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
ConfigData ConfigManager::Get()
{
    char i = ' ';
    fstream pFile;

    
        pFile.open("config.icf",ios_base::in);
        if(pFile.is_open())
        {
        pFile >> i;
        switch(i)
    {
        case 'a': config.driverType = video::EDT_DIRECT3D9;break;
        case 'b': config.driverType = video::EDT_DIRECT3D8;break;
        case 'c': config.driverType = video::EDT_OPENGL;   break;
        case 'd': config.driverType = video::EDT_SOFTWARE; break;
        case 'e': config.driverType = video::EDT_BURNINGSVIDEO;break;
        case 'f': config.driverType = video::EDT_NULL;     break;
    }   
        i = ' ';
        pFile >> i;
        switch(i)
    {
        case '1': config.resolution = core::dimension2d<s32>(640,480);   break;
        case '2': config.resolution = core::dimension2d<s32>(800,600);   break;
        case '3': config.resolution = core::dimension2d<s32>(1024,768);  break;
        case '4': config.resolution = core::dimension2d<s32>(1280,1024); break;
        case '5': config.resolution = core::dimension2d<s32>(1600,1200); break;
    }   
        i = ' ';
        pFile >> i;
        if(i == 'y') fullscreen = true;
        else fullscreen = false;
        pFile.close();
    }
        else
    {
        printf("Bitte waehlen sie einen Treiber aus:\n"\
        " (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
        " (d) Software Renderer\n (e) Burning's Software Renderer\n"\
        " (f) Keinen\n (andere Taste) Ende\n\n");

    
    std::cin >> i;

    switch(i)
    {
        case 'a': config.driverType = video::EDT_DIRECT3D9;break;
        case 'b': config.driverType = video::EDT_DIRECT3D8;break;
        case 'c': config.driverType = video::EDT_OPENGL;   break;
        case 'd': config.driverType = video::EDT_SOFTWARE; break;
        case 'e': config.driverType = video::EDT_BURNINGSVIDEO;break;
        case 'f': config.driverType = video::EDT_NULL;     break;
    }   

    printf("\nBitte waehlen sie ein Aufloesung:\n"\
        " (1) 640x480\n (2) 800x600\n (3) 1024x768\n"\
        " (4) 1280x1024\n (5) 1600x1200\n"\
        "\n");

    
    std::cin >> i;
    

    switch(i)
    {
        case '1': config.resolution = core::dimension2d<s32>(640,480);   break;
        case '2': config.resolution = core::dimension2d<s32>(800,600);   break;
        case '3': config.resolution = core::dimension2d<s32>(1024,768);  break;
        case '4': config.resolution = core::dimension2d<s32>(1280,1024); break;
        case '5': config.resolution = core::dimension2d<s32>(1600,1200); break;
    }   

    printf("\nVollbildmodus? (y/n)\n\n");   
    std::cin >> i;
    if(i == 'y')fullscreen = true;
    else fullscreen = false;
    }
    
    
    config.Fullscreen = fullscreen;
    #ifdef _DEBUG
    config.Fullscreen = false; // zu Debug Zwecken

    #endif
    return config;
}


Das, was am meisten ärgerlich war, war, dass es anfangs nicht funktioniert hatte, weil die Speicher-Funktion mit fstream fehlerhaft war :? (Toller Satz :lol: )

9

01.04.2009, 20:31

Eine merkwürdige Einrückung hast du... ;)

Willst du nicht gleich ganz von den C-Funktionen wegkommen, für die es entsprechend bessere Alternativen in C++ gibt? Oder welchen Grund hast du, dass du printf() statt std::cout verwendest?

Ausserdem brauchst du Variablen nicht zu "leeren", bevor du sie neu beschreibst. Stattdessen solltest du lieber eine Gültigkeitsprüfung einbauen...

10

01.04.2009, 20:54

Zitat von »"Nexus"«

Eine merkwürdige Einrückung hast du... ;)


Ja, das stimmt :D

Zitat von »"Nexus"«


Ausserdem brauchst du Variablen nicht zu "leeren", bevor du sie neu beschreibst. Stattdessen solltest du lieber eine Gültigkeitsprüfung einbauen...


Ist ein Überbleibsel davon, dass er immer "verhunzte" Variablen geladen hat. Um alle Fälle auszuschließen hatte ich diese Variablenleerung hingeschrieben, mitlerweile weiß ich, dass die Variablen beim Speichern "verhunzt" wurden.

Werbeanzeige