# Zeichen mit der Konsole einlesen.



## Scal (10. November 2013)

Hallo alle zusammen,

ich bin gerade dabei C zu erlernen und habe so meine Schwierigkeiten. Ich habe mir super Bücher besorgt die mir eine super Basis verschaffen jedoch brauche ich eure Hilfe bitte.

Ich versuche gerade Zeichen durch die Konsole einlesen zu lassen. Was ich dabei unbedingt möchte ist ein dynamischer Speicher. Danach würde ich das ganze gerne wieder ausgeben lassen. Die Eingabe soll auch durch ein text file erfolgen können. Nun ja, ich weiß das ich dafür Strings benötige und wahrscheinlich auch Pointer. Ich weiß außerdem das ich mit fgetc(stdin) != EOF alle Zeichen einlesen kann.

Was ich nun nicht weiß wie ich mir die Zeichen merken kann bzw. diese normal oder verkehrt ausgeben kann?

Danke für eure Hilfe.

liebe Grüße,
Alex


----------



## Jennesta (10. November 2013)

Hallo Alex,

erstmal willkommen hier im Forum.

Dein Problem hört sich sehr ähnlich (gefühlt dieselbe Aufgabe), nach diesem aus einem Thread von vor ein paar Tagen an.

Schau dir doch mal an, ob dies nicht dein Problem bereits löst. Ansonsten poste einmal deinen Code, den du bereits geschrieben hast um das Problem zu lösen, dann kann man dir gezielter helfen.

Beste Grüße,
Jennesta


----------



## sheel (10. November 2013)

Hi

falls das die Sache nicht klärt:

Noch einmal sicherheitshalber nachgefragt: C oder C++?

Von der Tastatur wird ja vermutlich eine Zeile eingelesen.
Wenn aus einer Datei gelesen wird, solls dann auch die erste Zeile sein oder die ganze Datei?
Oder generell mehrere Zeilen?

Ist die Pipe-Verwendung möglich/erlaubt/erwünscht?
(also die Sache mit <, wo man nicht Tastatur- und Dateivariante beide programmieren muss,
aber dafür das Programm auf eine spezielle Art startet)


----------



## saftmeister (11. November 2013)

Ich lass mal den Code für sich sprechen, habe versucht alle Schritte kurz zu dokumentieren:


```
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <ctype.h>


int main (int argc, char **argv)
{
	// Um ein Zeichen zu lesen
	char in;
	// Character-Pointer zum Ablegen der Zeichen
	char *string;
	// Aktuelle Position merken
	int pos = 0;
	// Helfer fuer realloc
	char *tmp;
	// Laenge des Strings
	int current_size = 10;

	// Speicher allokieren
	string = (char*)malloc( current_size );
	// Fehlerbehandlung
	if( !string )
	{
		perror( "malloc" );
	}
	// String leeren
	memset( string, 0, current_size );
	// Wiederholen
	while(1)
	{
		// Pruefen, ob der Puffer noch gross genug ist
		if( strlen( string ) + 1 == current_size )
		{
			// Speicher neu allokieren, manpage von realloc beachten
			tmp = realloc(string, ++current_size);
			// Fehlerbehandlung
			if( !tmp )
			{
				free( string );
				perror( "realloc" );
			}
			// Alles klar, String-Pointer umbiegen
			string = tmp;
		}
		// Zeichen von der Tastatur (stdin) einlesen
		in = getc( stdin );
		// Wenn es ein Buchstabe ist
		if( isalpha( in ) )
		{
			// Im String ablegen
			string[pos++] = in;
			// String Null-terminieren
			string[pos] = 0;
		}
		else
		{
			// Ansonsten aufhoeren
			break;
		}
	}
	// Zum Testen ausgeben
	printf("\nString: %s\n", string);
	// Speicher frei geben
	free(string);

	return 0;
}
```


----------



## Scal (11. November 2013)

Hallo,

erstmals danke für die raschen Antworten. Ich habe den anderen Thread bereits gelesen, er ist ähnlich zu meinem Problem jedoch nicht gleich. Das was mich noch mit dem anderen Thread verbindet sind die erlaubten Bibliotheken, nämlich nur stdio und stdlib leider. 

@Sheel Es handelt sich um ein "C" Programm. 

Grundsätzlich beginne ich doch damit die Zeichen einzulesen durch die Konsole:

int getchar(void); müsste doch z.B. Zeichen einlesen oder?
Dann müsste ich diese Zeichen ja noch irgendwo ablegen oder und ebenfalls einen Pointer anlegen der mir immer auf die letzte Stelle zeigt oder? 

Mir ist noch nicht ganz klar wie die detaillierte Herangehensweise ist. Vielleicht kann mir wer kurz sagen was ich machen muss und ich werd versuchen das bis heute Abend selbständig zu lösen 

Ansonsten wäre ich froh wenn ich dann meinen Code posten dürfte


----------



## cwriter (11. November 2013)

Hallo

Warum getchar() und nicht fgetc(stdin) oder _getch()? getchar() erfordert das Drücken der Entertaste und ist damit für deinen Zweck suboptimal.


> Dann müsste ich diese Zeichen ja noch irgendwo ablegen oder und ebenfalls einen Pointer anlegen der mir immer auf die letzte Stelle zeigt oder?


Der Pointer, der auf die letzte Stelle (des Strings?) zeigt, ist der Pointer vom Speicher plus die Länge des Strings.

Mein Vorschlag: Mache dein Beispiel zuerst mal mit einem statischen char Array (char string[128]; z.B.) und erweitere es dann zur dynamischen Variante.
Da ist der Grundcode folgender (ungestestet):

```
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
    char string[128];
    for(int i = 0;i < 128; i++)
    {
         string[i] = fgetc(stdin);
         if(!isalnum(string[i]))
         {
              break;
          }
    }
    string[i] = 0;
    puts(string);
    _getch();
    return 0;
}
```
Von da aus ist der Lerneffekt meiner Meinung nach am stärksten. Schaue dir Saftmeisters Code an, um einen weiteren Leitfaden zu haben.

Gruss
cwriter


----------



## Scal (11. November 2013)

Hallo,

also ich habe nun lange herumgespielt und komme zu folgendem Code. Jedes mal wenn ich kompiliere bekomme ich den Fehler "Segmentation Fault:11". Ich wollte die Zeichen verkehrt ausgeben, das war also bewusst. Vielleicht kann mir jemand bitte helfen.

lg Alex

```
#include <stdio.h>
#include <stdlib.h>
 
int main ()

{

char* buffer = malloc(50);
int i;
int get = fgetc(stdin);

for ( i=0; get!=EOF; i++)
{
  buffer[i] = get;
  buffer = realloc(buffer, sizeof(char*));    
  
}

char* ausgabe = buffer;

while (i > 0)
{
  printf("%c", ausgabe[i]);
  i--;
  free(ausgabe);
}

}
```


----------



## saftmeister (11. November 2013)

Scal hat gesagt.:


> Das was mich noch mit dem anderen Thread verbindet sind die erlaubten Bibliotheken, nämlich nur stdio und stdlib leider.



Ok, hier mal ein bisschen Klug******erei, aber es trotzdem wichtig, den Unterschied zu verstehen:

Was du da genannt hast, sind keine Bibliotheken sondern Header, also Dateien, die Funktionsprototypen aus der Standard-C-Library definieren. Wenn du nur diese Header verwenden darfst, bedeutet das, dass du nur Funktionen verwenden darfst, die in diesen Headern definiert sind.

Dann will ich mal eine Aufstellung der von mir verwendeten Funktionen machen, zugehörigen Headern und evtl. eine Alternative vorschlagen:


FunktionHeaderAlternativemallocstdlib.hstatische Char-Arraysperrorstdio.h-memsetstring.hSchleife, die alle Elemente auf 0 setztstrlenstring.hMan könnte hier auch die Variable "pos" verwendenreallocstdlib.hstatische Char-Arraysfreestdlib.hstatische Char-Arraysgetcstdio.h-isalphactype.hif-Condition, die alle Werte von 'A' bis 'Z' und 'a' bis 'z' prüftprintfstdio.h-

Dadurch ergibt sich dann bspw. folgender Source:


```
#include <stdio.h>
#include <stdlib.h>

int main (int argc, char **argv)
{
    // Um ein Zeichen zu lesen
    char in;
    // Character-Pointer zum Ablegen der Zeichen
    char *string;
    // Aktuelle Position merken
    int pos = 0;
    // Helfer fuer realloc
    char *tmp;
    // Laenge des Strings
    int current_size = 10;
    // Hilfszaehler
    int i;

    // Speicher allokieren
    string = (char*)malloc( current_size );
    // Fehlerbehandlung
    if( !string )
    {
        perror( "malloc" );
    }
    // String leeren
    for( i = 0; i < current_size; i++ )
    {
    	string[i] = 0;
    }

    // Wiederholen
    while(1)
    {
        // Pruefen, ob der Puffer noch gross genug ist
        if( pos + 1 == current_size )
        {
            // Speicher neu allokieren, manpage von realloc beachten
            tmp = realloc(string, ++current_size);
            // Fehlerbehandlung
            if( !tmp )
            {
                free( string );
                perror( "realloc" );
            }
            // Alles klar, String-Pointer umbiegen
            string = tmp;
        }
        // Zeichen von der Tastatur (stdin) einlesen
        in = getc( stdin );
        // Wenn es ein Buchstabe ist
        if( ('A' <= in && in <= 'Z') || ('a' <= in && in <= 'z') )
        {
            // Im String ablegen
            string[pos++] = in;
            // String Null-terminieren
            string[pos] = 0;
        }
        else
        {
            // Ansonsten aufhoeren
            break;
        }
    }
    // Zum Testen ausgeben
    printf("\nString: %s\n", string);
    // Speicher frei geben
    free(string);

    return 0;
}
```


----------



## cwriter (11. November 2013)

Hallo

Bitte nutze die Codetags [c ] [/ c] (ohne Abstand).

Die Schlaufe

```
for ( i=0; get!=EOF; i++)
```
kann schonmal nicht gut gehen. Du vergrösserst i immer weiter, doch get kann sich nicht verändern, da es nur einmal gesetzt wird, nämlich _vor_ der Schlaufe.
Füge innerhalb der Schlaufe noch ein

```
get = fgetc(stdin);
```
an.
Zudem allozierst du in der realloc-Zeile immer nur 4 bytes (warum eigentlich?). Korrekt wäre

```
buffer = (char*)realloc(buffer, i);
```
Dazu würde aber auch gehören, dass du das "= malloc(50);" ganz oben durch "= NULL;" ersetzt, es sei denn, du wolltest eine weitere Prüfung hinzufügen.

Und warum kopierst du den Pointer buffer in den Pointer ausgabe?

Und am Ende in der while-Schlaufe den buffer ständig zu free'en halte ich auch nicht für eine so gute Idee...

Gruss
cwriter

EDIT:
@saftmeister
Zwar OT, aber IMHO sind statische Arrays nicht wirklich eine Alternative zu ihren dynamischen Konterparts, da sie nicht denselben Zweck erfüllen.


----------



## Scal (11. November 2013)

Meine Schleife rennt doch jetzt so lange bis EOF erreicht ist oder? Und demnach müsste mein "i" die Anzahl der eingelesenen Zeichen widerspiegeln.

Die Ausgabe habe ich deshalb gemacht weil ich auf den anderen Thread aufmerksam geworden bin und mir überlegt habe wie ich denn die Zeichen verkehrt ausgeben könnte. Das müsste doch gehen wenn ich "buffer" übergebe und dann in einer Schleife das "i" wieder runterlaufen lasse oder?

Vielen Dank für die Geduld 


```
#include <stdio.h>
#include <stdlib.h>
 
int main ()

{

char* buffer = NULL;
int i;
int get = 0;


for ( i=0; (get=fgetc(stdin))!=EOF; i++)
{
  buffer[i] = get;
  buffer = (char*)realloc(buffer, i);      
}

char* ausgabe = buffer;

while (i > 0)
{
  printf("%c", ausgabe[i]);
  i--;
  free(ausgabe);
}

}
```


----------



## cwriter (11. November 2013)

Hallo

Uups, da habe ich einen Fehler wiederholt. Entschuldige bitte

```
#include <stdio.h>
#include <stdlib.h>
 
int main ()
{
    char* buffer = NULL;
    int get = 0;
	int i = 0;
 
 
    for (i=0; (get=fgetc(stdin))!=EOF; i++)
    {
      buffer = (char*)realloc(buffer, i+1);     //Muss früher sein, da sonst gar kein Speicher bereitsteht
      buffer[i] = get;
    }
 
    char* ausgabe = buffer;
 
    while (i > 0) //ausgabe[0] willst du ja auch noch haben
    {
      printf("%c", ausgabe[i-1]);
      i--;
     
    }
    free(ausgabe); //Das muss raus aus der while-Schlaufe, sonst wird der Speicher ständig freigegeben, und das willst du nicht
	return 0; //Sonst heult dir der Compiler die Ohren voll
}
```
Ich weiss, ich sollte es selber testen, bin aber gerade zu faul, ein neues Projekt dafür zu erstellen ;-)

Gruss
cwriter

EDIT: Code verbessert


----------



## Scal (11. November 2013)

Jetzt hab ich es verstanden  Schön wenn es im Kopf klick macht. 

Scheint ja hier ein wirklich tolles Forum zu sein, danke an alle******!

Schönen Abend noch


----------



## cwriter (11. November 2013)

Wenn das Thema erledigt ist, drücke bitte noch den blau-weissen Haken, um es als solches zu markieren.

Ansonsten wünsche ich dir ebenfalls einen schönen Abend 

Gruss
cwriter


----------



## Scal (11. November 2013)

Wenn ich theoretisch noch abfragen möchte ob überhaupt noch genug Speicher da ist. Ginge das dann so? Ist mir gerade noch eingefallen.

Danke 


```
for (i=0; (get=fgetc(stdin))!=EOF; i++)
    {
      buffer = (char*)realloc(buffer, i+1);     //Muss früher sein, da sonst gar kein Speicher bereitsteht
      
      if ( buffer == NULL)
        { 
          printf("Out of memory.\n");
          return 1;
        } 
      
      buffer[i] = get;
      printf("%c", buffer [i]);
      
    }
```


----------



## sheel (12. November 2013)

Hi

die Prüfung selbst ist so ok; kann bei *m*alloc auch direkt so eingesetzt werden.
Bei realloc gibt es aber ein kleines "Problem":
Angenommen, es gibt nirgends Fehler,
dann wird der reservierte Speicher ja am Schluss mit free wieder freigegeben.

Wenn zwar die Erstreservierung funktioniert hat, aber dann ein realloc danebengeht,
bedeutet das, dass der Speicher zwar nicht vergrößert wurde, aber:
Der alte unvergrößerte ist noch zum free´n, bevor man das Programm abbricht oÄ.

Ein fehlgeschlagenes realloc erkennt aber aber eben dadurch,
dass es die Variable mit der Adresse mit NULL überschreibt
->man hat die Adresse nicht mehr, die man für free braucht.

Ist etwas "dumm" so (ich hab zwar keine besseren Vorschlag,
wie realloc zu funktionieren hat, aber...naja)
Jedenfalls braucht man wegen diesem Verhalten eine weitere Variable,
die die Adresse noch hat, auch wenn sie in Variable 1 genullt wurde.

Etwa so, folgenden Code durch den Nächsten ersetzen:

```
buffer = (char*)realloc(buffer, i+1);
if ( buffer == NULL)
{ 
    printf("Out of memory.\n");
    return 1;
}
```


```
{
    char *buffer2;
    buffer2 = (char*)realloc(buffer, i+1);
    if ( buffer2 == NULL)
    {
        free(buffer);
        printf("Out of memory.\n");
        return 1;
    }
    buffer = buffer2;
}
```
Die neuen {} um alles herum sind nur, damit die neue Variable buffer2 nach diesem Codeteil
ieder weg ist (und man unabhängig von dem auch andere buffer2 haben kann, wenn man will)
Wenn man irgendeine passende ungebrauchte Variable schon hat
kann man die natürlich auch statt buffer2 verwenden
(und die {} sowie das "char *buffer2;" eben entfernen).


----------



## Scal (12. November 2013)

Hey,

ich versteh das jetzt nicht mehr so wirklich. Hier mein Code den ich jetzt habe:


```
{
  char* buffer = (char *) malloc (MAX * sizeof(char));
  int get = 0;
  int i = 0;
  char* buffer2;
 
   
  for (i=0; (get=fgetc(stdin))!=EOF; i++)
    {
      buffer = (char*)realloc(buffer, i);     //Muss früher sein, da sonst gar kein Speicher bereitsteht
      
      buffer = buffer2;
      buffer2 = (char*)realloc(buffer, i+1);
                
            if ( buffer2 == NULL)
            {
                free(buffer);
                printf("Error:Out of memory.\n");
                return 1;
            }
            
              else {
      buffer[i] = get;
      printf("%c", buffer [i]);
      
      }
    
    }
```


----------



## sheel (12. November 2013)

Du hast den Code nicht richtig reinkopiert...
und das auf Zeile 10 ist komplett sinnlos.


----------



## Scal (12. November 2013)

Sollte nun so passen  oder hab ich was übersehen?


```
#include <stdio.h>
#include <stdlib.h>

#define BLOCK_SIZE 128

#define SUCCESS 0
#define ERROR_NO_MEMORY 1

int main()
{
  int char_counter = 1;
  int block_counter = 1;
  
  // first BLOCK_SIZE bytes
  char *buffer = malloc((block_counter*BLOCK_SIZE) * sizeof(char));
  
  if (buffer == NULL)
    return ERROR_NO_MEMORY;
  
  int character;
  int index = 0;
  while ((character = getchar()) != EOF)
  {
    char_counter++;  // always one larger than actual number of chars
                     // because of the 0-Byte
    
    if ((char_counter % BLOCK_SIZE) == 0)
    {
      // BLOCK_SIZE bytes more
      char *temp = realloc(buffer, (++block_counter*BLOCK_SIZE) * sizeof(char));
    
      if (temp == NULL)
      {
        free(buffer);
        buffer = NULL;
        
        return ERROR_NO_MEMORY;
      }
      
      buffer = temp;
    }
    
    buffer[index++] = character;
  }
  
  buffer[index] = '\0';  // don't forget that
  
  printf("%s\n", buffer);
  
  
  char* ausgabe = buffer;
  
   while (char_counter > 0) //ausgabe[0] will man ja auch noch haben
    {
      printf("%c", ausgabe[char_counter-1]);
      char_counter--;
    }
     printf("\n");
  
  
  free(buffer);
  
  return SUCCESS;
  
}
```


----------



## Caligulaminus (13. November 2013)

Die Multiplikation mit sizeof(char) kannste dir schenken, sizeof(char) ist per Definition 1.


----------



## saftmeister (13. November 2013)

Caligulaminus hat gesagt.:


> Die Multiplikation mit sizeof(char) kannste dir schenken, sizeof(char) ist per Definition 1.



Echt? Mit jedem Compiler? Und auch immer bei Unicode?


----------



## Caligulaminus (13. November 2013)

saftmeister hat gesagt.:


> Caligulaminus hat gesagt.:
> 
> 
> 
> ...



Echt. Der Standard sagt:



			
				n3337-5.3.3.1 hat gesagt.:
			
		

> [..] sizeof(char), sizeof(signed char) and sizeof(unsigned char) are 1.[..]



Edit: Das hat mit Unicode übrigens nichts zu tun. Ein char ist ein char. Ein Unicode code point ist etwas anderes und kann je nach code point, Kodierung und Breite des chars ein oder mehrere chars benötigen.


----------



## saftmeister (13. November 2013)

OT: Dann wundert es mich aber, dass es doch hin und wieder Code gibt, wo mit sizeof(char) multipliziert wird. Wahrscheinlich ist das auch nicht weiter schlimm, der Compiler wird das vermutlich weg optimieren. Ich dachte bis dato, dass es in komischen Konstellationen vorkommen kann, das es eben mal nicht 1 ist. Wieder was dazu gelernt. Aber ob das auch für zukünftige C-Standards gelten wird, steht noch auf einem anderen Blatt. ;-)


----------



## Caligulaminus (13. November 2013)

saftmeister hat gesagt.:


> OT: Dann wundert es mich aber, dass es doch hin und wieder Code gibt, wo mit sizeof(char) multipliziert wird.


Ich find's nicht unbedingt verwunderlich, daß nicht jeder dieses "Detail" kennt. (Gänsefüßchen weil es wirklich fundamental ist.


saftmeister hat gesagt.:


> Wahrscheinlich ist das auch nicht weiter schlimm, der Compiler wird das vermutlich weg optimieren.


Den Compiler will ich sehen, der eine Multiplikation mit eins nicht wegoptimiert.


saftmeister hat gesagt.:


> Ich dachte bis dato, dass es in komischen Konstellationen vorkommen kann, das es eben mal nicht 1 ist.


Das ist im C(++) Universum so fundamental wie die Elementarladung - char *ist* die Elementarladung!


saftmeister hat gesagt.:


> Wieder was dazu gelernt. Aber ob das auch für zukünftige C-Standards gelten wird, steht noch auf einem anderen Blatt. ;-)


sizeof(char) == 1 ist ein Fundament. Wer das ändert schafft eine andere Sprache.


----------



## sheel (13. November 2013)

Für die noch Zweifelnden hier etwas mit Referenzen vom Standard:
http://stackoverflow.com/questions/2215445/are-there-machines-where-sizeofchar-1


----------

