Strona główna » C++ » Zadania » Napisy - zestaw przygotowawczy

Napisy - zestaw przygotowawczy

Zadanie

Oryginalna treść zadania

Rozwiązanie

Omówienie podpunktu 1 - toUpper()

Pisanie funkcji rozpoczynamy od napisania nagłówki funkcji, która z zadania wynika, że przyjmuje napis.

Dodanie znacznika const przed argumentem jest opcjonalne i nie ma większego znaczenia dla działania funkcji, ale pomaga wykryć przez kompilator jakąkolwiek próbę modyfikacji napisu i pokazanie błędu.

  1. char* toUpper(const char* napis){
  2.   const char change = 'A' - 'a';
  3.   char* c = new char[strlen(napis)];
  4.   int i = 0 ;
  5.   while(napis[i]){
  6.     if(napis[i] >= 'a' && napis[i] <= 'z'){
  7.       c[i] = napis[i] + change;
  8.     } else {
  9.       c[i] = napis[i];
  10.     }
  11.     i++;
  12.   }
  13.   c[i] = '\0';
  14.   return c;
  15. }

W zadaniu należy zamienić wszystkie małe litery alfabetu łacińskiego na wielkie. Znaki są to dla komputera liczby, które są odpowiednio wyświetlane, dlatego możemy dodawać i odejmować liczbę do znaku. W zadaniu potrzebujemy znać odległość pomiędzy a i A. Przyjmijmy różnice za x wtedy a + x = A, b + x = B ... (2.) Operację tę wykonujemy na początku. (3.) Następnie tworzymy nowy dynamiczny napis, który będzie naszym wynikiem. (4. - 12.) Teraz musimy przejść po każdym znaku co realizują i (6.) dla każdego znaku sprawdzić czy znak jest mały. (7.) Jeśli tak to go zmieniamy, ale (9.) jeśli nie to tylko przepisujemy. Na koniec (13.) dopisujemy \0 do napisu na ostatnim miejscu i (14.) zwracamy powstały napis.

Omówienie podpunktu 2 - countNumerics()

  1. int countNumerics(const char* napis){
  2.   int licznik = 0;
  3.   int i = 0;
  4.   while(napis[i]){
  5.     if(napis[i] >= '0' && napis[i] <= '9')
  6.       licznik++;
  7.     i++;
  8.   }
  9.   return licznik;
  10. }

W celu zliczenia wszystkich znaków musimy mieć (2.) jakąś zmienną np. licznik, która będzie przechowywać ile cyfr już znaleźliśmy. Oczywiście na początek ustalamy wartość na 0. Następnie (3. - 8.) pętla while pozwoli nam sprawdzić każdy znak po kolei, aż do końca napisu. Wewnątrz (4.) mamy warunek, który sprawdza czy znak jest cyfrą - (5.) jeśli tak jest to zwiększamy licznik. (10.) Po zakończeniu pętli zwracamy ile cyfr znaleźliśmy.

Omówienie podpunktu 3 - joinUsing()

Funkcja przyjmuje trzy argumenty: pierwszy i drugi typu char*, a trzeci char. Zwraca nam natomiast char*:

  1. char* joinUsing(const char* napis, const char* napis2, const char c){
  2.   char* wynik = new char[strlen(napis)+strlen(napis2)+2];
  3.   int j = 0, i = 0 ;
  4.  
  5.   while(napis[i]){
  6.     wynik[j] = napis[i];
  7.     j++;
  8.     i++;
  9.   }
  10.  
  11.   wynik[j]=c;
  12.   j++;
  13.   i=0;
  14.   while(napis2[i]){
  15.     wynik[j] = napis2[i];
  16.     j++;
  17.     i++;
  18.   }
  19.   wynik[j]='\0';
  20.   return wynik;
  21. }

(2.) Na początek alokujemy nowy dynamiczny napis, którego długość to długość napis1 i napis2 + 2. Dodatkowe dwa, ponieważ należy uwzględnić znak końca napisu oraz dodatkowy znak c. Ponieważ będziemy przechodzić po wyniku i w międzyczasie po dwóch innych napisach. W przykładzie j służy do określenia pozycji do napisania w wyniku, a i określa, który znak odczytujemy z podanego napisu. Kolejno (5. - 9.) dopisujemy napis1, (11. - 12.) potem znak c i (14. - 19.) na koniec napis2. Należy zwrócić uwagę na zwiększanie zmiennej j, które następuje po przepisaniu z jakiegokolwiek napisu i po dopisaniu litery c. Na koniec dopisujemy (21.) znak specjalny \0 i (22.) zwracamy wynik.

Omówienie podpunktu 4 - backwards()

Funkcja przyjmuje napis (typ char*) i zwraca napis (char*):

  1. char* backwards(const char* napis){
  2.   int dlugosc = strlen(napis);
  3.   char* c = new char[dlugosc];
  4.   for(int i = 0; i < dlugosc; i++){
  5.     c[dlugosc-i-1]=napis[i];
  6.   }
  7.   c[dlugosc]='\0';
  8.   return c;
  9. }

Zadanie jest bardzo podobne do sprawdzania czy podany napis jest palindromem. W celu przepisania wyrazu musimy znać długość wyniku, który równa się długość napisowi. W celu ułatwienia przepisywania (2.) znajdziemy długość napisu danego. Potem (3.) należy dokonać alokacji nowej przestrzeni w pamięci. Następnie (4. - 6.) zamieniamy pozycję znaków. Pierwszy jest ostatnim itd. W tym celu należy zauważyć, że znak z pozycji 0 znajdzie się na pozycji dlugosc - 1. Na sam koniec pamiętamy (7.) o znaku \0 i (8.) zwróceniu wyniku.

Omówienie podpunktu 5 - Testy

Napisane funkcje można przetestować przy pomocy poniższej funkcji main():

  1. int main () {
  2.   char* napis1 = new char[6];
  3.   napis1[0]='#';napis1[1]='A';napis1[2]='b';napis1[3]='c';napis1[4]='d';napis1[5]='\0';
  4.   char* napis1w = toUpper(napis1);
  5.   cout << "funkcja toUpper()\n dane: " << napis1 << "\nwynik: " << napis1w;
  6.   char* napis2 = new char[7];
  7.   napis2[0]='a';napis2[1]='1';napis2[2]='b';napis2[3]='2';napis2[4]='c';napis2[5]='3';napis2[6]='\0';
  8.   int wynik = countNumerics(napis2);
  9.   cout << "\n\nfunkcja countNumerics()\n dane: " << napis2 << "\nwynik: " << wynik;
  10.   char* napis3a = new char[4];
  11.   napis3a[0]='4';napis3a[1]='5';napis3a[2]='6';napis3a[3]='\0';
  12.   char* napis3b = new char[3];
  13.   napis3b[0]='2';napis3b[1]='b';napis3b[2]='\0';
  14.   char c = '-';
  15.   char* napis3w = joinUsing(napis3a, napis3b, c);
  16.   cout << "\n\nfunkcja joinUsing()\n dane: " << napis3a << ", " << c << ", " << napis3b << "\nwynik: " << napis3w;
  17.   char* napis4 = new char[6];
  18.   napis4[0]='s';napis4[1]='i';napis4[2]='p';napis4[3]='a';napis4[4]='n';napis4[5]='\0';
  19.   char* napis4w = backwards(napis4);
  20.   cout << "\n\nfunkcja backwards()\n dane: " << napis4 << "\nwynik: " << napis4w;
  21.   delete[] napis1, napis1w, napis2, napis3a, napis3b, napis3w, napis4;
  22.   cout << "\n\n";
  23.   system ("pause");
  24.   return 0;
  25. }