Du bist nicht angemeldet.

Werbeanzeige

BlackViper

Frischling

  • »BlackViper« ist der Autor dieses Themas

Beiträge: 12

Wohnort: Dortmund

Beruf: InformatikStudent

  • Private Nachricht senden

1

06.08.2005, 03:05

Übungsaufgabe 2 von Unterkapitel 2.2.8

12%

Ja, die meisten sind qualvoll schwer! (2)

59%

Die meisten sind "schwer" im Sinne von.. "ich kapier's, aber ich brauch sehr lange für die Lösung" (10)

18%

Die meisten sind leicht. Nur wenige ham's in sich. (3)

12%

Nope, echt easy und leicht verständlich! (2)

Hallo Leuts,

ich sitz nun schon etwas länger an einem Problem, das mich ziemlich wurmt...

Quellcode

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
    bool status=0;
    int Cursor_pos = 0;
    char sBuffer[] = "";

    void* pBuffer = NULL;
    pBuffer = &sBuffer;
    
    // TriBase-Engine initialisieren
    tbInit();
    
    tbVFile* pFile=new tbVFile;
    do 
    { 
        if(pFile->Init("test.txt"))
        {
            tbWriteToLog("Fehler beim Lesen der Datei!");
        }
        else
        {
            int File_size = pFile->GetSize();
            tbWriteToLog("Die Datei wurde erfolgreich eingelesen. Groesse: %d Byte", File_size);
            
            //not necessarily needed
            //pFile->Seek(TB_VFSO_START,0);
            
            // read x characters from file and store into sBuffer
            // insert into sBuffer[0], sBuffer[1], ... sBuffer[x-1]
            pFile->Read(2,pBuffer);
            
            // getting size of Array doesnt work properly!
            int BufferGroesse = strlen(sBuffer);
            tbWriteToLog("Buffergröße: %d", BufferGroesse);
            // because array begins at 0, we have to break if k = BuffSize
            for (int k=0;k<BufferGroesse;k++)
                tbWriteToLog("Feld %d: %c", k, sBuffer[k]);
            

            status=1;
        }


Nun zeigt mir die Log-HTML, dass bei Einlesen von weniger als 4 Charakters (hier 2) die Buffergröße dennoch immer bei 4 bleibt!

Zitat

...
Buffergröße: 4
Feld 0: c
Feld 1: d
Feld 2: Ì
Feld 3: Ì
Die Datei "copy.txt" wurde erfolgreich geschrieben.
...


Das heißt, ich kann keine korrekte Grenze herausfinden, wenn ich nur 1, 2 oder 3 Zeichen einlesen will.
Die Ausgabe des Buffers trägt also immer mindestens 4 Zeichen in die Log-HTML. Natürlemont sind das 3te und 4te Zeichen nicht gelesen worden und sehen daher crappy aus ;)

Jemand ne Idee, wie man das Einlesen korrigieren kann?

Greetinx
$BlackViper$
Fürchte nicht langsam zu gehen,
fürchte nur, stehen zu bleiben.

Nox

Supermoderator

Beiträge: 5 274

Beruf: Student

  • Private Nachricht senden

2

06.08.2005, 12:14

setz malden Buffer vor dem lesen auf Null
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.

BlackViper

Frischling

  • »BlackViper« ist der Autor dieses Themas

Beiträge: 12

Wohnort: Dortmund

Beruf: InformatikStudent

  • Private Nachricht senden

3

06.08.2005, 12:25

Keine Aenderung

Haj Nox,

int BufferGroesse = 0;
hab ich hinzugefügt.
Aber letztlich bewirkt es keine Änderung.

Der Buffer behält für 2 gelesene Zeichen den Wert 4.

Gruß

BlackViper
Fürchte nicht langsam zu gehen,
fürchte nur, stehen zu bleiben.

Nox

Supermoderator

Beiträge: 5 274

Beruf: Student

  • Private Nachricht senden

4

06.08.2005, 12:36

Nein du sollst den Buffer NUllsetzen also entweder mit memset oder ZeroMemory
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.

BlackViper

Frischling

  • »BlackViper« ist der Autor dieses Themas

Beiträge: 12

Wohnort: Dortmund

Beruf: InformatikStudent

  • Private Nachricht senden

5

06.08.2005, 12:56

Immer noch nichts...

Tja, nun hab ich vor pFile->Read
noch
ZeroMemory(sBuffer,0)
gesetzt. Es ändert sich nichts.
pBuffer ist ja schon anfänglich auf Null gesetzt und bekommt die Adresse von sBuffer, der ein leeres String ist.

Ehrlich gesagt, verstehe ich nicht ganz, was das Setzen von sBuffer auf Null bezwecken soll..
Fürchte nicht langsam zu gehen,
fürchte nur, stehen zu bleiben.

Nox

Supermoderator

Beiträge: 5 274

Beruf: Student

  • Private Nachricht senden

6

06.08.2005, 14:30

Hmm Ich sehe gerade...das funzt nur wenn du eine Array selbst erstellst und dann auf Null setzt. Anscheinend erstellt aber in diesem Beispiel die Funktion Read den Speicherbereich für die Daten und setzt diesen nciht auf 0.
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.

BlackViper

Frischling

  • »BlackViper« ist der Autor dieses Themas

Beiträge: 12

Wohnort: Dortmund

Beruf: InformatikStudent

  • Private Nachricht senden

7

06.08.2005, 14:54

Dynamisches Array

Ja, das ist schon klar.. immerhin ist das ganz im Sinne des dynamischen Arrays. Damit ist aber immer noch nicht geklärt, warum beim Messen des sBuffers mittels strlen stets korrekte ArrayLängen (hier als Buffergröße ausgegeben) für mindestens 4 gelesene Characters erfolgen, nicht aber für weniger als 4.

In der Tribase-Funktion tbVFile::Read(int iNumBytes, void * pOut)

gibt es die folgende Zeile

Quellcode

1
memcpy(pOut, (BYTE*)(m_pBuffer) + m_iCursor, iNumBytes);


Könnte die für dieses magische Minimum von 4 Zeichen verantwortlich sein?

Gruß
BlackViper[/code]
Fürchte nicht langsam zu gehen,
fürchte nur, stehen zu bleiben.

Anonymous

unregistriert

8

06.08.2005, 16:33

Wenn dein Ausschnitt von oben noch aktuell ist, dann wundert es mich nicht, dass es nicht funktioniert.



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
    bool status=0;
   int Cursor_pos = 0;
   char sBuffer[] = "";  //Der Puffer ist 1Byte groß, er besteht nur aus '\0' bzw 0


   void* pBuffer = NULL; //unsinnig da du danach eh direkt nen Wert zuweist

   pBuffer = &sBuffer;  //zeigt nun auf deinen 1Byte großen Puffer

   
   // TriBase-Engine initialisieren

   tbInit();
   
   tbVFile* pFile=new tbVFile;
   do
    {
        if(pFile->Init("test.txt"))
        {
            tbWriteToLog("Fehler beim Lesen der Datei!");
        }
        else
        {
         int File_size = pFile->GetSize(); 
         tbWriteToLog("Die Datei wurde erfolgreich eingelesen. Groesse: %d Byte", File_size);
         
         //not necessarily needed

         //pFile->Seek(TB_VFSO_START,0);

         
         // read x characters from file and store into sBuffer

         // insert into sBuffer[0], sBuffer[1], ... sBuffer[x-1]

         pFile->Read(2,pBuffer); //Wie willst du 2Byte in einen 1Byte großen Buffer lesen?!

         
         // getting size of Array doesnt work properly!

         int BufferGroesse = strlen(sBuffer); //Das ist kein String sondern ein Puffer mit der größe 1

         tbWriteToLog("Buffergröße: %d", BufferGroesse);
         // because array begins at 0, we have to break if k = BuffSize

         for (int k=0;k<BufferGroesse;k++) //Das funktioniert aus dem oben genannten Grund nicht

                                           //Das einzige gültige Element ist sBuffer[0]

                                           tbWriteToLog("Feld %d: %c", k, sBuffer[k]);
         

            status=1;
        }


Ne funktionierende Variante:

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
    bool status=0;
   int Cursor_pos = 0;
   char sBuffer[ 24 ];        //Puffer mit 24Bytes platz

   void* pBuffer = reinterpret_cast< void* >( sBuffer );   //Der Zeiger auf den Puffer

   
   // TriBase-Engine initialisieren

   tbInit();
   
   tbVFile* pFile=new tbVFile;
   do
    {
        if( pFile->Init( "test.txt" ) )
        {
            tbWriteToLog( "Fehler beim Lesen der Datei!" );
        }
        else
        {
         int File_size = pFile->GetSize(); 
         tbWriteToLog( "Die Datei wurde erfolgreich eingelesen. Groesse: %d Byte", File_size );
         
         int BufferGroesse = 0; //Noch ist der Puffer leer

         
         if( pFile->Read( 2, pBuffer ) == TB_OK ) //2Bytes einlesen

            BufferGroesse = 2;                    //Nur wenn der Lesevorgang erfolgreich war die Puffergröße ändern

         tbWriteToLog("Buffergröße: %d", BufferGroesse);
         // because array begins at 0, we have to break if k = BuffSize

         for ( int k = 0; k < BufferGroesse; k++ )                                              
            tbWriteToLog("Feld %d: %c", k, sBuffer[k]);

         status=1;
        } 
        //Da ich dein Beispiel verwendet habe endet hier meine Änderung, da ich nicht weiß wie es bei dir weitergeht.

BlackViper

Frischling

  • »BlackViper« ist der Autor dieses Themas

Beiträge: 12

Wohnort: Dortmund

Beruf: InformatikStudent

  • Private Nachricht senden

9

06.08.2005, 17:22

Hehe

C-/C++-Quelltext

1
2
if( pFile->Read( 2, pBuffer ) == TB_OK ) //2Bytes einlesen

            BufferGroesse = 2;                       //Nur wenn der Lesevorgang erfolgreich war die Puffergröße ändern 


Ja, das war der entscheidende Clue. Anstatt mit strlen qualvoll eine falsche BufferGrößen zu messen, umgehen wir das Problem mit einer einfachen Zuweisung der Buffergröße, wenn das Einlesen gefunzt hat (was es ja eigentlich schon tat) :)

Tja, so sind die Log-Ausgaben jetzt auch für 1-3 chars korrekt..

Hier nochemal für's Protokoll die endgültige Fassung:

Einlesen von "set"-vielen Characters aus einer Datei und kopieren in eine neue Datei:

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
    bool status=0;
    
    const int set = 5;              // Number of Characters

    const float min_length = 0.0;   // Minimum Length of Vectors

    const float max_length = 10.0;  // Maximum Length of Vectors


    int Cursor_pos = 0;
    int Zahl = 0;
    char sBuffer[] = "";

    int BufferGroesse = 0;
    //instead of this here....

    //void* pBuffer = NULL;

    //pBuffer = &sBuffer;

    //....use casted pointer to sBuffer

    void* pBuffer = reinterpret_cast< void* >( sBuffer );
    
    // TriBase-Engine initialisieren

    tbInit();
    
    tbVFile* pFile=new tbVFile;
    do 
    { 
        if(pFile->Init("test.txt"))
        {
            tbWriteToLog("Fehler beim Lesen der Datei!");
        }
        else
        {
            int File_size = pFile->GetSize();
            tbWriteToLog("Die Datei wurde erfolgreich eingelesen. Groesse: %d Byte", File_size);
            
            //not necessarily needed

            //pFile->Seek(TB_VFSO_START,0);

            Cursor_pos = pFile->GetCursor();
            tbWriteToLog("Der Cursor steht auf Position %d", Cursor_pos);
            
            // read "set"-many characters from file and store into sBuffer

            // insert into sBuffer[0], sBuffer[1], ... sBuffer[set-1]

            
            if( pFile->Read( set, pBuffer ) == TB_OK ) 
            BufferGroesse = set;
            
            // this doesnt work... you wont get proper size of  sBuffer-Array

            //BufferGroesse = strlen(sBuffer);

            tbWriteToLog("Buffergröße: %d", BufferGroesse);
            // because array begins at 0, we have to break if k = BuffSize

            for (int k=0;k<BufferGroesse;k++)
                tbWriteToLog("Feld %d: %c", k, sBuffer[k]);
            
            status=1;
        }
    }while(status==0);
    
    if(pFile->SaveToFile("copy.txt"))
    {
        tbWriteToLog("Fehler beim Schreiben der Datei!");
    }
    else
    {
        tbWriteToLog("Die Datei \"copy.txt\" wurde erfolgreich geschrieben.");
    }


Danke für die Hilfe :wirbel:

BlackViper
Fürchte nicht langsam zu gehen,
fürchte nur, stehen zu bleiben.

Anonymous

unregistriert

10

06.08.2005, 17:49

Du sagst, dass es so funktioniert, was mir jedoch ein Rätsel ist, da dein Puffer immernoch die Größe von 1Byte hat.
Du jedoch bis zu 5Bytes (da set ja 5 ist) liest.

Meine tbVFile::read Funktion sieht so aus

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
// ******************************************************************

// Lesen aus einer virtuellen Datei

tbResult tbVFile::Read(int iNumBytes,
                       void* pOut)
{
    // Parameter prüfen

    if(iNumBytes == 0)  return TB_OK;
    if(iNumBytes < 0)   TB_ERROR_INVALID_VALUE("iNumBytes", TB_ERROR);
    if(pOut == NULL)    TB_ERROR_NULL_POINTER("pOut", TB_ERROR);


    BOOL bError = FALSE;

    // Überschreitet der Lesevorgang das Dateiende?

    if(m_iCursor + iNumBytes > m_iSize)
    {
        // Das Ende der Datei ist überschritten - das wird vermerkt!

        // Die Anzahl der zu lesenden Bytes muss angepasst werden.

        iNumBytes = m_iSize - m_iCursor;
        bError = TRUE;
    }

    // Daten kopieren und den Lesezeiger weiterbewegen

    memcpy(pOut, (BYTE*)(m_pBuffer) + m_iCursor, iNumBytes);
    m_iCursor += iNumBytes;
    if(m_iCursor >= m_iSize) m_bEOF = TRUE;

    // Wurde das Ende der Datei weit überschritten, so wird ein Fehlercode

    // zurückgeliefert.

    return bError ? TB_ERROR : TB_OK;
}


demnach würde beim kopieren der Dateien mit memcpy aus dem Puffer von tbVFile in deinen pBuffer bis zu 5Zeichen gelesen werden, du hast jedoch nur 1Byte platz.

Entweder ich übersehe hier irgendwas oder es dürfte nicht fehlerfrei funktionieren.

Werbeanzeige