Code: Alles auswählen
int main()
{
char *y = NULL;
printf("%s",y); /**geht**/
char *i = "Hallo";
strcpy(i, NULL);
printf("%s",i); /**gehtnicht**/
}
THX
Code: Alles auswählen
int main()
{
char *y = NULL;
printf("%s",y); /**geht**/
char *i = "Hallo";
strcpy(i, NULL);
printf("%s",i); /**gehtnicht**/
}
Code: Alles auswählen
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <windows.h>
// Wandelt einen gegebenen String in Großbuchstaben um.
void toUpperString(char *str)
{
int i = 0;
while (str[i])
{
putchar(toupper(str[i]));
i++;
}
}
// Wandelt einen gegebenen String in Kleinbuchstaben um.
void toLowerString(char *str)
{
int i = 0;
while (str[i])
{
putchar(tolower(str[i]));
i++;
}
}
// Wandelt Groß- in Kleinbuchstaben um und umgekehrt.
void toInverseString(char *str)
{
int i = 0;
while (str[i])
{
if (isupper(str[i]))
{
putchar(tolower(str[i]));
}
else
{
putchar(toupper(str[i]));
}
i++;
}
}
/** Konvertiert einen String sicher mittels einer gegebenen
Funktion. Ist der String str NULL, wird eine Fehlermeldung ausgegeben.
Ansonsten wird der String ausgegeben, mittels der gegebenen Funktion
konvertiert und dann wird der String ausgegeben.**/
void safeStringConverter(char* str, void (*conversionFunc)(char*))
{
if (str == NULL)
{
printf("FEHLER");
return;
}
else
{
printf("Stringname: %s\n",str);
}
if (conversionFunc == toUpperString)
{
toUpperString(str);
}
else if (conversionFunc == toLowerString)
{
toLowerString(str);
}
else if (conversionFunc == toInverseString)
{
toInverseString(str);
}
else
{
printf("FEHLER, Funktion nicht gefunden!");
return;
}
}
// Hauptprogramm
int main(int argc, const char * argv[])
{
char s[64];
printf("----------------------------------\n");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),4);
printf("Test(1) toUpperString:\n");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),15);
strcpy(s, "Ich muss noch wachsen");
safeStringConverter(s, toUpperString);
printf("\n----------------------------------\n\n");
printf("----------------------------------\n");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),4);
printf("Test(2) toLowerString:\n");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),15);
strcpy(s, "HILFE ICH BIN ZU GROSS");
safeStringConverter(s, toLowerString);
printf("\n----------------------------------\n\n");
printf("----------------------------------\n");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),4);
printf("Test(3) toInverseString:\n");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),15);
strcpy(s, "TAUSCHE mich");
safeStringConverter(s, toInverseString);
printf("\n----------------------------------\n\n");
printf("----------------------------------\n");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),4);
printf("FEHLERPARAMTER TEST: \n");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),15);
strcpy(s,NULL);
safeStringConverter(s, toUpperString);
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),15);
return EXIT_SUCCESS;
}
Die printf()-Ausgabe scheitert nicht, sondern strcpy(). Du übergibst NULL als Quell-String für den Kopiervorgang. Die Funktion versucht an dieser Stelle Daten zu lesen und das Programm stürzt ab.powerschaf hat geschrieben:Warum scheitert die printf() Ausgabe hier?Code: Alles auswählen
strcpy(i, NULL);
Code: Alles auswählen
$ valgrind ./a.out
[...]
==2901== Invalid read of size 1
==2901== at 0x4F7D260: __strcpy_ssse3 (in /usr/lib/libc-2.26.so)
==2901== by 0x1086DD: main (in /tmp/a.out)
==2901== Address 0x0 is not stack'd, malloc'd or (recently) free'd
[...]
Wozu soll das gut sein? Wenn Du nur *genau die* Stringkonvertierungen zulassen willst, macht es keinen Sinn, einen Funktionszeiger zu übergeben (der ist ja gerade dazu gedacht, eine Funktion aufrufen zu können, an die beim Entwurf noch nicht gedacht war). Wenn das also eingeschränkt sein soll, wäre so was hier m.E. besser:powerschaf hat geschrieben:Code: Alles auswählen
... if (conversionFunc == toUpperString) { toUpperString(str); } else if (conversionFunc == toLowerString) { toLowerString(str); } else if (conversionFunc == toInverseString) { toInverseString(str); } else { printf("FEHLER, Funktion nicht gefunden!"); return; }
Code: Alles auswählen
enum conversion { TOUPPER, TOLOWER, TOINVERSE } cv;
void safeStringConverter(char* str, enum conversion cv)
{
switch (cv)
{
case TOUPPER:
toUpperStr(str);
break;
case TOLOWER:
toLowerStr(str);
break;
....
}
}
Code: Alles auswählen
if (conversionFunc)
(*conversionFunc)(str);