Funkcja zwracająca stringa

0

Witam
Piszę funkcję, która ma pobrać imię użytkownika(np. JOHN) i zwrócić stringa w postaci "Hello, John!". Jeśli string imię jest pusty ma zwrócić "Hello, world!"Poniżej wklejam kod i nie wiem gdzie jest błąd bo serwer wyrzuca mi błąd free(): invalid pointer.

#include <stdlib.h>

char *hello(const char *name) {
  int i;
	if (name=="")
		return "Hello, World!";
	char *tmp = (char*)malloc(sizeof(char)*strlen(name));
  char *result=(char*)malloc(sizeof(char)*200);
  tmp[0]=toupper(name[0]);
  for(i=1;i<strlen(name);i++)
    tmp[i]=tolower(name[i]);
 tmp[i]='\0';
  sprintf(result,"Hello, %s!",tmp);
  return result;
}
3

(name=="") tak się nie porównuje stringów w C - użyj strcmp

for(i=1;i<strlen(name);i++)
    tmp[i]=tolower(name[i]);

użyj strcpy

całość generalnie można sprowadzić do:

char* hello(const char* name)
{
    if(!name || !*name)
        name = "World";
    char* result = malloc(strlen(name) + sizeof("Hello, "));
    sprintf(result, "Hello, %c%s", toupper(name[0]), name+1);
    return result;
}

Co do invalid free to ciekawe, bo akurat takiego błędu bym się nie spodziewał.

4
gonskabalbinka napisał(a):

Witam
Piszę funkcję, która ma pobrać imię użytkownika(np. JOHN) i zwrócić stringa w postaci "Hello, John!". Jeśli string imię jest pusty ma zwrócić "Hello, world!"Poniżej wklejam kod i nie wiem gdzie jest błąd bo serwer wyrzuca mi błąd free(): invalid pointer.

#include <stdlib.h>

char *hello(const char *name) {
  int i;
	if (name=="")
		return "Hello, World!";
	char *tmp = (char*)malloc(sizeof(char)*strlen(name));
  char *result=(char*)malloc(sizeof(char)*200);
  tmp[0]=toupper(name[0]);
  for(i=1;i<strlen(name);i++)
    tmp[i]=tolower(name[i]);
 tmp[i]='\0';
  sprintf(result,"Hello, %s!",tmp);
  return result;
}

masz wyciek(i) pamięci

  • z zaniedbania tmp powinieneś zwolnić, ale tego nie robisz (a mógłbyś)
  • drugi problem jest o wiele bardziej istotny i złożony. Nie możesz zwolnić result, bo zwracasz do miejsca wywołania.
    Wniosek: wywołujący powinien wykorzystać i zwolnić.
    Ale wtedy kaszana się robi z return "Hello, World!"; skądże wywołującemu wiedzieć, ze tym razem nie jest to alokowana tablica, tylko stały string. Jest to poważny UB, który kopnie w pupę z opóźnieniem
    ten problem jest typowy dla podobnych funkcji C, jest to jedna ze słabości tego języka, i wymaga dobrego określenia (dokumentacji) jak używać funkcję ("funkcja zwraca nowo alokowaną tablicę, którą należy zwolnić"), i zdyscyplinowanego programisty, który będzie jej posłuszny. Niestety, w C nie ma stosownych "bezpieczników", tylko człowiek.
2
AnyKtokolwiek napisał(a):

Ale wtedy kaszana się robi z return "Hello, World!"; skądże wywołującemu wiedzieć, ze tym razem nie jest to alokowana tablica, tylko stały string.

W takich przypadkach, dokumentacja (khe, khe) powinna jasno mówić, że obiekt zwracany przez funkcję Foo() ma być zwalniany funkcją free() czy jakimś innym DeleteFoo() – a Foo() wtedy musi zawsze zwracać obiekt zwalnialny tą funkcją. Czyli nie może raz robić return "Hello, world", a za innym razem używać malloc.

ten problem jest typowy dla podobnych funkcji C, jest to jedna ze słabości tego języka, i wymaga dobrego określenia (dokumentacji) jak używać funkcję > ("funkcja zwraca nowo alokowaną tablicę, którą należy zwolnić"), i zdyscyplinowanego programisty, który będzie jej posłuszny.

Za to zachęca do czytania dokumentacji, a nie tylko listy metod pod ctrl+spacja :)

Przykład takiej dokumentacji - funkcja GetDC() z WinAPI. W sekcji Remarks napisano kiedy trzeba (a kiedy nie) użyć ReleaseDC:
https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdc

After painting with a common DC, the ReleaseDC function must be called to release the DC.
Class and private DCs do not have to be released. ReleaseDC must be called from the same thread that called GetDC.
The number of DCs is limited only by available memory.

1

Poza juz wymienionymi błędami, jest tu też overflow, bo nigdzie nie ma sprawdzenia czy aby na pewno cała wiadomość nie będzie dłuższa niż ten 200 znakowy bufor. Rozmiar bufora result powinien mieć strlen(name)+strlen("Hello, !")+1 a nie jakieś losowo dobrane 200. Tak jak zresztą pokazał kq w swoim poście.

0

Dzięki za odpowiedzi i uwagi

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.