• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Słowa (dynamiczna alokacja pamięci)

Object Storage Arubacloud
0 głosów
449 wizyt
pytanie zadane 7 maja 2020 w C i C++ przez Hubertius Bywalec (2,970 p.)

Cześć

Rozwiązuje takie oto zadanie polegające na posortowaniu słów:

Napisz program, który pobierze od użytkownika tekst (nie więcej niż 999 znaków), a następnie podzieli go na wyrazy i posortuje je alfabetycznie i wyświetli w oddzielnych liniach, przyjmując za kryterium wynik działania funkcji strcmp.

W przypadku, kiedy nie uda się przydzielić pamięci program powinien wyświetlić komunikat Failed to allocate mamemory i zakończyć działanie z kodem błedu 8, w przypadku kiedy nie będzie żadnych wyrazów w tekście podanym przez użytkownika program powinien wyświetlić komunikat Nothing to show.

W tym celu przygotuj następujące funkcje:

char **split_words(const char *text);
int sort_words(char **words);
void destroy(char **words);
Funkcja sortuje wyrazy w tablicy words alfabetycznie, od A do Z, przy czym duże litery mają wyższy priorytet, pomimo ich mniejszej wartości w tabeli ASCII. Koniec słów jest oznaczony wartością NULL.

int sort_words(char **words);
Parametr words to wskaźnik na tablicę wskaźników na słowa. Ostatnim elementem tablicy words jest terminator w postaci wartości NULL. Zatem tablica words w skrajnym przypadku ma jeden element (NULL) i nie przechowuje żadnych słów. Sortowanie należy realizować w miejscu.

Wartość zwracana:

1 - w przypadku błędnych danych wejściowych lub
0 - w przypadku powodzenia.
char **split_words(const char *text);
Funkcja dzieli tekst wprowadzony przez użytkownika na wyrazy (wyraz to ciąg następujących po sobie liter i tylko liter).

Funkcja może zaalokować dokładnie tyle pamięci, ile będzie potrzebne na przechowanie całej tablicy. Koniec danych w tablicy ma być oznaczony wartością NULL.

Wartość zwracana:

NULL - w przypadku przekazania do niej błędnych danych lub niepowodzenia alokacji pamięci,
!=NULL w przypadku sukcesu.
void destroy(char **words);
Funkcja zwalnia pamięć przydzieloną zarówno na tablicę, jak i poszczególne wyrazy.

Przykładowa interakcja z programem -- sukces:

Enter text: A woman has to live her life, or live to repent not having lived it. - D.H. Lawrence⏎
A⏎
D⏎
H⏎
Lawrence⏎
has⏎
having⏎
her⏎
it⏎
life⏎
live⏎
live⏎
lived⏎
not⏎
or⏎
repent⏎
to⏎
to⏎
woman⏎
Przykładowa interakcja z programem -- brak pamięci:

Limit sterty: 1000 bajtów

Enter text: Tempora neque velit ut quaerat dolor tempora. Voluptatem quisquam dolorem quaerat non ut. Magnam dolore neque tempora tempora numquam. Non modi adipisci voluptatem modi dolor consectetur. Quiquia dolore magnam sit porro. Quisquam quiquia eius velit. Aliquam dolorem labore sed eius etincidunt. Dolorem amet est dolorem sit tempora amet quaerat. Quaerat dolorem labore quisquam ut quaerat. Ipsum ut voluptatem etincidunt tempora non. Numquam quaerat aliquam quisquam. Etincidunt quisquam quiquia porro quiquia amet. Quiquia quaerat aliquam modi aliquam tempora dolorem. Est eius eius porro voluptatem labore dolorem quiquia. Etincidunt dolore ipsum tempora ipsum voluptatem. Sed numquam velit tempora tempora. Sed quisquam adipisci magnam sit modi modi. Etincidunt non adipisci eius dolor. Adipisci modi quaerat eius dolorem quiquia sed. Quisquam ipsum ut magnam ut numquam numquam velit. Porro porro adipisci aliquam neque aliquam. Labore magnam voluptatem etincidunt est neque. Dolore quisquam velit quiquia neque velit velit dolorem. Tempora labore non amet quiquia dolorem quaerat modi. Porro quiquia magnam dolor sit aliquam. Aliquam est magnam consectetur magnam numquam dolorem. Tempora magnam adipisci magnam aliquam neque. Sit dolor dolorem magnam. Velit numquam quisquam magnam sed. Porro ipsum velit magnam quiquia voluptatem quiquia modi. Ipsum porro magnam velit velit sed quaerat dolor. Sit sed dolorem eius consectetur eius sit velit. Tempora dolor sed amet. Ut sed velit est quiquia ut. Numquam ut non velit non. Porro ut sit est est non porro etincidunt. Sit porro quaerat sit etincidunt eius magnam. Sed etincidunt dolor est. Ipsum tempora est quaerat sit. Quisquam numquam consectetur consectetur dolore. Quisquam sit amet non dolor ut velit velit. Quaerat quisquam numquam amet velit. Dolorem tempora quiquia tempora. Dolor adipisci quisquam consectetur. Quaerat non adipisci sit. Etincidunt amet voluptatem sed ipsum non tempora ut. Eius velit dolore quisquam neque. Eius quisquam velit amet dolore quiquia. Amet aliquam ut dolor amet quisquam. Velit dolore modi modi. Aliquam velit quaerat dolorem. Etincidunt ut numquam consectetur. Velit quiquia sed velit. Numquam quiquia eius magnam. Neque dolore sit ipsum eius. ⏎
Failed to allocate memory⏎
Uwaga

W programie nie wolno korzystać z operatora [].

Na tą chwilę rozpisałem to w ten sposób:

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


char **split_words(const char *text);
int sort_words(char **words);
void destroy(char **words);



int main()
{
    int for_text = 1000;
    char * text = (char *) malloc(sizeof(char) * 1000 );
    if( text == NULL )
    {
        printf("Failed to allocate memory");
        return 8;
    }
    printf("Enter text: ");
    scanf(" %999[^\n]",text); // pobiera 999 znaków bez enter-a, jeżeli będzie 999 to je pobierze, a na 1000 indeksie tablicy wstawi '\0'
    //printf("\n%d\n",strlen(text));
    int i = 0;
    int count = 0;
    while( *(text + i) != '\0' )
    {
        if( *(text + i)>=65 && *(text + i)<=90 )
        {
            count++;
        }
        else if( *(text + i)>=97 && *(text + i)<=122 )
        {
            count++;
        }
        i++;
    }
    if( count == 0 )
    {
        printf("Nothing to show");
        return 0;
    }
    char ** split;
    split = split_words(text);
    if( split == NULL )
    {
        free(text);
        printf("Failed to allocate memory");
        return 8;
    }
    return 0;
}

char **split_words(const char *text)
{
    if( text == NULL || strlen(text) == 0 )
    {
        return NULL;
    }


}

int sort_words(char **words)
{
   if( words == NULL )
   {
       return 1;
   }
   char *swapp_word;
   int i = 0;
   int j = 0;
   while( *(words + i) != NULL )
   {
       j = 0;
       while( *(words + j + 1) != NULL )
       {
           if( strcmp(*(words + j),*(words + j + 1)) > 0 ) //women większe od A, B  większe od A itd. itd.
           {
               swapp_word = *(words + j);
               *(words + j) = *(words + j + 1);
               *(words + j + 1) = swapp_word;
           }
           j++;
       }
       i++;
   }

   return 0;
}

void destroy(char **words)
{
    if( words == NULL )
    {
        return;
    }
    else
    {
        unsigned int i = 0;
        while( *(words + i) != NULL )
        {
               free( *(words + i) );
               i++;
        }
        free(words);
    }
}

Największy problem mam na chwilę obecną z funkcją split_words. Wiem, że zwraca wskaźnik na tablicę dwuwymiarową, gdzie każdy jej wiersz to będzie poszczególny wyraz. Musiałbym więc zadbać o to, aby przeczesywać po kolei tablicę text w poszukiwaniu wyrazów do momentu natrafienia na '\0' i każdy z nich zapisywać do tablicy wynikowej. O ile rozumiem koncept to chyba nie do końca jestem pewny jak mogę to zrobić i dlatego proszę was o pomoc w związku z tą funkcją. Z góry dziękuję za wszelką pomoc w wyjaśnieniu teorii (ponieważ to dopiero moje drugie de facto zadanie ze wskaźników połączonych z alokacją i tablicami wielowymiarowymi, a także samego rozpisania kodu.

P.S  Użytkownik ma maksymalnie pobrać 999 znaków. Dlatego zrobiłem alokację na 1000, by pobierać 999 znaków, a 1000 był dla znaku '\0'. Jednak dla przykładu z samego dołu jest tam... ponad 2000 znaków. Być może powinienem zrobić alokację na znacznie większą liczbę znaków (powiedzmy 2500) i sprawdzać za pomocą funkcji strlen, czy nie jest więcej niż 999 znaków. Jeśli by tak było, pobrałbym poprawnie cały tekst od użytkownika, ale zakończyłbym działanie z kodem błędu 8 i informacją o "Failed to allocate memory". Jak sądzicie, to dobry trop?

1 odpowiedź

+1 głos
odpowiedź 8 maja 2020 przez j23 Mędrzec (194,920 p.)
char **split_words(const char *text)
{
    char **words = malloc(sizeof(char*));
    size_t n_words = 0;
    const char* p1 = text;
    const char* p2 = p1;
    
    while(*p1) {
        while (*p1 && !isalpha(*p1)) ++p1;
        p2 = p1;
        while (*p2 && isalpha(*p2)) ++p2;

        size_t n = (p2 - p1);
        char* w = strncpy(malloc(n + 1), p1, n);
        w[n] = 0;
        
        words = realloc(words, sizeof(char*) * (n_words + 1 + 1));
        words[n_words++] = w;
        
        p1 = p2;
    }
    
    words[n_words] = NULL;
    return words;
}

 

Podobne pytania

0 głosów
1 odpowiedź 287 wizyt
pytanie zadane 7 kwietnia 2023 w C i C++ przez Zuzan Początkujący (390 p.)
0 głosów
1 odpowiedź 430 wizyt
pytanie zadane 23 kwietnia 2020 w C i C++ przez monterek4444 Początkujący (350 p.)
0 głosów
1 odpowiedź 258 wizyt

92,655 zapytań

141,544 odpowiedzi

319,962 komentarzy

62,024 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...