PO 2018: Wejściówka na Lab.8

Napisz program, który pobiera od użytkownika jego nick oraz niewielką liczbę naturalną. Umieść w kodzie asercję, która sprawdza czy liczba jest rzeczywiście naturalna. Następnie program przystępuje do testu zręczności użytkownika: losuje znak alfanumeryczny występujący na klawiaturze (nie losuje znaków interpunkcyjnych, matematycznych i pozostałych „symboli”) i wypisuje go w oknie konsoli, po czym oczekuje na naciśnięcie przez użytkownika klawisza odpowiadającego wypisanemu znakowi. Wtedy natychmiast losuje następny znak, wypisuje w oknie konsoli i ponownie czeka na reakcję użytkownika. Jeżeli użytkownik się pomylił, również natychmiast wypisuje następny znak. Program wykonuje test tyle razy, ile wynosiła pobrana liczba naturalna.

Po zakończeniu testu wyświetlany jest czas trwania testu (liczony od wypisania pierwszej litery aż do ostatniej odpowiedzi użytkownika) i liczba trafnych odpowiedzi. Do pomiaru czasu użyj funkcji time i difftime. Dodatkowo zostaje otwarty plik txt o nazwie takiej jak podany nick, tj. „nick.txt” i do niego w kolejnym wierszu są dopisywane uzyskane wyniki (czas i liczba trafień). Jeżeli takiego pliku jeszcze nie ma, program wypisuje w oknie konsoli komunikat o tym, że taki plik jest właśnie zakładany. W komunikacie podana jest pełna ścieżka do folderu, w którym plik zostanie utworzony wraz z jego nazwą. Hint: pełną ścieżkę do bieżącego folderu można pobrać z argv[0].

Każda akcja jest odnotowywana w pliku „log.txt”: pobranie nicka i liczby naturalnej, wypisanie litery na ekranie, odpowiedź użytkownika (wraz z informacją, czy była poprawna). Każdy wpis w pliku „log.txt” zaczyna się od daty i czasu dokonania wpisu z dokładnością do sekund. Następnie wypisywany jest komunikat o zdarzeniu. Plik „log.txt” należy otwierać tak, aby nie stracić jego dotychczasowej zawartości i aby nowe informacje były dołączane na końcu.

Uwagi:

  1. Zaproponuj własny sposób sprawdzenia, czy plik o podanej nazwie istnieje. Następnie napisz funkcję, która jako argument wywołania przyjmuje nazwę pliku, a zwraca wartość zero, jeżeli pliku nie ma, oraz 1 – jeżeli istnieje. Użyj tej funkcji do sprawdzenia, czy plik „nick.txt” istnieje.
  2. Do sprawdzania błędów związanych z dostępem do pliku „log.txt” wykorzystaj stałą errno, a do generowania komunikatów – funkcje strerror i perror. Wszelkie komunikaty o sytuacjach błędnych, jakie wystąpiły w trakcie pracy programu związane np. z dostępem do plików, wysyłaj do standardowego strumienia dla komunikatów o błędach stderr. Hint: aby wygenerować np. błąd 13 (brak prawa dostępu do pliku) wystarczy wcześniej otworzyć plik za pomocą edytora typu MS Word albo OpenOffice Writer i pozostawić otwartym. Wtedy próba otwarcia tego pliku w trybie „w”, „a” lub „a+” przez nasz program powinna zakończyć się niepowodzeniem.

PO 2018: Wejściówka na Lab.7

Przeprowadzono pomiary temperatury w terenie za pomocą czterech czujników temperatury w okresie od 10 lutego do 12 marca. Pomiary były wykonywane przez każdy z czujników co około 5 min. Mierzone wartości zostały zapisane w pliku ( [do pobrania] aby zapisać plik na dysk lokalny użyj prawego przycisku myszki i wybierz opcję „Zapisz element docelowy jako..” lub „zapisz link jako..”). Plik zawiera listę rekordów, gdzie rekord to kolekcja kilku dowolnych wartości, każda ściśle określonego typu, występujących w ustalonej, zawsze tej samej kolejności. Każdy rekord w pliku reprezentuje pojedynczy pomiar i składa się z czterech wartości zapisanych w jednym wierszu pliku: nr pomiaru, nr czujnika, data i czas, oraz zmierzona temperatura, które rozdzielone są znakiem spacji.

W funkcji main pobierz od użytkownika nazwę pliku z danymi, otwórz ten plik w trybie do odczytu, a następnie wczytaj zawartość pliku do listy dynamicznej dwukierunkowej. Po zakończeniu czytania zamknij plik. Przyjmij, że dane w pliku są zawsze poprawne, tj. wiersz zawsze zawiera czwórkę prawidłowych napisów w tej samej kolejności.

Typ danych do przechowywania jednego rekordu ma następującą budowę:

struct pomiar {
	unsigned int nr_pomiaru;
	unsigned int nr_czujnika;
	char data_i_czas[20];
	double temp;
	struct pomiar *nast;
	struct pomiar *poprz;
};

Następnie rozdziel elementy z wczytanej listy na cztery listy dynamiczne dwukierunkowe, po jednej liście dla każdego z czujników. W tym celu zadeklaruj cztery nowe głowy list, tj. wskaźniki typu struct pomiar*, po czym przejrzyj kolejno wszystkie elementy, sprawdź z jakiego czujnika pochodzi pomiar i przenieś ten element do listy właściwej dla tego czujnika. Nie alokuj nowych zmiennych dynamicznych reprezentujących pomiary i nie kopiuj żadnych danych, a jedynie wyjmuj elementy z jednej listy i dodawaj do jednej z pozostałych czterech poprzez działanie na wartościach pól nast i poprz. Na koniec działania lista źródłowa powinna być pusta.

Wypisz w oknie konsoli, ile pomiarów pochodzi z każdego z czujników, tj. jakie są rozmiary każdej z list oraz jakie są wartości najwyższej i najniższej zmierzonej temperatury dla każdego z czujników.

Po zakończeniu zapisywania zamknij pliki, usuń elementy z list i zakończ działanie programu.

Pobierz plik tekstowy z danymi wejściowymi i umieść go we właściwym katalogu. Do obsługi plików wykorzystaj funkcje fopen, fclose, fprintf, fscanf i feof (lub odpowiadających im wersji bezpiecznych). Wszystkie z biblioteki: stdio.h.

PO 2018: Wejściówka na Lab.6

Przeprowadzono pomiary temperatury w terenie za pomocą czterech czujników temperatury w okresie od 10 lutego do 12 marca. Pomiary były wykonywane przez każdy z czujników co około 5 min. Mierzone wartości zostały zapisane w pliku ( [do pobrania] aby zapisać plik na dysk lokalny użyj prawego przycisku myszki i wybierz opcję „Zapisz element docelowy jako..” lub „zapisz link jako..”). Plik zawiera listę rekordów, gdzie rekord to kolekcja kilku dowolnych wartości, każda ściśle określonego typu, występujących w ustalonej, zawsze tej samej kolejności. Każdy rekord w pliku reprezentuje pojedynczy pomiar i składa się z czterech wartości zapisanych w jednym wierszu pliku: nr pomiaru, nr czujnika, data i czas, oraz zmierzona temperatura, które rozdzielone są znakiem spacji.

W funkcji main pobierz od użytkownika nazwę pliku z danymi, otwórz ten plik w trybie do odczytu, a następnie wczytaj zawartość pliku do listy dynamicznej jednokierunkowej. Po zakończeniu czytania zamknij plik. Przyjmij, że dane w pliku są zawsze poprawne, tj. wiersz zawsze zawiera czwórkę prawidłowych napisów w tej samej kolejności.

Typ danych do przechowywania jednego rekordu ma następującą budowę:

struct pomiar {
	unsigned int nr_pomiaru;
	unsigned int nr_czujnika;
	char data_i_czas[20];
	double temp;
	struct pomiar *nast;
};

Następnie rozdziel elementy z wczytanej listy na cztery listy dynamiczne jednokierunkowe, po jednej liście dla każdego z czujników. W tym celu zadeklaruj cztery nowe głowy list, tj. wskaźniki typu struct pomiar*, po czym przejrzyj kolejno wszystkie elementy, sprawdź z jakiego czujnika pochodzi pomiar i przenieś ten element do listy właściwej dla tego czujnika. Nie alokuj nowych zmiennych dynamicznych reprezentujących pomiary i nie kopiuj żadnych danych, a jedynie wyjmuj elementy z jednej listy i dodawaj do jednej z pozostałych czterech. Na koniec działania lista źródłowa powinna być pusta.

Wypisz w oknie konsoli, ile pomiarów pochodzi z każdego z czujników, tj. jakie są rozmiary każdej z list.

Zapisz powstałe cztery listy do czterech plików o nazwach zaczynających się od tego samego ciągu znaków. W tym celu najpierw pobierz od użytkownika początek nazwy plików do zapisu, następnie dla każdego z plików dodaj do jego nazwy na jej końcu cyferkę odpowiadają numerowi czujnika i dodaj „.txt” (przykład: użytkownik podał „abc”, pliki nazywają się „abc1.txt”, abc2.txt”, „abc3.txt” i „abc4.txt”). Zapisz do każdego z plików zawartość odpowiadającej mu listy w takim samym formacie jaki miał plik wejściowy.

Po zakończeniu zapisywania zamknij pliki, usuń elementy z list i zakończ działanie programu.

Pobierz plik tekstowy z danymi wejściowymi i umieść go we właściwym katalogu. Do obsługi plików wykorzystaj funkcje fopen, fclose, fprintf, fscanf i feof (lub odpowiadających im wersji bezpiecznych). Wszystkie z biblioteki: stdio.h.

PO 2018: Wejściówka na Lab.5

Napisz funkcję bin2int, która jako argument przyjmuje wskaźnik do tablicy znaków (np. char* t) przechowujących liczbę zapisaną w postaci binarnej w taki sposób, że pierwszym znakiem musi być zawsze '1′, tj. np. 1001, 100, 10101111, 1110010, itp., i która zwróci wartość typu int odpowiadającą podanej liczbie binarnej (np. dla 1001 będzie to wartość 9).

Następnie napisz program, który:

  1. Do dwuwymiarowej tablicy dynamicznej podobnej do tej prezentowanej na slajdzie 121, wykład 4, ale przechowującej dane typu char i o wymiarach m wierszy na n kolumn (m i n podane przez użytkownika), wczyta z pliku tekstowego kilka liczb zapisanych w postaci binarnej. W każdym wierszu pliku znajduje się jedna liczba zapisana w taki sposób, że pierwszą cyfrą musi być zawsze 1, tj. np. 1001, 100, 10101111, 1110010, itp. Tak zapisane liczby mogą mieć różną liczbę znaków, ale nie większą niż n-1. W każdym wierszu tablicy przechowywana będzie jedna wczytana liczba. Przyjmij, że liczba wierszy w pliku nie jest znana, ale nie większa niż m, tak aby było wiadomo, że dane zmieszczą się w tablicy.
  2. Po zakończeniu wczytywania wywoła dla każdego ciągu binarnego z tablicy funkcję bin2int, która zwróci wartość typu int odpowiadającą podanej liczbie binarnej. Zwrócona wartość na być wypisana w oknie konsoli.
  3. Posortuje wczytane ciągi binarne w taki sposób, aby liczby całkowite reprezentowane przez ciągi były uporządkowane malejąco. Przemieszczenia ciągów binarnych nie dokonuj poprzez kopiowanie wartości z jednych tablic dynamicznych do drugich, ale poprzez zamianę położeń wartości wskaźników do dynamicznych tablic przechowujących ciągi binarne. To ważne: aby zmienić porządek, nie wykonuj żadnych alokacji nowych tablic dynamicznych, a jedynie zamieniaj adresy w komórkach tablicy wskaźników. Zastosuj dowolne sortowanie. Uwaga: przygotuj swój program również na sytuację, kiedy plik z liczbami był pusty.
  4. Po zakończeniu przestawiania jeszcze raz wypisze w oknie konsoli wartości liczbowe dla wszystkich ciągów binarnych w tablicy ułożonych wg nowego porządku korzystając z funkcji bin2int.