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

Pliki w tablicy struktur

Aruba Cloud VPS - 50% taniej przez 3 miesiące!
0 głosów
1,015 wizyt
pytanie zadane 27 maja 2020 w C i C++ przez pozdro600 Początkujący (260 p.)
edycja 28 maja 2020 przez pozdro600

Mam zadanie:

Napisz program, który pobierze od użytkownika listę plików tekstowych a następnie będzie pobierał kolejne teksty i dodawał je do tego pliku, w którym aktualnie znajduje się najmniej danych.

W tym celu przygotuj strukturę do przechowywania wskaźnika do pliku oraz jego informacji o jego rozmiarze. Pomoże ona w procesie wyboru pliku o najmniejszej liczbie danych oraz w śledzeniu informacji o ilości tych danych.
Struktura powinna wyglądać następująco:

struct file_t
{
    FILE *f;
    int size;
};

Pole f przechowuje uchwyt otwartego pliku (przez funkcję open_file opisaną dalej). Z kolei pole size przechowuje aktualną wielkość pliku w bajtach. Wartość tego pola powinna być aktualizowana po każdej operacji dodania danych do pliku f.


Przygotuj następujące funkcje: otwierającą plik, zamykającą plik oraz wyszukującą plik o najmniejszym rozmiarze. Prototypy tych funkcji powinny wyglądać następująco:

int open_file(struct file_t* f, const char *filename);

Funkcja otwiera plik o nazwie filename i przypisuje jego uchwyt do struktury f. Jeśli plik nie istnieje to funkcja powinna spróbować go utworzyć. Pole size struktury powinno zostać uzupełnione rozmiarem pliku.

Wartość zwracana:

  • 0 - w przypadku sukcesu (plik utworzony bądź otworzony, struktura f uzupełniona),
  • 1 - w przypadku przekazania do funkcji nieprawidłowych danych,
  • 2 - gdy nie udało się uzyskać dostępu do pliku filename.
struct file_t* find_min(const struct file_t* files, int size);

Funkcja ma odnaleźć pierwszy plik w tablicy files o size elementach który posiada najmniejszą ilość zapisanych danych.

Wartość zwracana:

  • Jeśli znaleziony, to funkcja powinna zwrócić wskaźnik do struktury file_t opisującej taki plik.
  • W przypadku podania błędnych danych funkcja powinna zwrócić wartość NULL.

Zwróć uwagę na modyfikator const.

void close_file(struct file_t* f);

Funkcja zamyka plik. W przypadku braku możliwości wykonania operacji zamknięcia funkcja nie podejmuje żadnych działań.


Napisz program, który będzie pobierał od użytkownika nazwy plików aż do wprowadzenie pustej linii. Pierwsze 5 istniejących plików powinno zostać otworzone i wykorzystane do dalszej pracy.

Po zakończeniu fazy pobierania nazw plików i ich otwierania program przechodzi o pobierania kolejnych tekstów od użytkownika. Pobierane teksty nie mogą być dłuższe niż 999 znaków a pętla pobierania tekstów kończy się z chwilą podania pustego ciągu znaków.

Każdy pobrany tekst jest dopisywany do pierwszego pliku z wczytanej listy, w którym na chwilę obecną znajduje się najmniejsza ilość danych.

  • W przypadku kiedy nie uda się otworzyć żadnego pliku program powinien wyświetlić komunikat Couldn't open file i zakończyć się z kodem błedu4.

Po zakończeniu wprowadzania danych program powinien wyświetlić komunikat Files saved i zwrócić kod błędu 0.

Przykładowa interakcja z programem -- sukces:

Podaj nazwy plikow: ⏎
lost.txt⏎
since.txt⏎
//../city.txt⏎
⏎
Podaj teksty: ⏎
Dolor non labore tempora sed eius quaerat. Quisquam non dolor labore ut ipsum ipsum labore. Magnam etincidunt eius quisquam adipisci eius velit. Velit voluptatem porro magnam adipisci. Ut dolore voluptatem est ipsum non sed quaerat.⏎
Modi quisquam ut labore. Amet dolorem ipsum tempora quisquam velit magnam. Quisquam adipisci eius labore dolore non voluptatem etincidunt. Amet voluptatem sit neque aliquam adipisci velit amet. Sed quaerat adipisci modi eius non. Consectetur modi dolore porro aliquam. Dolore sit amet dolor. Eius consectetur consectetur quiquia tempora. Magnam non voluptatem aliquam dolore sed etincidunt. Sit ut dolorem modi consectetur magnam.⏎
Etincidunt labore consectetur sed. Amet adipisci magnam labore. Modi quaerat velit dolor. Dolorem tempora dolore ut porro velit non est. Dolore ipsum neque eius tempora tempora quisquam.⏎
Aliquam quisquam quisquam eius consectetur quiquia. Ut est neque non. Neque dolore tempora modi velit. Adipisci etincidunt dolor ipsum dolore dolor. Consectetur dolore consectetur dolorem non consectetur dolorem ut. Ut quiquia ut dolorem ipsum aliquam labore neque.⏎
Est velit neque dolor aliquam numquam est labore. Ut quisquam ipsum quisquam neque dolore velit. Magnam dolorem aliquam est ipsum non. Tempora ipsum sed consectetur. Eius tempora aliquam consectetur dolore quiquia eius consectetur. Sit ut sit est magnam est numquam. Dolorem dolore eius porro.⏎
Dolor quiquia magnam magnam amet. Dolore quisquam labore adipisci voluptatem sit. Labore quaerat sit voluptatem dolor magnam etincidunt. Sed sit labore magnam porro modi amet amet. Tempora quaerat ut tempora.⏎
Ut est voluptatem velit sit modi neque. Magnam sit magnam sed quaerat. Dolore labore amet consectetur. Voluptatem dolorem adipisci ipsum porro modi quaerat dolore. Modi dolore quaerat quiquia amet non aliquam. Sed sit dolor quisquam dolor velit. Voluptatem ut ut voluptatem amet etincidunt non. Dolorem etincidunt quisquam labore dolore ipsum dolorem quaerat. Neque quisquam etincidunt quisquam numquam non. Neque etincidunt voluptatem ut.⏎
⏎
Files saved

Oto mój program:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <math.h>

struct file_t
{
    FILE* f;
    int size;
}t[5];
void close_file(struct file_t* f) {
    if (f == NULL || f->f == NULL) {

    }
    else {
        fclose(f->f);
    }
}
int open_file(struct file_t* f, const char* filename) {
    if (f == NULL || filename == NULL) {
        return 1;
    }
    FILE* fp;
    fp = fopen(filename, "ab");
    if (fp == NULL) {
        return 2;
    }
    long int res = ftell(fp);
    fclose(fp);
    f->size = res;
    f->f = fopen(filename, "ab+");
    if (fp == NULL) {
        return 2;
    }
    return 0;
}
struct file_t* find_min(const struct file_t* files, int size) {
    if (files == NULL || size <= 0) {
        return NULL;
    }
    int x = (files + 0)->size, i = 0, index = 0;
    for (i = 0; i < size; i++) {
        if ((files + i)->size <= x) {
            x = (files + i)->size;
            index = i;
        }
    }
    return (struct file_t*)(files + index);
}
int main() {
    puts("Input files' names:");
    char tab[100];
    int num = 0;
    while(1==1){
        if(fgets(tab, 100, stdin)==NULL||*tab=='\n'){
            if (num == 0) {
                printf("Couldn't open file");
                return 4;
            }
            break;
        }
        int index=strlen(tab);
        *(tab+index-1)='\x0';
        if (strlen(tab) > 30) {
            *(tab + 30) = '\x0';
        }
        if (open_file((t + num), tab) > 0) {
        }
        else {
            num++;
        }
    }
    if (num == 0) {
        printf("Couldn't open file");
        return 4;
    }
    char str[1000];
    printf("Input text:");
    *str = '\x0';
    while (fgets(str, 1000, stdin)==NULL||*str!='\n') {
        int index=strlen(str);
        *(str+index-1)='\x0';
        struct file_t* p = find_min(t, num);
        fwrite(str, sizeof(char), strlen(str), p->f);
    }
    for (int i = 0; i < num; i++) {
        close_file(t + i);
    }
    printf("File saved");
    return 0;
}


 

W testach na platformie akademickiej program po uruchomieniu wyświetla "Files saved" od razu po komendzie "Podaj teksty", a dopiero pozniej pobiera dane co nie pozwala mi przejsc testów.

komentarz 27 maja 2020 przez j23 Mędrzec (195,220 p.)

Można wiedzieć, dlaczego czytasz nazwy plików i linie tekstu po znaku zamiast czytać liniami (np. funkcją fgets)?

W linii 101 powinno być strlen(str), a nie sizeof(str).

komentarz 27 maja 2020 przez pozdro600 Początkujący (260 p.)
Dzięki, poprawiłem. Wiesz moze czemu na testach wyświetla mi na początku "Files saved", a dopiero potem pobiera tekst?
komentarz 27 maja 2020 przez j23 Mędrzec (195,220 p.)

fseek(stdin, 0, SEEK_END);

A to po co tam jest?

 

BTW, nie lepiej uprościć tę drugą pętlę do takiej postaci:

while (scanf("%[^\n]s", str) == 1 && *str != '\x0') {
	struct file_t* p = find_min(t, num);
	fwrite(str, sizeof(char), strlen(str), p->f);
}

 

komentarz 27 maja 2020 przez pozdro600 Początkujący (260 p.)
Na wszelki wypadek czyszczę bufor w taki sposób.
komentarz 27 maja 2020 przez j23 Mędrzec (195,220 p.)

Co Ty chcesz tam czyścić, skoro czytasz całe linie tekstu?

Standardowe strumienie nie są seekable i niewykluczone, że użycie fseek na takim strumieniu wprowadzi go w stan błędu.

Wywal linie z fseek dla stdin.

 

komentarz 27 maja 2020 przez pozdro600 Początkujący (260 p.)
Poprawiłem i niestety nadal w repl.it pojawia się ten sam błąd.
komentarz 28 maja 2020 przez j23 Mędrzec (195,220 p.)
Uaktualnij kod, żeby było wiadomo, jak wygląda z poprawkami.
komentarz 28 maja 2020 przez pozdro600 Początkujący (260 p.)
Uaktualniłem
komentarz 28 maja 2020 przez pozdro600 Początkujący (260 p.)
Poprawiłem go na tyle ze jedynym problemem jest ze wpisuje wszystko do jednego pliku
komentarz 28 maja 2020 przez pozdro600 Początkujący (260 p.)

Dobra, wiem. Dzięki za pomoc.laugh

 

komentarz 31 lipca 2020 przez ResCrove Obywatel (1,700 p.)

@j23, czy zrozumiałeś może co w tym kodzie było nie tak że komunikat Files saved wyświetlał się na początku a dopiero potem pobierał tekst? ( mam ten sam problem )

komentarz 31 lipca 2020 przez Oscar Nałogowiec (29,340 p.)

@pozdro600,
 Skopiowałem sobie twój program, uruchomiłem normalnie w konsoli i działa, może nie całkiem dobrze, ale działa. Nie modyfikujesz wielkości pliku po zapisie. Być może problem leży w tym środowisku, w którym uruchamiasz. Skoro dostajesz komunikat "File saved" to znaczy, że program doszedł do końca, nie ma innej możliwości. Późniejsze czytanie to jakaś ściema.

komentarz 1 sierpnia 2020 przez j23 Mędrzec (195,220 p.)

@ResCrove, zastosowałeś sugerowane poprawki?

Zaloguj lub zarejestruj się, aby odpowiedzieć na to pytanie.

Podobne pytania

0 głosów
3 odpowiedzi 529 wizyt
pytanie zadane 28 stycznia 2016 w C i C++ przez Kimi Bywalec (2,050 p.)
0 głosów
1 odpowiedź 1,499 wizyt
pytanie zadane 11 stycznia 2019 w C i C++ przez kamyk2 Początkujący (420 p.)
0 głosów
1 odpowiedź 265 wizyt
pytanie zadane 12 lipca 2015 w C i C++ przez hit02 Nałogowiec (33,970 p.)

93,109 zapytań

142,088 odpowiedzi

321,611 komentarzy

62,450 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

Wprowadzenie do ITsec, tom 1 Wprowadzenie do ITsec, tom 2

Można już zamawiać dwa tomy książek o ITsec pt. "Wprowadzenie do bezpieczeństwa IT" - mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy aż 15% zniżki! Dziękujemy ekipie Sekuraka za fajny rabat dla naszej Społeczności!

...