# [C] EOF-Zeichen in char-Array



## myhonor (25. November 2009)

ich will eine Datei einlesen und in einem Array speichern (mit Speicherreservierung). Das Problem ist, dass das Programm mein EOF-Zeichen (&yuml; in html) ins letzte Array mitspeichert. Wie kann ich das verhindern?

mfg myhonor


----------



## Vereth (25. November 2009)

Das klingt wie ein Programmierfehler. Bist du sicher, dass du nach dem Dateiende auch mit dem Einlesen/Verarbeiten aufhörst? Poste doch einfach mal deinen Code.


----------



## deepthroat (25. November 2009)

Hi.





myhonor hat gesagt.:


> ich will eine Datei einlesen und in einem Array speichern (mit Speicherreservierung). Das Problem ist, dass das Programm mein EOF-Zeichen (&yuml; in html) ins letzte Array mitspeichert. Wie kann ich das verhindern?


Indem du das Programm änderst. ;-]

Gruß


----------



## myhonor (25. November 2009)

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

int main(void)
{
char *input;
	char INPUT;
	char *m_input = NULL;
	int input_counter = 0;
	int b = 0;
	int c = 0;

	input = malloc(sizeof(char));
	m_input = malloc(10 * sizeof(char));

	while ((*input=getchar()) != EOF)
	{
		INPUT=*input;
		switch(*input)
		{
		case '@':
			{
				if (m_input == NULL)
				{
					m_input = realloc(m_input, 7 * sizeof(char));
				}
				m_input[b++] = ' ';
				m_input[b++] = '[';
				m_input[b++] = 'a';
				m_input[b++] = 't';
				m_input[b++] = ']';
				m_input[b++] = ' ';
			} break;
		default:
			{
				if (m_input == NULL)
				{
					m_input = realloc(m_input, 2 * sizeof(char));
				}

				m_input[b] = *input;
				b++;
			}
		}
		putchar(INPUT);
		input_counter++;					
	}

	printf("\n----------\n");
	int i;
	for (i=0;i<=b;i++)
	{
		printf("b(%d) =\t%p\t%c\n", i, &m_input[i], m_input[i]);
	}

	free(input);
	free(m_input);
	
	return EXIT_SUCCESS;
}
```

Ich glaub mit der dynamischen Speicherreservierung stimmt auch was nicht.


----------



## deepthroat (25. November 2009)

Warum allozierst du Speicher für ein einzelnes (bzw. 10) Zeichen dynamisch? Das macht nicht viel Sinn.

Außerdem liefert die Funktion getchar einen int zurück!


```
int input;

while ((input = getchar()) != EOF) {
  switch (input) {
     ...
  }
}
```

Und warum prüfst du ständig ob m_input NULL ist? Du mußt schon irgendwie prüfen ob m_input genug Platz hat und wenn nicht realloc aufrufen (dazu mußt du dir natürlich erstmal merken wieviel Speicher gerade alloziert ist).

Bei der Ausgabe hast du einen Off-By-One Fehler

```
for (i = 0; i < b; ++i) {
   ...
}
```
Gruß


----------



## myhonor (25. November 2009)

Ok, danke für den Hinweis mit int, aber wie kann ich ein int in einen char übertragen? muss ich es casten? mit pointern soll das angeblich ne heikle angelegenheit sein.


----------



## deepthroat (25. November 2009)

myhonor hat gesagt.:


> Ok, danke für den Hinweis mit int, aber wie kann ich ein int in einen char übertragen? muss ich es casten?


Nein, ein int wird automatisch zu einem char umgewandelt wenn nötig.


----------



## myhonor (25. November 2009)

Ich hab jetzt zusätlich folgendes hingeschrieben:


```
#define MAX 10
int s_max = MAX;                                                // s_max = Speicher Max (10)
m_input = malloc (s_max*sizeof(char);        // reservier 10 Bytes
s_max += s_max;                                              // bei if (m_input == NULL)
```


----------



## deepthroat (25. November 2009)

myhonor hat gesagt.:


> Ich hab jetzt zusätlich folgendes hingeschrieben:
> 
> 
> ```
> ...


Nochmal: wie sollte m_input denn plötzlich NULL sein?

Die Bedingung müßte so aussehen:

```
if ((s_max - b) < anzahl_benoetigte_zeichen) {
  // reallozieren falls der Speicher nicht ausreicht.
  ...
}
```
Übrigens wäre es sinnvoller den Speicher nicht jedesmal zu re-allozieren, sondern z.B. gleich immer um 500 Zeichen zu erhöhen.

Gruß


----------



## myhonor (25. November 2009)

> Übrigens wäre es sinnvoller den Speicher nicht jedesmal zu re-allozieren, sondern z.B. gleich immer um 500 Zeichen zu erhöhen.
> 
> Gruß



Es ist ein beliebig langer Text in einem txt-File gelesen. Haben ein Testfile bekommen, aber das hat keine 300 Zeichen. Außerdem ist es verlangt, jedes Mal den Speicher neu zu allozieren, damit kein Speicher verschwendet wird.


----------



## deepthroat (25. November 2009)

myhonor hat gesagt.:


> Es ist ein beliebig langer Text in einem txt-File gelesen. Haben ein Testfile bekommen, aber das hat keine 300 Zeichen. Außerdem ist es verlangt, jedes Mal den Speicher neu zu allozieren, damit kein Speicher verschwendet wird.


Dann brauchst du aber keine Abfrage, denn dann ist dein Speicher immer zu klein. Du mußt aber den Speicher summieren. Und warum allozierst du dann gleich am Anfang 10 Zeichen, wenn du doch keinen Speicher verschwenden sollst?

```
size_t memsize = 0;
char* input = NULL;

while (...) {
  memsize += zusaetzliche_groesse;
  input = realloc(input, memsize * sizeof(*input));
}
free (input);
```

PS: Und es ist nicht notwendig jedesmal 1 Zeichen mehr zu allozieren als benötigt wird.


----------



## myhonor (25. November 2009)

hab ich wieder rückgängig gemacht mit den 10 Bytes zu beginn.

Aber irgendwie mag er mein realloc nicht, er spuckt immer die Meldung "invalid next size" aus


```
if ((b-6) >= s_max)
{
	s_max += 6;
	m_input = realloc(m_input,s_max*sizeof(*m_input));
	if (m_input == NULL)
	{
		printf("Kein Speicher mehr da!");
		return EXIT_FAILURE;
	}
}
```


----------



## deepthroat (25. November 2009)

myhonor hat gesagt.:


> hab ich wieder rückgängig gemacht mit den 10 Bytes zu beginn.
> 
> Aber irgendwie mag er mein realloc nicht, er spuckt immer die Meldung "invalid next size" aus


Und welchen Wert hat s_max in diesem Fall? Verwende den Debugger. Ansonsten ist das zu wenig Kontext um den Fehler eingrenzen zu können.



myhonor hat gesagt.:


> ```
> if ((b-6) >= s_max)
> ```


Du hast die Bedingung falsch umgeformt.

```
if ((b+6) > s_max)
```
Aber wie gesagt brauchst du die Bedingung auch nicht, da du ja jedesmal realloc aufrufen willst/mußt.


----------



## Many0815 (25. November 2009)

also hab ich das jez richtig verstanden?
es wird ein beliebig langer text eingelesen und du willst dann einen speicher reservieren!?

also wenn ich das richtig verstanden habe, dann kannst du ja im prinzip zuerst schaun wie lang der text ist und dann diesen speicher mit malloc reservieren...


```
#include <malloc.h>

struct text {
char c;
}datei;
...
main()
{
...
datei.c[0] = malloc(sizeof (text));
}
```

Also File einlesen in die Struktur und die größe der Struktur wird dann reserviert...

für den fall dass ich das Problem falsch verstanden habe, schon mal tschuldigung...^^

cheers many


----------



## Vereth (25. November 2009)

Außerdem arbeitest du mit char, und sizeof(char) ist immer 1. Du kannst dir also beim realloc das *sizeof(...) sparen, was den Code auch wieder ein bisschen vereinfacht.


----------



## myhonor (25. November 2009)

Many0815 hat gesagt.:


> ```
> #include <malloc.h>
> 
> struct text {
> ...



Bei mir sind nur 2 Bibliotheken erlaubt: stdio.h und stdlib.h

Und übrigens wird mit mehreren txt-Files gearbeitet, die auf einem Test-Server gespeichert sind und auf die ich nicht zugreifen kann.


----------



## Many0815 (26. November 2009)

1.)
wenn du nicht auf diese datein zugreifen kannst, wie soll man dass dann in ein array speichern bzw. speicher reservieren?
irgendwie muss ich mir die datei ja mal anschaun um zu wissen wie lang ist die...

und 2.)
warum sind nur diese 2 bibliotheken erlaubt?

cheers


----------

