Post by t***@gmail.comhier ist meine Funktion. Sie erhält als Parameter einen
HTML-String (char *s) und soll den normalen Text aus dem HTML
1 void parse_html3(char *s) {
2
3 size_t i, j;
4 char *res = (char*)malloc(strlen(s) + 1);
5
6 for (i = 0, j = 0; i < strlen(s); i++) {
7
8 if (s[i] == '>') {
9
10 while (s[++i] != '<' && s[i] != 0) {
11
12 if (s[i] == '\n')
13 continue;
14 res[j] = s[i];
15 ++j;
16 }
17
18 } // end if
19 } // end for
20
21 printf("%s\n", res);
22 }
Das glaub' ich Dir noch nicht so ganz:
* In Zeile 4 wird dynamischer Speicher angefordert, und am Ende
des Unterprogramms in Zeile 22 wird der letzte existierende
Zeiger darauf (in Variable res) vergessen. Der Speicher
versumpft. Das Programm weiß nicht mehr, dass es ihn gibt.
Also: Gib ihn an die Speicherverwaltung zurück.
Folgendes vor Zeile 22 einfügen:
21.1 free(res); res = NULL;
Die Zuweisung
res = NULL;
ist überflüssig. Nur hat es sich bei fortlaufenden
Programmänderungen schnell, dass man einen Zeiger auf
dynamischen Speicher verwendet, der längst ungültig geworden
ist, indem man den Speicher mit free() freigegeben hat. Diese
Zuweisung sorgt dafür, dass bei eventuell noch folgender
Verwendung des Zeigerwertes in res der Nullzeiger
verwendet wird, was üblicherweise vom Betriebssystem als
Adressierungsfehler erkannt wird.
Falls in Zeile 4 kein Speicher angefordert werden konnte, wird
res ein Nullzeiger, NULL, zugewiesen. Bevor du den
dynamischen Speicher verwendest, solltest Du prüfen, ob Du
überhaupt welchen erhalten hast:
5.1 if (res == NULL) {
5.2 printf("Leider kein Speicher verfuegbar.\n");
5.3 } else {
Dann folgen Zeilen 6 bis 21.1 (der Übersicht halber etwas
eingerückt, weil sie ja Teil des Else‐Zweiges sind):
6 for (i = 0, j = 0; i < strlen(s); i++) {
...
21 printf("%s\n", res);
21.1 free(res); res = NULL;
und Zeile 21.2 (Abschluss des in Zeile 5.4 begonnenen Else‐Teils)
21.2 }
* Der Parameter s (Zeile 1) ist ein Zeiger auf ein *änderbares*
char. Bei folgendem Programmstück
{
const char *testme =
"<HTML><BODY><P>Einmal ist eine Muecke nachts "
"durch den Wald gesummt\n"
"und hat sich etwas zu stechen gesucht.\n"
"Aber sie hat nur das Wiesel gefunden."
"</P></BODY></HTML>";
parse_html3(testme);
}
sollte der Compiler zum Aufruf von parse_html3 zumindest ein
Warning, wenn nicht gar einen Fehler liefern: testme ist ein
Zeiger auf ein String‐Literal und damit auf einen
unveränderbaren (const) Speicherbereich. In der Deklaration
von parse_html3 aber wird es versäumt, zuzusichern, dass
parse_html3 den Speicherbereich, auf den der Parameter s
zeigt, nicht verändert.
Ändere Zeile 1 ab in
1 void parse_html3(const char *s) {
Mit dieser Änderung weiß der Compiler im obigen Aufruf
parse_html3(testme);
zweierlei:
1., dass er das String‐Literal dem Unterprogramm zur
pfleglichen (d.h. nicht verändernden) Behandlung anvertrauen
darf
2., dass irgendeine Zuweisung s[...] = ...; innerhalb von
parse_html3 auf jeden Fall ein Fehler ist.
Die Änderungsvorschläge zusammengefasst:
1 void parse_html3(const char *s) {
2
3 size_t i, j;
4 char *res = (char*)malloc(strlen(s) + 1);
5
5.1 if (res == NULL) {
5.2 printf("Leider kein Speicher verfuegbar.\n");
5.3 } else {
6 for (i = 0, j = 0; i < strlen(s); i++) {
7
8 if (s[i] == '>') {
9
10 while (s[++i] != '<' && s[i] != 0) {
11
12 if (s[i] == '\n')
13 continue;
14 res[j] = s[i];
15 ++j;
16 }
17
18 } // end if
19 } // end for
20
21 printf("%s\n", res);
21.1 free(res); res = NULL;
21.2 }
22 }
* Noch etwas zum selben Verwendungsbeispiel:
(1) Welches Zeichen gibt das Programm im folgenden Ausgabebeispiel
an der Stelle des Fragezeichens aus?
durch den Wald gesummt?und hat sich etwas zu stechen gesucht.
(2) Füge am Anfang des Programms
#include <string.h> /* Für memset() */
ein und zwischen
const char *testme =
"<HTML><BODY><P>Einmal ist eine Muecke nachts "
"durch den Wald gesummt\n"
"und hat sich etwas zu stechen gesucht.\n"
"Aber sie hat nur das Wiesel gefunden."
"</P></BODY></HTML>";
und
parse_html3(testme);
noch den folgenden Teil, der etwas dynamischen Speicher
anfordert, beschreibt und wieder freigibt:
{
size_t size = strlen(testme) + 1 + 2;
/* Speicher für zwei Zeichen mehr (einschließlich der
* Abschluss‐'\0') als für testme[...] gebraucht würde.
*/
char *etwasSpeicher = malloc (size);
if (etwasSpeicher != NULL) {
/* Speicher mit size-1 Xen belegen
*/
memset(etwasSpeicher,'X',size-1);
/* Abschluss‐'\0' setzen
*/
etwasSpeicher[size-1] = '\0';
printf("%s\n", etwasSpeicher);
free(etwasSpeicher);
}
}
Erscheinen in der Ausgabe des Aufrufs
parse_html3(testme);
ein paar X?
--
Bitte in die Adressierung auch meinen |Please put my full name also into
Vor- u. Nachnamen stellen z.B. |the recipient like
Friedhelm Waitzmann <***@example>, (Friedhelm Waitzmann) ***@example,
"Waitzmann, Friedhelm" <***@example>