Zeichen mit der Konsole einlesen.

Scal

Mitglied
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
 
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
 
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)
 
Ich lass mal den Code für sich sprechen, habe versucht alle Schritte kurz zu dokumentieren:

C:
#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;
}
 
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 :)
 
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):
C:
#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
 
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
Code:
#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);
}

}
 
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:

FunktionHeaderAlternative
mallocstdlib.hstatische Char-Arrays
perrorstdio.h-
memsetstring.hSchleife, die alle Elemente auf 0 setzt
strlenstring.hMan könnte hier auch die Variable "pos" verwenden
reallocstdlib.hstatische Char-Arrays
freestdlib.hstatische Char-Arrays
getcstdio.h-
isalphactype.hif-Condition, die alle Werte von 'A' bis 'Z' und 'a' bis 'z' prüft
printfstdio.h-

Dadurch ergibt sich dann bspw. folgender Source:

C:
#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;
}
 
Hallo

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

Die Schlaufe
C:
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
C:
get = fgetc(stdin);
an.
Zudem allozierst du in der realloc-Zeile immer nur 4 bytes (warum eigentlich?). Korrekt wäre
C:
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.
 
Zuletzt bearbeitet:
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 :)

C:
#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);
}

}
 

Neue Beiträge

Zurück