Cześć :)
Wykonuję obecnie takie zdanie:
Napisz program, który pobierze od użytkownika tekst, podzieli go na zdania i wyświetli posortowane rosnąco ze względu na liczby słów w tych zdaniach. Zdania mają być wyświetlone w oddzielnych liniach, ze słowami posortowanymi alfabetycznie, ze względu na wynik funkcji strcmp.
Przykład:
Enter text: "In theory, theory and practice are the same. In practice, they're not." - Yoggi Berra⏎
In not practice re they⏎
In and are practice same the theory theory⏎
W tym celu przygotuj następujące funkcje:
int split_sentences(const char *text, char ****output);
int sort_sentences(char ***output);
void destroy(char ***words);
int split_sentences(const char *text, char ****output);
Funkcja dzieli tekst text na zdania. Zdanie kończy się kropką. Ponadto każde zdanie dzieli na wyrazy. Wyraz to ciąg następujących po sobie liter.
Przykłady:
dwa zdania (Ala oraz Ma): Ala .Ma. Kota
jedno zdanie (kota): kota.
brak zdań: ala ma kota
dwa puste zdania: ..
Koniec tablic zdań oraz wyrazów funkcja ma oznaczyć wartością NULL. Poszczególne wyrazy, jako że są tekstami, kończą się terminatorem '\\x0'
Funkcja może zaalokować dokładnie tyle pamięci, ile będzie potrzebne na przechowanie całej tablicy. Wynik działania funkcji split_sentences ma zostać napisany pod wskaźnik *output. Jeżeli funkcja ma zakończyć się porażką, to powinna ustawić NULL podwskaźnikiem *output* i zwrócić niezerowy kod błędu.
Wartość zwracana:
1 - w przypadku przekazania do funkcji błędnych danych,
2 - w przypadku braku zdań w tekście text,
3 - w przypadku braku pamięci,
0 - w przypadku sukcesu (*output zawiera poprawny wskaźnik).
Interpretacja parametru char ****output:
Poziom znaku - typ char reprezentuje pojedynczy znak.
Poziom słowa - typ wskaźnikowy char* reprezentuje wskaźnik na znak, który w tym przypadku należy interpretować jako wskaźnik na słowo (wskaźnik na pierwszy znak słowa, słowo jest tekstem w języku C i kończy się terminatorem \x0).
Poziom zdania - typ wskaźnikowy char** jest wskaźnikiem na pamięć przechowującą wskaźnik na słowo. W tym przypadku należy interpretować go jako wskaźnik na pamięć przechowującą sekwencję wielu wskaźników na słowa; sam wskaźnik char** wskazuje tylko na pierwsze słowo (wskaźnik do niego). Sekwencja musi kończyć się terminatorem NULL. Zatem zdanie posiadające 5 słów będzie reprezentowane przez sekwencję 6 elementów (ostatni to NULL).
Poziom tekstu - typ wskaźnikowy char***, analogicznie do poprzedniego przykładu, wskazuje na sekwencję wskaźników na zadania. Zatem można go interpretować jako wskaźnik na cały treść/dokument (czyli zbiór zdań). Sekwencja kończy się terminatorem NULL.
Poziom zmiennej przechowującej wskaźnik na treść - typ wskaźnikowy char*** ponownie opisuje wskaźnik do pamięci przechowującej wskaźnik, itd. W tym przypadku należy go interpretować jako adres zmiennej typu char*** w której umieszczony ma być adres pierwszego zdania tekstu wejściowego.
Zatem jeśli przyjmiemy, że zmienna char**** p zawiera poprawny wskaźnik z poprawnie przydzielonymi pamięciami, to odpowiednio:
*p - Adres całej treści podzielonej na zdania i słowa. Typ tego wyrażenia to char***
*(*p + 1) - Adres drugiego zdania w tekście *p (pierwsze ma indeks 0). Typ tego wyrażenia to char**
*(*(*p + 2) + 4) - Piąte słowo z trzeciego tekstu. Typ tego wyrażenia to char*.
*(*(*(*p + 1) + 6) + 8) - Dziewiąty znak z siódmego słowa znajdującego się w drugim wierszu. Typ tego wyrażenia to char.
Natomiast wyrażenie *(p + 1) jest niepoprawne, ponieważ p jest adresem jednej zmiennej (jednego elementu wskaźnikowego). Za tym elementem nie ma nic, co dało by się zinterpretować w kontekście treści/zdań/słów.
int sort_sentences(char ***output);
Funkcja sortuje zdania w output rosnąco pod kątem liczby wyrazów w nich występujących. Ponadto w każdym zdaniu wyrazy należy posortować alfabetycznie od A do Z, przy czym duże litery mają wyższy priorytet, pomimo mniejszej wartości ich kodów tabeli ASCII. Sortowanie należy realizować w miejscu.
Koniec słów w tablicy (zdaniu) jest oznaczony wartością NULL. Koniec zdań w tablicy (output) jest oznaczony wartością NULL.
Wartość zwracana:
1 - w przypadku błędnych danych wejściowych lub
0 w przypadku powodzenia.
void destroy(char ***words);
Funkcja zwalnia pamięć przydzieloną zarówno na tablicę words, jak i poszczególne wyrazy.
Napisz program, który pobierze od użytkownika tekst (nie więcej niż 999 znaków), podzieli go na zdania, każde zdanie podzieli na wyrazy a następnie posortuje zdania rosnąco pod względem liczby wyrazów, a wyrazy w poszczególnych zdaniach alfabetycznie.
Program ma wyświetlić, w oddzielnej linii dla każdego zdania, wyrazy posortowane alfabetycznie począwszy od zdania z najmniejszą liczbą wyrazów.
W przypadku, kiedy nie uda się przydzielić pamięci program powinien wyświetlić komunikat Failed to allocate memory i niezwłocznie zakończyć działanie z kodem błędu 8,
W przypadku kiedy nie będzie żadnych zdań w tekście podanym przez użytkownika program powinien wyświetlić komunikat Nothing to show.
Jeżeli w którymś ze zdań nie będzie wyrazów, program w jego miejsce powinien wyświetlić komunikat Nothing to show i kontynuować.
Przykładowa interakcja z programem -- skrajny przypadek:
Enter text: , . , , . , . . - .Technology is teaching us to be human again.-Simon Mainwaring⏎
Nothing to show⏎
Nothing to show⏎
Nothing to show⏎
Nothing to show⏎
Nothing to show⏎
Technology again be human is teaching to us⏎
Uwaga
- W programie nie wolno korzystać z operatora [].
A oto i mój kod:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
int split_sentences(const char *text, char ****output);
int sort_sentences(char ***output);
void destroy(char ***words);
void print_output(char ***output);
int main()
{
printf("Enter text: ");
char * pointer;
pointer = (char *) malloc (sizeof(char) * 2500 );
if( pointer == NULL )
{
printf("Failed to allocate memory");
return 8;
}
scanf(" %2500[^\n]",pointer);
*(pointer + 999) = '\0';
char *** output;
int result = 0;
result = split_sentences( (const char *) pointer, &output);
if( result == 0 )
{
}
if( result == 2 )
{
printf("Nothing to show");
free(pointer);
return 0;
}
print_output(output);
}
void print_output(char ***output)
{
int i = 0, j = 0;
while( *( output + i) != NULL )
{
j = 0;
while( *(*(output + i) + j) != NULL )
{
printf("%s ",*(*(output + i) + j));
j++;
}
if( j == 0 )
{
printf("Nothing to show");
}
printf("\n");
i++;
}
}
void destroy(char ***words)
{
if( words == NULL )
{
}
else
{
int i = 0, j = 0;
while( *(words + i) != NULL )
{
while( *( *(words + i) + j) != NULL )
{
free(*( *(words + i) + j));
j++;
}
free(*(words + i));
i++;
}
free(words);
}
}
int split_sentences(const char *text, char ****output)
{
if( text == NULL || output == NULL )
{
return 1;
}
int sentences = 0;
int i = strlen(text) - 1; // wskazuje na terminatra
while( *(text + i) == ' ' )
{
i--;
}
int ending = i + 1;
i = 0;
while( *(text + i) == ' ' )
{
i++;
}
int start = i;
while( *(text + i) != '\0' )
{
if( *(text + i) == '.' )
{
sentences++;
}
i++;
}
if( sentences == 0 )
{
return 2;
}
*output = (char ***) malloc(sizeof(char **) * (sentences + 1) );
if( *output == NULL )
{
return 3;
}
*( (*output) + sentences) = NULL;
i = 0;
int j = 0;
int itr = start;
while( *(text + itr ) != '\0' && itr < ending )
{
if( isalpha( *(text + itr ) ) != 0 )
{
while( isalpha( *(text + itr) ) != 0 )
{
itr++;
}
j++;
}
if( *(text + itr) == '.' )
{
*( (*output) + i) = (char **) malloc(sizeof(char *) * (j + 1) );
if( *( (*output) + i ) == NULL ) // błąd alokacji wyrazów dla poszczególnych zdań
{
int get_out = 0;
for(get_out = 0; get_out < i; get_out++)
{
free(*( (*output) + get_out ) );
}
free(*output);
return 3;
}
*(*( (*output) + i ) + j) = NULL;
j = 0;
i++;
}
if( isalpha( *(text + itr ) ) == 0 )
{
itr++;
}
}
itr = start;
i = 0;
j = 0;
int k = 0;
while( *(text + itr) != '\0' && itr < ending ) // alokacja dla liter dla wyrazów
{
if( isalpha(*(text + itr)) != 0 )
{
k = 0;
while( isalpha(*(text + itr)) != 0 )
{
itr++;
k++;
}
*(*( (*output) + i ) + j) = (char *) malloc (sizeof(char) * (k + 1) );
if( *(*( (*output) + i ) + j) == NULL )
{
int get_out_sentences = 0;
int get_out_words = 0;
for(get_out_sentences = 0; get_out_sentences <= i; i++ )
{
for(get_out_words = 0; get_out_words < j; get_out_words++)
{
free( *(*( (*output) + get_out_sentences ) + get_out_words ) );
}
free( *( (*output) + get_out_sentences ) );
}
free( *output );
return 3;
}
j++;
}
if( *(text + itr) == '.' )
{
j = 0;
k = 0;
i++;
}
if( isalpha(*(text + itr)) == 0 )
{
itr++;
}
}
itr = start;
i = 0;
j = 0;
k = 0;
while( *(text + itr) != '\0' && itr < ending )
{
if( isalpha( *(text + itr) ) != 0 )
{
k = 0;
while( isalpha( *(text + itr) ) != 0 )
{
*(*(*( (*output) + i ) + j) + k) = *(text + itr);
k++;
itr++;
}
*(*(*( (*output) + i ) + j) + k) = '\0';
j++;
}
if( *(text + itr) == '.' )
{
j = 0;
k = 0;
i++;
}
if( isalpha( *(text + itr) ) == 0 )
{
itr++;
}
}
return 0;
}
int sort_sentences(char ***output)
{
if( output == NULL )
{
return 1;
}
int i = 0, j = 0;
while( *(output + i) != NULL )
{
while( *(*(output + i) + j + 1) != NULL )
{
if( strcmp( *(*(output + i) + j ) , *(*(output + i) + j + 1) ) > 0 ) //women większe od A, B większe od A itd. itd.
{
char *swapp = *(*(output + i) + j );
*(*(output + i) + j ) = *(*(output + i) + j + 1);
*(*(output + i) + j + 1) = swapp;
}
j++;
}
i++;
}
return 0;
}
Dla poniższych danych efekt bez uwzględnienia sortowania jest następujący:
Enter text: Ala ma kota. Serio. Naprawde. Sto procent legit. No scam.
Ala ma kota
Serio
Naprawde
Sto procent legit
No scam
Process returned 0 (0x0) execution time : 11.138 s
Press any key to continue.
Z czym na tą chwilę mam problem:
1) Nie wiem czemu, ale gdy po ostatnim zdaniu coś piszę (coś co nie powinno być już brane pod uwagę, bo już wszystkie zdania są uwzględnione) dzieje mi się takie coś:
Enter text: . . Serio . Ala
Process returned -1073741819 (0xC0000005) execution time : 10.440 s
Press any key to continue.
albo w ten sposób:
Enter text: Ala ma kota. a
Process returned -1073741819 (0xC0000005) execution time : 6.326 s
Press any key to continue.
Podpowiecie mi czego nie zrobiłem w moim kodzie dla problemu w tym podpunkcie? :(
2) Funkcja sort jest nie dokończona. Na tę chwilę mam tylko sortowanie wyrazów w zdaniu (swoją drogą możecie się wypowiedzieć, czy wszystko na ten czas zrobiłem poprawnie). Jak mogę przeprowadzić sortowanie zdań? Czuję, że pewnie rozwiązanie jest proste i powinno mi stać przed oczami, ale jest już późna godzina i chyba nie zbyt już jasno myślę. :(
Z góry dziękuję za wszelkie odpowiedzi. :)