/* fileupdate.c

Oft wird gefragt, wie man von einer Text-Datei eine bestimmte Zeile lesen kann,
und diese Zeile in veraenderter Form wieder auf die Datei ausgeben kann.
Man kann zwar auch eine Textdatei im Modus r+ oeffnen (das erlaubt lesen und
schreiben auf die Datei), das funktioniert jedoch nur, wenn die einzelnen Zeilen
immer die gleiche Laenge haben. Der r+ Modus wird fuer Textdateien meist nur
verwendet, um am Ende der Datei neue Inhalte anzuhaengen!

Zwei Loesungen sind moeglich:

1) Datei zum Lesen oeffnen
   Die ganze Datei in eine geeignete Datenstruktur lesen.
   Datei schliessen
   Inhalte der Datenstruktur aendern
   Datei zum Schreiben oeffnen
   die Daten wieder auf die Datei schreiben
   Datei schliessen

2) Die Originaldatei (D1) oeffnen (Mode "r")
   eine zweite Datei (D2) oeffnen (Mode "w")
   Fuer alle Zeilen (Datensaetze)
     Zeile aus D1 lesen
     Zeile eventuell veraendern
     Zeile auf D2 schreiben
   Dateien schliessen
   Datei D1 loeschen ( Bibliotheksfunktion: remove )
   Datei D2 auf den Namen von D1 umbenennen ( Bibliotheksfunktion: rename )


Im folgenden ist die Loesung 2 ausgefuehrt!


Beispiel fuer die vom Programm verwendete Datei
mit einem ; als Trennzeichen
-------------------------------------------------
1;Hammer 250 g;60.30
00002;Zange;23
0003;Draht 2 mm; 12.40
0006;Heugabel; 230.50
-------------------------------------------------
*/

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

void datensatz_aendern(unsigned int *nr, char *text, double *preis)
{
  char antwort[10];

  /*
  Der Wechsel zwischen dem Lesen von Zeichenketten und Zahlen erfordert, dass
  jeweils das von der Eingabetaste erzeugte Zeichen aus dem Buffer entfernt wird,
  dafuer sorgt das %*c und das %s im Zusammenhang mit der Zeichenkette antwort !
  Siehe dazu auch die Seiten 102 und 102 im Buch (4. Aufl.)
  */

  printf("\nArtikelNr.   : %-40u Aendern ja/nein ? ", *nr);
  scanf("%s", antwort);
  if (tolower(antwort[0]) == 'j') {
    printf("neue Nummer. : ");
    scanf("%u%*c", nr);
  }

  printf(  "ArtikelBez.  : %-40s Aendern ja/nein ? ", text);
  scanf("%s%*c", antwort);
  if (tolower(antwort[0]) == 'j') {
    printf("neue Bez.    : ");
    gets(text);
  }

  printf(  "ArtikelPreis.: %-40.2f Aendern ja/nein ? ", *preis);
  scanf("%s%*c", antwort);
  if (tolower(antwort[0]) == 'j') {
    printf("neuer Preis  : ");
    scanf("%lf%*c", preis);
  }
  printf("=================================\n");

}  /* end datensatz_aendern */



int main(void)
{
  FILE *fin, *fout;
  char line[100];
  int result;

  unsigned int artikel_nr;       //  fortgeschrittene Programmierer
  char artikel_bezeichnung[40];  //  wuerden diesen Datensatz in
  double artikel_preis;          //  einer Struktur zusammenfassen

  unsigned int ges_artikel_nr;

  if ((fin = fopen("artikel.txt", "r")) == NULL) {
    printf("Datei konnte nicht geoeffnet werden!\n");
    exit(1);
  }

  printf("Gesuchte Artikelnr: ");
  scanf("%u%*c", &ges_artikel_nr);
  printf("-----------------------------------\n");

  fout = fopen("artikelneu.txt", "w");

  while (fgets(line, 100, fin)) {
    /* Zeile durch sscanf zerlegen und zur Kontrolle ausgeben */
    result = sscanf(line, "%u;%[^;];%lf", &artikel_nr, artikel_bezeichnung, &artikel_preis);
    fprintf(stdout, "%08u;%-40s;%8.2f\n", artikel_nr, artikel_bezeichnung, artikel_preis);
    /* Information ausgeben, wenn die Zerlegung nicht erfolgreich war */
    if (result != 3) printf("*** Fehler im letzten Datensatz ***\n");

    if (ges_artikel_nr == artikel_nr) {
      datensatz_aendern(&artikel_nr, artikel_bezeichnung, &artikel_preis);
      /* veraenderten Datensatz auf Datei schreiben */
      fprintf(fout, "%08u;%s;%8.2f\n", artikel_nr, artikel_bezeichnung, artikel_preis);
    }
    else
      /* Datensatz wie gelesen wieder auf Datei schreiben */
      fputs(line, fout);

  } /* end while */

  /* hier koennte man zusaetzliche neue Datensaetze auf fout schreiben */

  fclose(fin);
  fclose(fout);

  /* Nach erfolgreichem Test kann die neue Datei wieder unter dem urspruenglichen
     Namen gespeichert werden */

  remove("artikel.txt");
  rename("artikelneu.txt", "artikel.txt");

  return 0;
}