PO 2019: 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 (zobacz też Wikipedia). 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 2019: 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 126, 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.

PO 2019: Wejściówka na Lab.4

Napisz program, który będzie wczytywał dane z jednego pliku tekstowego i zmienione zapisywał do drugiego.
W tym celu:

  1. Zadeklaruj strukturalny typ danych struct para zdefiniowany tak, że zmienna takiego typu może przechowywać dwie wartości: napis oraz liczbę. W funkcji main zadeklaruj lokalną tablicę o długości 5, zawierającą elementy typu struct para.
  2. Napisz funkcję wiersz, która będzie odczytywała dane z wiersza w otwartym pliku. W wierszu zapisane są kolejno: nr indeksu studenta, nazwisko i ocena. Funkcja odczytuje dane z jednego wiersza, następnie ignoruje odczytany nr indeksu a do komórki tablicy wpisuje w odpowiednich polach tylko nazwisko i ocenę. Przyjmij, że w pliku może być dowolna liczba wierszy (jest możliwe również, że plik jest pusty), ale nie większa niż rozmiar tablicy. Przyjmij też, że dane w pliku są zawsze poprawne, tj. wiersz zawsze zawiera trójkę prawidłowych napisów w tej samej kolejności: numer, nazwisko i ocena.
    Nagłówek funkcji ma wyglądać tak:
    int wiersz(FILE* f, struct para *p)
    gdzie f to wskaźnik do otwartego pliku, natomiast p to wskaźnik do komórki tablicy, do której mają zostać zapisane dane z jednego odczytanego wiersza pliku. Funkcja zwraca wartość zero, jeżeli odczyt zakończył się pomyślnie, a wartość 1, jeżeli nie udało się odczytać kolejnej porcji danych ze względu na koniec pliku.
  3. W funkcji main pobierz od użytkownika nazwę pliku z danymi oraz nazwę pliku wyjściowego. Otwórz plik z danymi w trybie do odczytu, a plik wynikowy w trybie do zapisu. Następnie w pętli za pomocą funkcji wiersz odczytaj kolejne wiersze pliku zapisując dane w kolejnych komórkach tablicy. Każdą odczytaną komórkę tablicy zapisz od razu do pliku wynikowego tak, aby w kolejnych wierszach pliku znalazły się pary: nazwisko i ocena. Uwaga: nazwisko należy zapisać do pliku w postaci zaszyfrowanej, tj. należy zastąpić wszystkie samogłoski znakiem '*’. Jeżeli nie wszystkie komórki tablicy zostały zapełnione danymi, zapisz do pliku tylko tyle, ile zostało odczytanych z pliku wejściowego. Po zakończeniu pętli zamknij pliki, wyświetl w oknie konsoli zawartość tablicy i zakończ działanie funkcji main.
  4. Przygotuj sobie odpowiedni plik tekstowy z prawidłowymi danymi w kilku wierszach i umieść go we właściwym folderze. Następnie przetestuj program.

Do obsługi plików wykorzystaj funkcje: fopen, fclose, fprintf, fscanf i feof. Wszystkie z biblioteki: stdio.h.

Przetestowany, działający program uploaduj do systemu moodle jako rozwiązanie zadania „wejściówka” tematu nr 4.

Różne przykłady zadań i problemów dotyczących tego rodzaju zastosowań można znaleźć w podręcznikach lub na forach, których tematem jest programowanie w ANSI C. Dobre słowa kluczowe dla wyszukiwarki na najbliższy tydzień to: fopen, fclose, fprintf, fscanf i feof w połączeniu z ansi c. Oczywiście niczego nie należy brać bezkrytycznie, każdy kawałek kodu warto zweryfikować wklejając do okna VC++ i sprawdzając, jak naprawdę działa.

Hint:

Przygotowując się na lab. nr 4 warto przypomnieć sobie jak skonstruowany jest C-napis, sprawdzić jak działa szyfr Cezara, oraz zapoznać się z funkcjami:

  • int isalpha(int c)
  • int islower(int c)
  • int isupper(int c)
  • int tolower(int c)
  • int toupper(int c)

Funkcje znajdują się w bibliotece ctype.h i służą do sprawdzania, czy dany znak jest literą i jakiego rodzaju (dużą czy małą) oraz do zamiany dużych liter na małe i małych na duże. Zadania pierwszego poziomu na lab. 4 mogą mieć wspólne fragmenty z zadaniami poziomu 2 lab. nr 3, tj. będą dotyczyły konwertowania napisów do postaci zaszyfrowanych wg różnych reguł, oraz oczywiście będą dotyczyły pracy na plikach tekstowych (materiał ostatnio omawiany na wykładzie).

PO 2019: Wejściówka na Lab.3

Zadeklaruj strukturalny typ danych, który będzie zawierał dwa pola: napis oraz liczba całkowita. W funkcji main zadeklaruj lokalną tablicę o niewielkiej długości (np. 5), zawierającą elementy typu takiego, jak zdefiniowana wcześniej struktura.

Następnie napisz funkcję, która jako argument wywołania przyjmuje tę tablicę. Kod funkcji sprawdza, czy w każdej z komórek tablicy pole liczbowe nie zawiera wartości mniejszej (ale dodatniej) od długości napisu przechowywanego w drugim polu. Jeżeli tak, skraca napis do długości takiej, jak wartość w polu liczbowym. W przeciwnym przypadku pozostawia napis niezmieniony. Takie sprawdzenie i skracanie wykonuje się dla wszystkich komórek tablicy. Po przejrzeniu całej tablicy funkcja zwraca liczbę skróceń, jakie rzeczywiście zostały wykonane.

Napisz w funkcji main kod, który pozwala użytkownikowi wprowadzić wartości do obydwu pól w każdej z komórek tej tablicy. W main, poniżej kodu wprowadzającego dane umieść wywołanie funkcji skracającej napisy w tablicy, przy czym argumentem wywołania jest tablica, do której dane zostały właśnie przez użytkownika wprowadzone. Na koniec dopisz kod wyświetlający nową zawartość tablicy (w kolejnych wierszach pary: liczba i napis) oraz zwróconą przez funkcję liczbę faktycznie wykonanych skróceń.

Przetestowany, działający program załaduj do systemu moodle jako rozwiązanie zadania „wejściówka” lab. nr 3 (wyłącznie plik cpp z kodem źródłowym, nic więcej).