Tutoriumsinhalt

  • Testreports
  • Funktionen
  • Arrays
  • Strings
  • Bitoperationen

What does the Palme say? - Die magischen Codes

  • Was bedeuten die Codes wie 6a7, 1,6c1,6, 6d5?
  • Am Testsystem werden die Ausgabe eures Programms mit der korrekten Ausgabe verglichen (mit diff).
  • Die Codes geben an, was an der Musterausgabe geändert werden müsste, um eure Ausgabe zu erhalten
  • Es gibt dabei die Codes a (append), d (delete) und c (change)
CHANCE #1
  description:
    check whether output is correct
  summary:
    [FAILED] comparing "$STDOUT"

  compares:
        < REFERENCE
        > USER CREATED

    #0: 6d5 

Beispiel

  • 6a7: Nach der 6. Zeile der Musterausgabe, müsste die folgende 7. Zeile angehängt werden (Zeile folgt). Das heißt, ihr gebt dieses Zeile zuviel aus
  • 6d5: Die 6. Zeile der Musterausgabe (Zeile folgt) müsste gelöscht werden. Das heißt, ihr gebt eine Zeile nicht aus, obwohl ihr solltet
  • 2c2: Die 2. Zeile der Musterausgabe stimmt nicht mit eurer 2. Zeile überein, daraufhin folgt die Zeile der Musterausgabe und eure Zeile

Was stimmt hier nicht?

=====================================================================================
TESTCASES

testcase #1 [FAILED]
  there were 1 chance(s) to pass testcase

CHANCE #1
  description:
    check whether output is correct
  summary:
    [FAILED] return check - ref: 0 user: 255

  compares:
        < REFERENCE
        > USER CREATED


-------------------------------------------------------------------------------------
===================================================================================== 
   

Und hier?

=====================================================================================
TESTCASES

testcase #1 [FAILED]
  there were 1 chance(s) to pass testcase

CHANCE #1
  description:
    check whether output is correct
  summary:
    [FAILED] comparing "$STDOUT"

  compares:
        < REFERENCE
        > USER CREATED

    #0: 6a7
    #0: > 1915657434 * 8

-------------------------------------------------------------------------------------
===================================================================================== 
   

Findet den Fehler...

OUTPUT
    Archive:  Term_6/Course_11/Assignment_58/Group_7642/Submission_1_hw1a.zip
      inflating: Course_11/Assignment_58/Group_7642/14960/1381852533/hw1a/hw1a.c
    Returnvalue was: 0 - should be 0
=====================================================================================
CHECK

check #1
  Result:
    [FAILED] File hw1a.c not found
=====================================================================================
COMPILE

executable #1
  using file_set #1
  return was: 1 - should be 0

OUTPUT
  gcc44: hw1a.c: No such file or directory
  gcc44: no input files  
   

... noch mehr Fehler ...

summary:
    [FAILED] comparing "$STDOUT"

  compares:
        < REFERENCE
        > USER CREATED

    #0: 1,7c1,7
    #0: <    xxxxxxx * 2
    #0: <    xxxxxxx * 3
    #0: <    xxxxxxx * 4
    #0: <   xxxxxxxx * 5
    #0: <  xxxxxxxxx * 6
    #0: <  xxxxxxxxx * 7
    #0: < An overflow has occurred!
    #0: ---
    #0: > xxxxxxx * 2
    #0: > xxxxxxx * 3
    #0: > xxxxxxx * 4
    #0: > xxxxxxxx * 5
    #0: > xxxxxxxxx * 6
    #0: > xxxxxxxxx * 7
    #0: > An overflow has occured!    
   

Auch hier gibt es einen Fehler!

summary:
    [FAILED] comparing "$STDOUT"

  compares:
        < REFERENCE
        > USER CREATED

    #0: 1,6c1,6
    #0: <    xxxxxxx * 2
    #0: <    xxxxxxx * 3
    #0: <    xxxxxxx * 4
    #0: <   xxxxxxxx * 5
    #0: <  xxxxxxxxx * 6
    #0: <  xxxxxxxxx * 7

    #0: ---
    #0: >    xxxxxxx * 2 
    #0: >    xxxxxxx * 3 
    #0: >    xxxxxxx * 4 
    #0: >   xxxxxxxx * 5 
    #0: >  xxxxxxxxx * 6 
    #0: >  xxxxxxxxx * 7 

   

Funktionen

<Rueckgabewert-Typ> Funktion-Name (<Parameter1>, <Parameter2>...)
{
  // Code 
  return <Rueckgabewert> 
}

int main()
{
  // Aufruf:
  <Rueckgabewert-Typ> Ergebnis;
  Ergebnis = Funktion-Name(<Parameter1>, <Parameter2>...);
} 

Rückgabewert der main-Funktion anzeigen

> echo $?
0

Arrays

  • Hintereinander liegende Daten vom gleichen Typ
  • Größe kann nicht mehr verändert werden, muss bei Deklaration bekannt sein
  • Zugriff über [ ]
  • Deklaration:
    <typ> name[<size>];
  • Initialisiertes Array:
    <typ> name[] = {<value1>, <value2>, ...};
  • Zugriff:
    name[<index>] = <value>;

Beispiel

1int main() { 2 int fibo[5]; 3 fibo[0] = 1; 4 fibo[1] = 1; 5 fibo[2] = fibo[1] + fibo[0]; 6 fibo[3] = fibo[2] + fibo[1]; 7 fibo[4] = fibo[3] + fibo[2]; return 0; }
0x1000
0x1004
0x1008
0x100C
0x1010
0x1014
fibo   0x1000
0x1004
0x1008
0x100C
0x1010
0x1014
fibo   0x10001
0x1004
0x1008
0x100C
0x1010
0x1014
fibo   0x10001
0x10041
0x1008
0x100C
0x1010
0x1014
fibo   0x10001
0x10041
0x10082
0x100C
0x1010
0x1014
fibo   0x10001
0x10041
0x10082
0x100C3
0x1010
0x1014
fibo   0x10001
0x10041
0x10082
0x100C3
0x10105
0x1014

Variable-length-Arrays

  • GCC akzeptiert Arrays mit variabler Länge (C99 Standard)
  • Beispiel
    int size = numberOfHornsOnAUnicorn();
    int array[size];
    
  • Gefährlich zu verwenden, da diese Arrays am Stack liegen → normal 8MB maximale Größe, kann jedoch auch nur 64kB sein!
  • Ist das Array zu groß, stürzt das Programm ohne erkennbare Ursache ab
  • Have fun debugging!
  • Array als Funktionsparameter

    • Soll ein Array an eine Funktion als Parameter übergeben werden gibt es 3 Wege
    1. Array variabler Größe
      void foo(int bar[]) {
       [..]
      }
    2. Array fixer Größe
      void foo(int bar[8]) {
       [..]
      }
    3. Als Pointer
      void foo(int* bar) {
       [..]
      }

    Spezielle Arrays: Mehrdimensionale Arrays

    • Arrays können mehrere Dimensionen haben
    • 2-dimensionale Arrays:
      <typ> name[<rows>][<columns>];
    • Zugriff über Zeilen- und Spaltenindex:
      name[<row>][<column>] = <value>;
    • Beispiel Initialisierung:
      char matrix[3][3] = { {'A', 'B', 'C'}, {'D', 'E', 'F'}, 
            {'G', 'H', 'I'} };

    Mehr als 2 Dimensionen?

    • Ja, in C beliebig viele (so lange wir Speicher haben)
    • Schwer vorstellbar ab 4 Dimensionen, deshalb als Array von Arrays denken
    int cube[3][3][3];
    int hypercube[3][3][3][3];
    

    Beispiel: 4 Dimensionen

     int hypercube[3][3][3][3];
    

    Möglichkeit 1: 4D-Würfel

    Möglichkeit 2: Array von 3D Würfeln

    Mehrdimensionale Arrays als Parameter

    #include <stdio.h>
    
    void printMatrix3(char matrix[][3])
    {
      int y;
      for(y = 0; y < 3; y++)
      {
        printf("%c %c %c\n", matrix[y][0], matrix[y][1], matrix[y][2]);
      }
    }
    
    int main()
    {
      char matrix[3][3] = { {'A', 'B', 'C'}, {'D', 'E', 'F'}, 
          {'G', 'H', 'I'} };
      printMatrix3(matrix);
    }
    
    Achtung: Nicht mehr möglich als Pointer zu übergeben!

    Strings - auch nur Arrays

    • String = Zeichenkette, »Text«
    • String ist nur ein Array von char (Zeichen)
    • Strings enden mit einem 0-Byte ('\0', nicht dem Zeichen 0!)
    • Deklaration (am häufigsten):
      char* text = "Hallo!";
    • Andere Varianten:
      char text[] = "Hallo!";
      char text[] = {'H', 'a', 'l', 'l', 'o', '!', '\0'};

    Strings: Vergleich

    • Funktion strcmp aus string.h verwenden
    • == funktioniert nicht, vergleicht nur die Speicheradressen
    •  char* str1 = "Hello";
       char* str2 = "World";
       if(strcmp(str1, str2) == 0) 
       {
         // strings sind gleich
       } 
       else 
       {
         // strings sind ungleich
       }
      

    Strings: Zugriff auf einzelne Buchstaben

    • Zugriff durch Array-Schreibweise ([])
    • Erstes Zeichen hat Index 0!
    • Letztes Zeichen ist 0-Byte ('\0')
    •  char* str1 = "Hello";
       char c1 = str[0]; // c1 = 'H'
       char c2 = str[4]; // c2 = 'o'
       char c3 = str[5]; // c3 = '\0'
      

    Strings: Funktionen

    • Weitere Funktionen die mit Strings arbeiten in string.h
    • http://www.cplusplus.com/reference/cstring/
    • Einbinden mit
      #include <string.h>
    • Nützliche Funktionen:
      strlen
      Länge des Strings (ohne 0-Byte!)
      strcpy
      String in einen anderen kopieren
      strcat
      Strings aneinanderhängen
      sprintf
      Wie printf, aber Ausgabe wird in String gespeichert

    Bitoperationen

    • Verknüpfen Daten bitweise
    • Erfordern zwei Operanden (Ausnahme: NOT)
    • AND (&), OR (|), XOR (^)
    • Left Shift (<<), Right Shift (>>)
    • NOT (~)

    Bitoperationen

    AND ... &

    &10
    110
    000

    OR ... |

    |10
    111
    010

    Bitoperationen

    XOR ... ^

    ^10
    101
    010

    NOT ... ~

    10
    ~01

    Bitoperationen

    Shift Left ... <<

    Verschiebt die Bits um n Stellen nach links
    Beispiel: 9 ( = 0000 1001b) << 1 = 18 ( = 0001 0010b)

    Shift Right ... >>

    Verschiebt die Bits n Stellen nach rechts
    Beispiel: 27 ( = 0001 1011b) >> 2 = 6 ( = 0000 0110b)

    Bitoperation - Wozu?

    • Setzen von einzelnen Bits
    • Löschen von einzelnen Bits
    • Extrahieren von Bits
    • Potenzen von 2 schnell berechnen
    • Extrahieren von Teilen eines Bytes
    • Tauschen von Bytes
    • Bitfelder

    Bitmasken-Beispiel: Bitfeld

    #include <stdio.h>
    int main()
    {
      unsigned char lampen_zustand = 0; // 8 Zustände (Lampen)
      // Lampe 1 einschalten
      lampen_zustand |= 1;
      // Lampen 5-8 ausschalten
      lampen_zustand &= 15;
      // Lampe 5 umschalten
      lampen_zustand ^= 16;
      // Zustand ausgeben
      int lampe;
      for(lampe = 0; lampe < 8; lampe++) 
      {
        printf("Lampe %d: %s\n", lampe + 1, 
          lampen_zustand & (1 << lampe) ? "ein" : "aus");
      }
    }
    

    Bitmasken-Beispiel: RGB

    Bitmasken-Beispiel: Byte-Reihenfolge

    #include <stdio.h>
    
    unsigned int swapByteOrder(unsigned int value)
    {
      value = ((value << 8) & 0xFF00FF00) |
              ((value >> 8) & 0xFF00FF); 
      return (value << 16) | (value >> 16);
    }
    
    int main()
    {
      unsigned int value = 0x12345678;
      
      printf("value = %x\n", value);
      printf("swapped value = %x\n", swapByteOrder(value));
      
      return 0;
    }
    

    Bitmasken-Beispiel: Hexadezimale Ausgabe

    #include <stdio.h>
    
    #define BITS_PER_NIBBLE 4
    #define NIBBLE_MASK 0xF
    
    int main()
    {
      int a_number = 17036401;
      int index;
      
      printf("bin = ");
      for( index = 32; index > 0; index-- )
      {
        printf( "%d", (a_number & (1 << (index - 1))) ? 1 : 0 );
        if( (index - 1) % BITS_PER_NIBBLE == 0 )
          printf(" ");
      }
      
      // This should only demonstrate how to use bit operations.
      // In practice use %x for hexadecimal output
      printf("\nhex = ");
      for( index = 32 / BITS_PER_NIBBLE; index > 0; index-- )
      {
        int nibble = (a_number >> ((index - 1) * BITS_PER_NIBBLE)) & NIBBLE_MASK;
        printf( "%4c ", nibble < 10 ? nibble + '0' : nibble + 'A' - 10 );
      }
      
      return 0;
    }
    

    Bitmasken

    Bithacking

    if((value & (value - 1) == 0)
    {
      printf("Wann werde ich ausgeführt?");
    }
    

    Bithacking

    a = a^b;
    b = b^a;
    a = a^b;
    

    Bithacking

    Viel Erfolg beim
    ersten Gruppenbeispiel!

    Abgabeschluss für Ass1:

    • 3.11.2017 14:00:00 Uhr