C Tutorial – Fortgeschrittenes – Feedback

Schnelle objektorientierte, kompilierende Programmiersprache.
Antworten
Xeon
Beiträge: 169
Registriert: So Dez 17, 2017 4:10 pm

C Tutorial – Fortgeschrittenes – Feedback

Beitrag von Xeon » Di Dez 10, 2019 2:35 pm

Hallo,

diesmal ist es nicht nur ein Feedback, sondern Fragen sind auch dabei.


6. Attribute

Das Atribute UNSIGNED
Auch wenn sich int kürzer schreibt als unsigned int, so steckt für den Compiler, wie auch für den Menschen eine zusätzliche Information in diesem Datentyp. Auf ein Array darf man meistens nur mit positiven Werten zugreifen. Möchte man auf ein Array mit 256 Elementen zugreifen, so darf der Index selbst kein char sein, sondern muss mindestens ein unsigned char sein, da man ansonsten nicht hinter den Beginn des Arrays zugreift, sondern von 128 Elementen vor dem Arraybeginn bis 127 Elemente nach dem Arraybeginn. Die hinteren 128 Elemente erreicht man so nicht, während man gleichzeitig 128 Elemente erreicht, auf die man nicht zugreifen darf. Dies zu vergessen ist ein beliebter Anfängerfehler. Es ist auch nicht in der Verantwortung der Programmiersprache, dem Entwickler zu erklären, was er tun und lassen darf, sondern Du musst dem Computer erklären, was er tun soll. Bei einem Array, bei dem Du hinter den Start zugreifen möchtest, benutze also möglichst Variablen eines Integertyps, der mit dem Attribut unsigned erweitert wurde.

Xeon: Warum unsigned, wenn man auf einem negativen Bereich zugreifen möchte?


8. Dateien

Die Größe einer Datei herausfinden

Xeon: Ich weiß nicht was du dazu meinst Xin, aber bei Windows kann man einen Pfand nun auch nur mit diesem Zeichen ‚/‘ öffnen statt mit ‚\\‘ .


Eine Datei in den Speicher kopieren

Code: Alles auswählen

include <stdio.h>
#include <stdlib.h>
 
int main (void)
{
  FILE *file = fopen("datei.txt", "r");
 
  if( file )
  {
    fseek( file, 0, SEEK_END );
    long int size = ftell( file );
    printf( "Wir befinden uns an Position %ld, die Datei ist also bisher %ld Byte groß.\n", size, size-1 );
    fseek( file, 0, SEEK_SET );
 
    char * buffer = (char *) malloc( size );
    if( buffer )
    {
      long int read = fread( buffer, sizeof( char ), size-1, file );
 
      if( read != size - 1 )
        printf( "%ld sollten gelesen werden, es wurden aber nur %ld Bytes gelesen.\n", size-1, read );
 
      buffer[ read ] = '\0';
 
      printf( "Text gelesen:\n%s\n", buffer );
    } 
    else
      printf( "Speicher konnte nicht angefordert werden.\n" );
 
    fclose(file);
  }
  else
    printf( "Datei konnte nicht geöffnet werden.\n" );
 
  return EXIT_SUCCESS;
}
Xeon: Bei mir wird der letzte Buchstabe nicht ausgegeben. Wenn ich aber im Code size-1 durch size ersetze geht es wunderbar. Ist dies ein Fehler von dir Xin oder eine Aufgabe?


Liebe Grüße
Xeon

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8858
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: C Tutorial – Fortgeschrittenes – Feedback

Beitrag von Xin » Di Dez 10, 2019 6:53 pm

Xeon hat geschrieben:
Di Dez 10, 2019 2:35 pm
6. Attribute

Das Atribute UNSIGNED
Auch wenn sich int kürzer schreibt als unsigned int, so steckt für den Compiler, wie auch für den Menschen eine zusätzliche Information in diesem Datentyp. Auf ein Array darf man meistens nur mit positiven Werten zugreifen. Möchte man auf ein Array mit 256 Elementen zugreifen, so darf der Index selbst kein char sein, sondern muss mindestens ein unsigned char sein, da man ansonsten nicht hinter den Beginn des Arrays zugreift, sondern von 128 Elementen vor dem Arraybeginn bis 127 Elemente nach dem Arraybeginn. Die hinteren 128 Elemente erreicht man so nicht, während man gleichzeitig 128 Elemente erreicht, auf die man nicht zugreifen darf. Dies zu vergessen ist ein beliebter Anfängerfehler. Es ist auch nicht in der Verantwortung der Programmiersprache, dem Entwickler zu erklären, was er tun und lassen darf, sondern Du musst dem Computer erklären, was er tun soll. Bei einem Array, bei dem Du hinter den Start zugreifen möchtest, benutze also möglichst Variablen eines Integertyps, der mit dem Attribut unsigned erweitert wurde.

Xeon: Warum unsigned, wenn man auf einem negativen Bereich zugreifen möchte?
Du möchtest ja nicht auf einen negativen Bereich zugreifen.
Ein signed char geht von -128 bis +127. Ein Array von 256 Zeichen hingegen geht von 0 bis 255. Wenn Du nach dem 127. Zeichen auf das -128. zugreifst, bist Du außerhalb des Arrays, denn 127+1 = -128, wenn Du signed chars benutzt.
Du greifst 128 Zeichen vor das Array, da sind aber vermutlich nicht die Daten, die Du erwartest.
Xeon hat geschrieben:
Di Dez 10, 2019 2:35 pm
8. Dateien

Die Größe einer Datei herausfinden

Xeon: Ich weiß nicht was du dazu meinst Xin, aber bei Windows kann man einen Pfand nun auch nur mit diesem Zeichen ‚/‘ öffnen statt mit ‚\\‘ .
Unter Windows ist der Verzeichnistrenner der Backslash und der wird unter C als Einleitung einer Escapesequenz genutzt. Um also den \ hinzubekommen, musst Du \\ schreiben.
Unter Unixoiden wird der Slash als Verzeichnistrenner benutzt.


Eine Datei in den Speicher kopieren

Code: Alles auswählen

include <stdio.h>
#include <stdlib.h>
 
int main (void)
{
  FILE *file = fopen("datei.txt", "r");
 
  if( file )
  {
    fseek( file, 0, SEEK_END );
    long int size = ftell( file );
    printf( "Wir befinden uns an Position %ld, die Datei ist also bisher %ld Byte groß.\n", size, size-1 );
    fseek( file, 0, SEEK_SET );
 
    char * buffer = (char *) malloc( size );
    if( buffer )
    {
      long int read = fread( buffer, sizeof( char ), size-1, file );
 
      if( read != size - 1 )
        printf( "%ld sollten gelesen werden, es wurden aber nur %ld Bytes gelesen.\n", size-1, read );
 
      buffer[ read ] = '\0';
 
      printf( "Text gelesen:\n%s\n", buffer );
    } 
    else
      printf( "Speicher konnte nicht angefordert werden.\n" );
 
    fclose(file);
  }
  else
    printf( "Datei konnte nicht geöffnet werden.\n" );
 
  return EXIT_SUCCESS;
}
Xeon: Bei mir wird der letzte Buchstabe nicht ausgegeben. Wenn ich aber im Code size-1 durch size ersetze geht es wunderbar. Ist dies ein Fehler von dir Xin oder eine Aufgabe?[/quote]
Soweit ich weiß, habe ich dazu keine Aufgabe.
Ich habe Deinen hier geposteten Quelltext kopiert und kompiliert. Das sieht aus wie der Quelltext aus dem Tutorial.

Bei mir kommt raus:

Code: Alles auswählen

xin@dualpower:~/proggen$ ./a.out 
Wir befinden uns an Position 11, die Datei ist also bisher 10 Byte groß.
Text gelesen:
Hallo Welt
und die Datei ist einfach der Text "Hallo Welt":

Code: Alles auswählen

xin@dualpower:~/proggen$ ls -lha datei.txt 
-rw-rw-r-- 1 xin xin 11 Dez 10 18:48 datei.txt
xin@dualpower:~/proggen$ cat datei.txt 
Hallo Welt
So, wie ich mir das vorgestellt habe.

Wenn Du da noch Schwierigkeiten hast, pack es in zip und lad es hier hoch. Auch wenn es keinen Unterschied machen sollte: Welches Betriebsystem nutzt Du?
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

mfro
Beiträge: 346
Registriert: Mi Jan 16, 2013 4:58 pm

Re: C Tutorial – Fortgeschrittenes – Feedback

Beitrag von mfro » Di Dez 10, 2019 8:37 pm

Xin hat geschrieben:
Di Dez 10, 2019 6:53 pm
Xeon hat geschrieben:
Di Dez 10, 2019 2:35 pm
Xeon: Ich weiß nicht was du dazu meinst Xin, aber bei Windows kann man einen Pfand nun auch nur mit diesem Zeichen ‚/‘ öffnen statt mit ‚\\‘ .
Unter Windows ist der Verzeichnistrenner der Backslash und der wird unter C als Einleitung einer Escapesequenz genutzt. Um also den \ hinzubekommen, musst Du \\ schreiben.
Unter Unixoiden wird der Slash als Verzeichnistrenner benutzt.
Da hat der Xeon recht: Windows versteht durchaus auch den Forward-Slash "/" als Verzeichnistrenner (ausserhalb von CMD.EXE, jedenfalls).
It's as simple as that. And remember, Beethoven wrote his first symphony in C.

nufan
Wiki-Moderator
Beiträge: 2557
Registriert: Sa Jul 05, 2008 3:21 pm

Re: C Tutorial – Fortgeschrittenes – Feedback

Beitrag von nufan » Mi Dez 11, 2019 7:52 am

Xin hat geschrieben:
Di Dez 10, 2019 6:53 pm
Xeon hat geschrieben:
Di Dez 10, 2019 2:35 pm
Bei einem Array, bei dem Du hinter den Start zugreifen möchtest, benutze also möglichst Variablen eines Integertyps, der mit dem Attribut unsigned erweitert wurde.

Xeon: Warum unsigned, wenn man auf einem negativen Bereich zugreifen möchte?
Du möchtest ja nicht auf einen negativen Bereich zugreifen.
Ich glaube das Problem liegt hier an der Formulierung "hinter den Start". Spontan hätte ich das auch als negativen Offset interpretiert.
Xin hat geschrieben:
Di Dez 10, 2019 6:53 pm
Xeon hat geschrieben:
Di Dez 10, 2019 2:35 pm
Eine Datei in den Speicher kopieren

Code: Alles auswählen

include <stdio.h>
#include <stdlib.h>
 
int main (void)
{
  FILE *file = fopen("datei.txt", "r");
 
  if( file )
  {
    fseek( file, 0, SEEK_END );
    long int size = ftell( file );
    printf( "Wir befinden uns an Position %ld, die Datei ist also bisher %ld Byte groß.\n", size, size-1 );
    fseek( file, 0, SEEK_SET );
 
    char * buffer = (char *) malloc( size );
    if( buffer )
    {
      long int read = fread( buffer, sizeof( char ), size-1, file );
 
      if( read != size - 1 )
        printf( "%ld sollten gelesen werden, es wurden aber nur %ld Bytes gelesen.\n", size-1, read );
 
      buffer[ read ] = '\0';
 
      printf( "Text gelesen:\n%s\n", buffer );
    } 
    else
      printf( "Speicher konnte nicht angefordert werden.\n" );
 
    fclose(file);
  }
  else
    printf( "Datei konnte nicht geöffnet werden.\n" );
 
  return EXIT_SUCCESS;
}
Xeon: Bei mir wird der letzte Buchstabe nicht ausgegeben. Wenn ich aber im Code size-1 durch size ersetze geht es wunderbar. Ist dies ein Fehler von dir Xin oder eine Aufgabe?
Soweit ich weiß, habe ich dazu keine Aufgabe.
Ich habe Deinen hier geposteten Quelltext kopiert und kompiliert. Das sieht aus wie der Quelltext aus dem Tutorial.

Bei mir kommt raus:

Code: Alles auswählen

xin@dualpower:~/proggen$ ./a.out 
Wir befinden uns an Position 11, die Datei ist also bisher 10 Byte groß.
Text gelesen:
Hallo Welt
und die Datei ist einfach der Text "Hallo Welt":

Code: Alles auswählen

xin@dualpower:~/proggen$ ls -lha datei.txt 
-rw-rw-r-- 1 xin xin 11 Dez 10 18:48 datei.txt
xin@dualpower:~/proggen$ cat datei.txt 
Hallo Welt
So, wie ich mir das vorgestellt habe.
Hier gebe ich Xeon recht. Das "size-1" beim Aufruf von "fread()" passt nicht. Es muss zwar ein Byte mehr allokiert als gelesen werden um den String korrekt zu beenden, beim Quelltext im Tutorial wird aber das letzte Zeichen nicht gelesen.
@Xin: Eventuell hast du ein Newline am Ende deiner Datei. Da auch in "printf()" noch ein Newline ausgegeben wird, würde das nicht auffallen. Deine Datei hat laut "ls" 11 Byte, aber der Text "Hallo Welt" nur 10 Zeichen, also ist das wahrscheinlich das Problem :)

Zum Vergleich:

Code: Alles auswählen

$ gcc main.c   
$ echo -n test > datei.txt 
$ ./a.out datei.txt   
Wir befinden uns an Position 4, die Datei ist also bisher 3 Byte groß.
Text gelesen:
tes
$

Xeon
Beiträge: 169
Registriert: So Dez 17, 2017 4:10 pm

Quelltext

Beitrag von Xeon » Mi Dez 11, 2019 4:01 pm

Hallo Xin,

ja das ist der Quelltext vom Tutorial, habe ihn eins zu eins kopiert. Habe in meiner Datei ein Newline Zeichen angehängt nach nufan und jetzt geht es bei mir so auch.

Um deine Frage zu beantworten: Ich benutze Windows

Xeon
Beiträge: 169
Registriert: So Dez 17, 2017 4:10 pm

Lob an den Autor

Beitrag von Xeon » Mi Dez 18, 2019 2:11 pm

Hallo

Jetzt mal ein Lob an den Autor vom C Tutorial. Die Themen sind gut erklärt, es werden Dinge erklärt die ich vorher nicht gewusst habe. Bin gespannt auf die Expertenthemen.




Liebe Grüße
Xeon

nufan
Wiki-Moderator
Beiträge: 2557
Registriert: Sa Jul 05, 2008 3:21 pm

Re: C Tutorial – Fortgeschrittenes – Feedback

Beitrag von nufan » Mi Dez 25, 2019 5:53 pm

Hallo Xeon!
Ich habe die beiden von dir angesprochenen Abschnitte zu Attributen und Dateien angepasst. Sollte noch immer etwas unklar sein, bitte einfach melden :)

Antworten