| ### Programmieren in C von Prof. Dr. Rainer Thomas

# Arrays

### 6.1 Eindimensionale Arrays
6.2 Zeichenketten (Strings)
6.3 Mehrdimensionale Arrays

## 6.1 Eindimensionale Arrays

### Eindimensionale Arrays in C

- Ein Array (Vektor) ist eine Datenstruktur (= zusammengesetzter Datentyp), deren Elemente (= Komponenten) alle vom gleichen Typ (= Basistyp) sind.
Die einzelnen Elemente sind in einer festliegenden Reihenfolge angeordnet und werden über einen Index angesprochen.
- C kennt nur Arrays feststehender - d.h. zur Compile-Zeit ermittelbarer - Länge.
- Die Abspeicherung eines Arrays erfolgt in einem zusammenhängenden Speicherblock;
die einzelnen Array-Elemente sind in aufeinanderfolgenden Speicherplätzen abgelegt.

Beipiel : Array mit 5 Komponenten

- Array-Variablenvereinbarung

Festlegung von

- Name der Array-Variablen
- Typ der Array-Komponenten (Basistyp)
- Anzahl der Array-Komponenten (= Länge des Arrays)
(nur bei Definition notwendig)

Syntaxdiagramm (Teildiagramm, für Definition) :

Beispiele :

    char kette[50];
    int z_feld[10];

    #define ANZ 80
    char k1[ANZ], k2[2*ANZ];

- Die Indexgrenzen sind in C nicht frei wählbar.
Untere Grenze: 0
Obere Grenze : Komponentenzahl - 1

Beispiel : `float a[5]` ---> Indexbereich 0 .. 4

- Zugriff zu einer Array-Komponente :

Angabe des Index (als int-Ausdruck) in eckigen Klammern nach dem Array- Variablennamen.

Beispiele :

    a[3],    a[i+2*j]

- Array-Variable können in einer Vereinbarung gemischt mit einfachen Variablen vereinbart werden, wenn die Array-Komponenten vom gleichen Typ wie die einfachen Variablen sind.

Beispiel :

    int z_feld[10], laenge;

- Die Längenangabe bei Array-Vereinbarungen darf fehlen :

- bei der Definition initialisierter Arrays
- in Parameterdeklarationen
- in Array-Variablen-Deklarationen

- Achtung !
Es gibt keine Laufzeitüberprüfung auf Überschreitung des max. Array- Index.

Beispiel :

    int f[10];
    ...
    f[10] = ... ;     /* Fehler, der aber nicht als Lauf-
                         zeitfehler angezeigt wird.  */

- Geschlossene Wertzuweisungen zwischen ganzen Arrays sind nicht zulässig.

Beispiel :

    int feld1[10], feld2[10];
    ...
    feld1 = feld2;    /* Unzulässig, Compilerfehler ! */

### Sieb des Eratosthenes

- Algorithmus zur Ermittlung von Primzahlen

- Realisierung des Siebs durch ein Array von logischen Werten

  `TRUE` ==> Zahl im Sieb
  `FALSE` ==> Zahl aus Sieb entfernt

2 ist die einzige gerade Primzahl, alle weiteren Primzahlen sind ungerade
--> Beschränkung auf Untersuchung der ungeraden Zahlen >=3
- Vereinfachung : Beschränkung des Siebs auf die ungeraden Zahlen >=3

--> Array flags :

    flags[0]   -->   zahl 3>
    flags[1]   -->   zahl 5
    flags[2]   -->   zahl 7
    flags[3]   -->   zahl 9
    flags[4]   -->   zahl 11
    usw.

allgemeine Zuordnung : `zahl = 2 * flags_index + 3`

### Programmbeispiel : Sieb des Eratosthenes

    /* ------------------------------------------------------------------ */
    /* Programm ERATO                                                     */
    /* ------------------------------------------------------------------ */
    /* Primzahlenermittlung mittels Sieb des Eratosthenes                 */
    /* ------------------------------------------------------------------ */

    #include <stdio.h>

    #define SIZE     503
    #define TRUE     1
    #define FALSE    0
    #define ANZZEIL  12
    #define WRITELN  putchar('\n')

    void main(void)
    {
      int i,k;
      int iPrim, iAnzahl;
      char cFlags[SIZE+1];

      printf("\nPrimzahlen zwischen 3 und %d\n\n",2*SIZE+3);
      iAnzahl=0;
      for (i=0; i<=SIZE; i++)
        cFlags[i]=TRUE;
        for (i=0; i<=SIZE; i++)
          if (cFlags[i])
          { iPrim=i+i+3;
            for (k=i; k<=SIZE; k=k+iPrim)
              cFlags[k]=FALSE;
            iAnzahl++;
            printf("%6d",iPrim);
            if (iAnzahl%ANZZEIL == 0)
              WRITELN;
          }
    }

    /* ------------------------------------------------------------------ */

Bildschirmausgabe :

    E:\RT\C\VORL>erato1

    Primzahlen zwischen 3 und 1009

         3     5     7    11    13    17    19    23    29    31    37    41
        43    47    53    59    61    67    71    73    79    83    89    97
       101   103   107   109   113   127   131   137   139   149   151   157
       163   167   173   179   181   191   193   197   199   211   223   227
       229   233   239   241   251   257   263   269   271   277   281   283
       293   307   311   313   317   331   337   347   349   353   359   367
       373   379   383   389   397   401   409   419   421   431   433   439
       443   449   457   461   463   467   479   487   491   499   503   509
       521   523   541   547   557   563   569   571   577   587   593   599
       601   607   613   617   619   631   641   643   647   653   659   661
       673   677   683   691   701   709   719   727   733   739   743   751
       757   761   769   773   787   797   809   811   821   823   827   829
       839   853   857   859   863   877   881   883   887   907   911   919
       929   937   941   947   953   967   971   977   983   991   997  1009

### Programmbeispiel : Dezimal-Dualzahl-Umwandlung

    /* ------------------------------------------------------------------ */
    /* Programm DEZDUAL */
    /* ------------------------------------------------------------------ */
    /* Umwandlung einer positiven ganzen Dezimalzahl (unsigned Integer)   */
    /* in eine Dualzahl                                                   */
    /*                                                                    */
    /* Staendige Division durch 2,                                        */
    /* der anfallende Rest stellt jeweils die naechste Ziffer dar.        */
    /* Anfallen der Ziffern von niedrigstwertiger zu hoechstwertiger      */
    /* Stelle                                                             */
    /* ------------------------------------------------------------------ */

    #include <stdio.h>

    #define BASIS    2
    #define LAENGE   16
    #define WRITELN  putchar('\n')

    void main(void)
    {
       char ziffern[LAENGE];
       unsigned zahl;
       int ziff_anz;
       printf("\npositive ganze Dezimalzahl ? ");
       scanf("%d",&zahl);
       ziff_anz=0;
       while (zahl)
       { ziffern[ziff_anz++]=zahl%BASIS+'0';
         zahl=zahl/BASIS;
       }
       printf("\numgewandelt in Dualzahl    : ");
       for (ziff_anz--; ziff_anz>=0; ziff_anz--)
          putchar(ziffern[ziff_anz]);
       WRITELN;
    }

    /* ------------------------------------------------------------------ */

Bildschirmausgabe :

    E:\RT\C\VORL>dezdual

    positive ganze Dezimalzahl ? 135

    umgewandelt in Dualzahl    : 10000111

### Initialisierung von Arrays

- In C können auch Arrays bei der Definition initialisiert werden.
KuR-C : nur globale und statisch-lokale Arrays
ANSI-C: auch lokale Arrays der Speicherklasse auto
- Syntax :

Die Initialisierungswerte für die einzelnen Komponenten sind als konstante Ausdrücke anzugeben und durch Kommata getrennt in geschweiften Klammern zusammenzufassen

Achtung :
  auch für lokale Arrays der Speicherklasse auto sind nur konstante Ausdrücke als Initialisierungswerte zulässig Unterschied zu einfachen Variablen)

- Beispiel :

    #define AWERT 5
    int ifeld[4] = { 2, AWERT+3, 2*AWERT, -8};

- Bei der Definition initialisierter Arrays kann die Angabe der Array- Komponentenzahl (Arraylänge) weggelassen werden:
Das Array bekommt genausoviel Komponenten, wie Initialisierungswerte angegeben werden.
- Wird bei der Definition initialisierter Arrays die Arraylänge angegeben und werden weniger Initialisierungswerte als es der Arraylänge entspricht angegeben, so werden die ersten Komponenten mit den angegebenen Werten und die restlichen Komponenten mit 0 initialisiert.

Beispiel :

    int ifeld[5] = {1, 2, 3};  -->  ifeld[0] = 1
                                    ifeld[1] = 2
                                    ifeld[2] = 3
                                    ifeld[3] = ifeld[4] = 0

- Die Angabe von mehr Initialisierungswerten als der Arraylänge entspricht ist ein Fehler !
- Soll ein Element in der Mitte des Arrays initialisiert werden, so müssen auch alle vorhergehenden Elemente initialisiert werden.
- Es gibt keine Möglichkeit zur einfachen Angabe einer wiederholten Initialisierung aufeinanderfolgender Komponenten mit gleichen Werten.
- Die Komponenten nichtinitialisierter Arrays

- werden bei globalen und statisch-lokalen Arrays defaultmäßig mit 0 initialisiert,
- bzw sind bei lokalen Arrays der Speicherklasse auto undefiniert

### Programmbeispiel zur Initialisierung von Arrays in C

    /* ------------------------------------------------------------------ */
    /* Programm INITAR1                                                   */
    /* ------------------------------------------------------------------ */
    /* Demonstration der Initialisierung von Arrays                       */
    /* (hier: globale Arrays)                                             */
    /* ------------------------------------------------------------------ */

    #include <stdio.h>

    #define ANZ 4

    float a[]   ={3.5, -7.2, -4.3, 1.8};
    float b[ANZ]={2.9, 1.3, 5.1};

    void main(void)
    {
      float c[ANZ];
      int i;
      void aus_array(float [], int);               /* Funktionsdeklaration */

      for (i=0; i<ANZ; i++)
        c[i]=a[i]+b[i];
        aus_array(c,ANZ);
    }

    void aus_array(float feld[], int laenge)       /* Funktionsdefinition */
    {
      int i;

      printf("\n{ ");
      for (i=0; i<(laenge-1); i++)
        printf("%.2f, ",feld[i]);
      printf("%.2f }\n",feld[laenge-1]);
    }

    /* ------------------------------------------------------------------ */

Bildschirmausgabe :

    E:\RT\C\VORL>initar1

    { 6.40, -5.90, 0.80, 1.80 }

## 6.2 Zeichenketten (Strings)

### Zeichenketten (Strings) in C

- Zeichenketten (Strings) in C sind spezielle char-Arrays.
Die Komponenten derartiger Arrays sind die einzelnen Zeichen des Strings, gefolgt von einem abschließenden NUL-Zeichen ('`\0`').

Das NUL-Zeichen ('`\0`') dient zur Kennzeichnung des String-Endes.

--> | Eine char-Array-Variable, die einen String aufnehmen soll, muß wenigstens um eine Komponente länger, als der String lang ist, sein.

Beispiel : `char wort[4];`

--> Die Variable wort kann Strings der maximalen Länge 3 aufnehmen.

  z.B.:

    wort[0]='d';

    wort[1]='i';

    wort[2]='e';

    wort[3]='\0';

- char-Arrays können mit einer String-Konstanten initialisiert werden.

d.h. statt
  `char wort[] = {'d', 'i', 'e', '\0'};`

kann man auch schreiben
  `char wort[] = "die";`

- In C selbst sind keine weiteren Sprachelemente zur Manipulation von Strings enthalten.
Insbesondere ist es nicht möglich, einer char-Array-Variablen einen ganzen String per Zuweisung geschlossen zu übergeben.
- Es existieren aber in der C-Standard-Bibliothek eine Reihe von Funktionen zur Stringbearbeitung.

z.B.:

strcat() | Konkatenation zweier Strings
strcmp() | Vergleich zweier Strings
strcpy() | Kopieren eines Strings
strlen() | Ermittlung der Länge eines Strings
strchr() | Durchsuchen eines Strings nach einem Zeichen
strstr() | Durchsuchen eines Strings nach einem anderen String

- Die Ausgabe von Strings ist sehr einfach mit

`printf() und puts()`

und die Eingabe (Zuweisung an String-Variable) mit

`scanf() und gets()`

möglich.

### Programmbeispiel zu Strings in C (1)

    /* ------------------------------------------------------------------ */
    /* Programm STRDEM1                                                   */
    /* ------------------------------------------------------------------ */
    /* Demonstrationsprogramm zu Zeichenketten (Strings)                  */
    /* ------------------------------------------------------------------ */

    #include <stdio.h>

    #define NUL '\0'

    char satz[]="Warum C ?";

    void main(void)
    {
      int i=0;
      printf("\n%s\n\n",satz);
      while (satz[i]!=NUL)
      { printf("%c =  %02x\n",satz[i],satz[i]);
        i++;
      }
      printf("  =  %02x\n",satz[i]);
    }

    /* ------------------------------------------------------------------ */

Bildschirmausgabe :

    E:\RT\C\VORL>strdem1

    Warum C ?

    W = 57
    a = 61
    r = 72
    u = 75
    m = 6d
      = 20
    C = 43
      = 20
    ? = 3f
      = 00

### Programmbeispiel zu Strings in C (2)

    /* ------------------------------------------------------------------ */
    /* Programm STRDEM2                                                   */
    /* ------------------------------------------------------------------ */
    /* Demonstrationsprogramm zu Zeichenketten (Strings)                  */
    /* ------------------------------------------------------------------ */

    #include <stdio.h>

    #define NUL   '\0'
    #define MAXL  80

    void main(void)
    {
      char wort[MAXL+1];
      int i=0;
      printf("\nEingabestring ? ");
      scanf("%s",wort);              /* kein Adressoperator ! */
      printf("\n%s\n\n",wort);
      while(wort[i]!=NUL)
      { printf("%c =  %02x\n",wort[i],wort[i]);
        i++;
      }
      printf("  =  %02x\n",wort[i]);
    }

    /* ------------------------------------------------------------------ */

Bildschirmausgabe :

    E:\RT\C\VORL>strdem2

    Eingabestring ? darum

    darum

    d = 64
    a = 61
    r = 72
    u = 75
    m = 6d
      = 00

### Programmbeispiel : Stringfunktionen (1)

    /* ------------------------------------------------------------------- */
    /* Programm STRDEM3                                                    */
    /* ------------------------------------------------------------------- */
    /* Demonstration selbstgeschriebener String-Funktionen                 */
    /* Einlesen, Kopieren und Ermittlung der Laenge eines Strings          */
    /* ------------------------------------------------------------------- */

    #include <stdio.h>

    #define NUL   '\0'
    #define MAXL  80

    int StrLang(char acKette[])                       /* Länge von acKette */
    {
      int i=0;
      while (acKette[i] != NUL)
        i++;
      return(i);
    }

    void StrCopy(char acStr1[], char acStr2[])  /* Copy acStr1 nach acStr2 */
    {
      int i=0;
      while ((acStr2[i]=acStr1[i])!=NUL)
        i++;
    }

    void main(void)
    {
      char acEinString[MAXL+1],acAusString[MAXL+1];
      printf("\nEingabestring ? ");
      scanf("%s",acEinString);
      StrCopy(acEinString,acAusString);
      printf("\nAusgabestring = %s\n",acAusString);
      printf("Stringlaenge  = %d\n",StrLang(acEinString));
    }

    /* ------------------------------------------------------------------- */

Bildschirmausgabe :

    E:\RT\C\VORL>strdem3

    Eingabestring ? Es_ist_so_schoen

    Ausgabestring = Es_ist_so_schoen
    Stringlaenge  = 16

### Funktionen der ANSI-C-Standardbibliothek zur Stringbearbeitung (1)

- Die ANSI-C-Standardbibliothek stellt eine Reihe von Funktionen zur Manipulation von Strings und Zeichenarrays zur Verfügung:

- Funktionen zum Kopieren von Strings und Zeichenarrays
- Funktionen zum Aneinanderhängen von Strings
- Funktionen zum Vergleich von Strings und Zeichenarrays
- Funktionen zum Suchen nach Zeichen und Zeichenfolgen in Strings und Zeichenarrays
- Funktion zur Ermittlung der Länge eines Strings
- Funktion zum Füllen eines Arrays mit einem Zeichen
- Funktion zur Ermittlung der zu einer Fehlernummer gehörenden Fehlermeldung

- Die entsprechenden Funktions-Deklarationen befinden sich in der
Standard-Header-Datei `<string.h>`.
Diese ist daher bei Verwendung der Funktionen mittels

`#include <string.h>`

einzubinden.

In <string.h> ist auch der von einigen Funktionen verwendete

Datentyp `size_t`

definiert.
Dies ist der "natürliche" unsigned-Typ, d.h. der Typ, den der sizeof-Operator liefert.
- Da in C Array-Grenzen-Überschreitungen nicht überprüft werden, liegt es am Programmierer einen Array-Überlauf zu verhindern.
(Im ANSI-Standard ist lediglich festgelegt, daß das Überschreiten von Array-Grenzen zu einem undefinierten Verhalten führt.)
- Alle Kopierfunktionen - außer memmove - setzen voraus, daß sich der Quell- und der Zielbereich nicht überlappen.
Im Falle der Überlappung ist das Verhalten undefiniert.
- In der ANSI-C-Standardbibliothek sind noch drei weitere Funktionen enthalten, die zu den Ein-/Ausgabefunktionen gerechnet werden, die aber in Wirklichkeit Stringbearbeitungsfunktionen darstellen
( --> String-I/O-Funktionen) :

- Funktion zur formatierten "Eingabe" aus einem String
- zwei Funktionen zur formatierten "Ausgabe" in einen String

Bei Anwendung dieser Funktionen ist die Standard-Header-Datei <stdio.h> einzubinden.

    /* -------------------------------------------------------------------- */
    /*          strcpy          -         Kopieren eines Strings     */
    /* -------------------------------------------------------------------- */

    #include <string.h>       /* enthält Funktionsdeklaration */

    char *strcpy(char *str1, const char *str2);
                           /* str1   String, in den kopiert wird (Zielstring) */
                           /* str2   String, der kopiert wird (Quellstring)   */

"`strcpy`" kopiert den String "`str2`" in den String "`str1`"
(genauer : an die Stelle, auf die durch "`str1`" gezeigt wird)

Funktionswert :
  Pointer auf den Zielstring, d.h. "`str1`"
( = 1. Parameter )

    /* -------------------------------------------------------------------- */
    /*          strcat         -        Konkatenation zweier Strings */
    /* -------------------------------------------------------------------- */

    #include <string.h>       /* enthält Funktionsdeklaration  */

    char *strcat(char *str1, const char *str2);
                           /* str1   String, an den angehängt wird */
                           /* str2   String, der angehängt wird    */

"`strcat`" hängt den String "`str2`" an den String "`str1`" an.
(der resultierende String "`str1`" wird mit dem '\0'-Zeichen abgeschlossen)

Funktionswert :
  Pointer auf den resultierenden String, d.h. "`str1`"
( = 1. Parameter )

    /* -------------------------------------------------------------------- */
    /*          strcmp          -         Vergleich zweier Strings   */
    /* -------------------------------------------------------------------- */

    #include <string.h>       /* enthält Funktionsdeklaration    */

    int strcmp(const char *str1, const char *str2);
                           /* str1   erster zu vergleichender String  */
                           /* str2   zweiter zu vergleichender String */

"strcmp" vergleicht den String "`str1`" lexikographisch mit dem String "`str2`".

Funktionswert :
  < 0 , wenn "`str1`" kleiner "`str2`" ist
  = 0 , wenn "`str1`" gleich "`str2`" ist
  > 0 , wenn "`str1`" groesser "`str2`" ist

    /* -------------------------------------------------------------------- */
    /*        strchr -  Durchsuchen eines Strings nach einem Zeichen */
    /* -------------------------------------------------------------------- */

    #include <string.h>     /* enthält Funktionsdeklaration */

    char *strchr(const char *str, int c);
                               /* str       zu durchsuchender String */
                               /* c         Suchzeichen              */

"`strchr`" durchsucht den String "`str`" nach dem ersten Auftreten des Zeichens "`c`"

Funktionswert :
  Pointer auf die Stelle im String "`str`", an der das Zeichen %quot;`c`" erstmals auftritt,
bzw. NULL-Pointer, wenn das Zeichen %quot;`c`" nicht im String %quot;`str`" enthalten ist.

    /* -------------------------------------------------------------------- */
    /*  strstr - Durchsuchen eines Strings nach einem anderen String */
    /* -------------------------------------------------------------------- */

    #include <string.h>     /* enthält Funktionsdeklaration */

    char *strstr(const char *str1, const char *str2);
                               /* str1     zu durchsuchender String */
                               /* str2     Suchstring               */

"`strstr`" durchsucht den String "`str1`" nach dem ersten Auftreten des Strings "`str2`"

Funktionswert :
  Pointer auf die Stelle im String "`str1`", an das "`string2`" beginnt,
bzw. NULL-Pointer, wenn der String "`str2`" nicht im String "`str1`" enthalten ist.

    /* -------------------------------------------------------------------- */
    /*         strlen   -    Ermittlung der Länge eines Strings */
    /* -------------------------------------------------------------------- */

    #include <string.h>     /* enthält Funktionsdeklaration */

    size_t strlen(const char *str);
                         /* str    String, dessen Länge ermittelt werden soll */

Anm:
  Der Typ `size_t` ist der "natürliche" unsigned-Typ
(in <string.h> definiert)

"`strlen`" ermittelt die Länge des Strings "`str`" in Anzahl Zeichen (ohne abschließendes '`\0`'-Zeichen)

Funktionswert :
  Länge des Strings "`str`" in Anzahl Zeichen

### Programmbeispiel : Stringfunktionen (2)

    /* ------------------------------------------------------------------ */
    /* Programm STRDEM4                                                   */
    /* ------------------------------------------------------------------ */
    /* Demonstration von Stringfunktionen der ANSI-C-Standardbibliothek   */
    /* Einlesen, Kopieren und Ermittlung der Laenge eines Strings         */
    /* ------------------------------------------------------------------ */

    #include <stdio.h>
    #include <string.h>

    #define NUL   '\0'
    #define MAXL  80

    void main(void)
    {
      char acEinString[MAXL+1],acAusString[MAXL+1];
      printf("\nEingabestring ? ");
      scanf("%s",acEinString);
      strcpy(acAusString, acEinString);
      printf("\nAusgabestring = %s\n",acAusString);
      printf("Stringlaenge  = %d\n",strlen(acEinString));
    }

    /* ------------------------------------------------------------------ */

Bildschirmausgabe :

    E:\RT\C\VORL>strdem4

    Eingabestring ? Es_ist_immer_noch_schoen

    Ausgabestring = Es_ist_immer_noch_schoen
    Stringlaenge  = 24

### Funktionen der ANSI-C-Standardbibliothek zur Stringbearbeitung

(String-I/O-Funktionen)

    /* -------------------------------------------------------------------- */
    /*        sscanf      -      Formatierte "Eingabe" aus einem String     */
    /*--------------------------------------------------------------------- */

    #include <stdio.h>                /* enthält Funktionsdeklaration */

    int sscanf(char *s, const char *ctrl, ...);

              /* s      String, aus dem "gelesen" wird                         */
              /* ctrl   String zur Festlegung des Eingabeformats               */
              /* ...    weitere Parameter:  Pointer auf Variable,              */
              /*                            die Eingabewerte aufnehmen sollen  */

"`sscanf`" entnimmt die naechsten Zeichen dem durch `s` referierten String, interpretiert sie entsprechend den im Steuerstring "`ctrl`" vorliegenden Typ- und Formatangaben und weist die demgemäss konvertierten Werte den durch ihre Pointer (weitere Parameter !) referierten Variablen zu.
Das Erreichen des String-Endes entspricht dem Erreichen des Dateiendes bei Dateien.

Funktionswert :
  die Anzahl der erfolgreich zugewiesenen Werte
  bzw. EOF (= -1), wenn - vor dem Konvertieren des ersten Wertes - ein Fehler aufgetreten ist.

Aufbau und Bedeutung des Steuerstrings "`ctrl`" wie bei der Funktion `scanf`.

    /* -------------------------------------------------------------------- */
    /*        sprintf      -      Formatierte "Ausgabe" in einen String     */
    /*--------------------------------------------------------------------- */

    #include <stdio.h>                /* enthält Funktionsdeklaration */

    int sprintf(char *s, const char *ctrl, ...);

              /* s      String, in den die "Ausgabe" erfolgt                   */
              /* ctrl   String zur Festlegung des Ausgabeformats               */
              /* ...    weitere Parameter:  Ausgabewerte, Anzahl und Typ ent-  */
              /*                    sprechend Konvertierungszeichen in "ctrl"  */

"`sprintf`" legt die als weitere Parameter übergebenen Werte entsprechend den Formatangaben in "`ctrl`" als Zeichenfolgen in dem durch `s` referierten String ab. Die "Ausgabe" wird mit einem '`\0`'-Character abgeschlossen.

Funktionswert :
  Anzahl der abgelegten Zeichen, ohne abschließenden '`\0`' -Character

Aufbau und Bedeutung des Steuerstrings "`ctrl`" wie bei der Funktion `printf`.

### Programmbeispiel : formatierte Ein-/Ausgabe aus/in einen String

    /* ------------------------------------------------------------------ */
    /* Programm IO_STR                                                    */
    /* ------------------------------------------------------------------ */
    /* Beispiel zur formatierten "Ein-/Ausgabe" aus/in einen String       */
    /* ------------------------------------------------------------------ */

    #include <stdio.h>

    #define ANZ  80

    void main(void)
    {
      char acZahlStr[ANZ+1];
      char acAusStr[ANZ+1];
      char acAusText[]="Produkt      :";
      int iZahl1, iZahl2;

      printf("\n2 int-Zahlen ? ");
      gets(acZahlStr);
      sscanf(acZahlStr, "%d%d", &iZahl1, &iZahl2);  /* "Eingabe" aus String */
      iZahl1=iZahl1*iZahl2;
      sprintf(acAusStr, "%s %d", acAusText, iZahl1); /* "Ausgabe" in String */
      puts(acAusStr);
    }

    /* ------------------------------------------------------------------ */

Bildschirmausgabe :

    E:\RT\C\VORL>io_str

    2 int-Zahlen ? 45 6
    Produkt      : 270

    E:\RT\C\VORL>

## 6.3 Mehrdimensionale Arrays

### Mehrdimensionale Arrays in C

- Elemente von Arrays können wiederum Arrays sein
--> 2-dimensionale Arrays

Beispiel :
  int mat[3][4];

-->
  mat ist ein 3-elementiges Array, dessen Elemente int-Arrays mit jeweils 4 Elementen sind

  1.Index (=3) : Anzahl der Zeilen
2.Index (=4) : Anzahl der Spalten

- Entsprechend obiger Interpretation 2-dimensionaler Arrays erfolgt die Speicherung zeilenweise:

- Analog können auch mehr als 2-dimensionale Arrays definiert werden. Die Speicherung erfolgt immer so, daß sich der letzte Index am häufigsten ändert.
- Ansprechen einer Array-Komponente:
Der Index jeder Dimension ist getrennt in eckigen Klammern anzugeben.

Beispiel : `mat[0][1] = 1;`

- Sind mehrdimensionale Arrays Funktionsparameter, so darf in der Parameterdeklaration die Größenangabe für die 1. Dimension ("Zeile") weggelassen werden.
Die Größenangaben für die übrigen Dimensionen sind dagegen immer notwendig.
z.B. `void invert(int mat[][4])`
- Initialisierung mehrdimensionaler Arrays :

- Angabe von soviel Initialisierungswerten wie Array-Elemente vorhanden sind

Die Größenangabe für die 1.Dimension ("Zeile") darf entfallen.

Die Angabe der Initialisierungswerte kann mit oder ohne Kennzeichnung der Array-Struktur erfolgen.

- Beispiel:

    int mat[][4] = { { 1,  4,  3, -4 },
                     { 2,  0, -3,  1 },
                     { 0, -5,  6,  0 } };

oder

    int mat[][4] = { 1, 4, 3, -4, 2, 0, -3, 1, 0, -5, 6, 0 };

--> Definition und Initialisierung eines 3*4 int-Arrays

- Angabe von weniger Initialisierungswerten als Array-Elemente vorhanden sind

Im allgemeinen sind für alle Dimensionen Größenangaben erforderlich.
Bei Eindeutigkeit über die Arraygröße kann die Größenangabe für die 1.Dimension jedoch weggelassen werden.

Die nicht belegten Elemente werden mit 0 vorbesetzt.

Die Kennzeichnung der Array-Struktur bei den Initialisierungswerten ist notwendig, wenn Elemente "innerhalb" des Arrays durch fehlende Angabe mit 0 initialisiert werden sollen.

Beispiele:

    int mat[3][4] = { { 1,  4,  3, -4 },
                      { 2,  0, -3,  1 } };
                                   oder
    int mat[3][4] = { 1, 4, 3, -4, 2, 0, -3, 1 };

--> | Die letzte Zeile (`mat[2][0] ... mat[2][3]`) wird mit 0 initialisiert.

    int mat[3][4] = { { 1,  4,  3 },
                      { 2,  0, -3 },
                      { 0, -5,  6 } };

--> | Die letzte Spalte (`mat[0][3], mat[1][3], mat[2][3]`) wird mit 0 initialisiert. Die Kennzeichnung der Arraystruktur bei den Initialisierungswerten ist notwendig.

    int mat[3][4] = { 1, 4, 3, -4, 2, 0, -3, 1, 0, -5 };
                            oder
    int mat[][4]  = { 1, 4, 3, -4, 2, 0, -3, 1, 0, -5 };

--> | Die beiden letzten Elemente der letzten Zeile (`mat[2][2], mat[2][3]`) werden mit 0 initialisiert.

### Programmbeispiel zu 2-dimensionalen Arrays : Matrixaddition

    /* ------------------------------------------------------------------ */
    /* Programm MATADD                                                    */
    /* ------------------------------------------------------------------ */
    /* Demonstrationsprogramm zu 2-dimensionalen Arrays                   */
    /* Matrixaddition                                                     */
    /* ------------------------------------------------------------------ */

    #include <stdio.h>
    #define ZEILEN 3
    #define SPALTEN 4

    float fmat1[][SPALTEN] = {{1.5,  4.1,  3.4, -4.0},
                              {2.2,    0, -3.7,  1.1},
                              {  0, -5.1,  6.6,  0.2}};
    float fmat2[][SPALTEN] = {-1.5, 2.3, 3.7, 2.1, 0.7, 5.5, 3.3, 0,0,0,0,0};

    void mat_add(float mat1[][SPALTEN],
                 float mat2[][SPALTEN],
                 float mat3[][SPALTEN], int anz_zeil)
    {
      int i,j;

      for (i=0; i<anz_zeil; i++)
        for (j=0; j<SPALTEN; j++)
          mat3[i][j]=mat1[i][j]+mat2[i][j];
    }

    void mat_aus(float fmat[][SPALTEN], int anz_zeil)
    {
      int i,j;

      for(i=0; i<anz_zeil; i++)
      { printf("\n{");
        for (j=0; j<SPALTEN; j++)
          printf("%6.2f, ",fmat[i][j]);
        putchar('}');
      }
      putchar('\n');
    }

    void main(void)
    {
      float fmat3[ZEILEN][SPALTEN];

      mat_add(fmat1,fmat2,fmat3,ZEILEN);
      mat_aus(fmat3,ZEILEN);
    }

    /* ------------------------------------------------------------------ */

Bildschirmausgabe :

    E:\RT\C\VORL>matadd

    {  0.00,   6.40,   7.10,  -1.90, }
    {  2.90,   5.50,  -0.40,   1.10, }
    {  0.00,  -5.10,   6.60,   0.20, }

Zum Inhaltsverzeichnis | Zum nächsten Abschnitt

###### Copyright © FH München, FB 04, Prof. Dr. Rainer Thomas
V - PC - 610 - 01 - TH - 05
V - PC - 610 - 02 - TH - 01
V - PC - 611 - 01 - TH - 03
V - PC - 611 - 02 - TH - 07
V - PC - 612 - 00 - TH - 05
V - PC - 613 - 00 - TH - 05
V - PC - 614 - 00 - TH - 07
V - PC - 620 - 00 - TH - 03
V - PC - 621 - 00 - TH - 04
V - PC - 622 - 00 - TH - 05
V - PC - 623 - 00 - TH - 06
V - PC - 624 - 01 - TH - 03
V - PC - 624 - 02 - TH - 05
V - PC - 624 - 03 - TH - 06
V - PC - 625 - 00 - TH - 03
V - PC - 626 - 00 - TH - 02
V - PC - 627 - 00 - TH - 02
V - PC - 630 - 00 - TH - 03
V - PC - 631 - 00 - TH - 03
V - PC - 632 - 00 - TH - 06