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

Wczytanie liczb z pliku do tablicy. (C)

+1 głos
121 wizyt
pytanie zadane 9 stycznia w C i C++ przez Sway22 Początkujący (270 p.)
Witam, jestem bardzo początkująca w programowaniu i mam takie pytanie: Jak wczytać liczby z pliku do tablicy w C?
komentarz 9 stycznia przez Sway22 Początkujący (270 p.)
int main()
{
    FILE *tablica;
    tablica = fopen("C:\\Ciąg.txt", "r");

    int a[7]; // jak zrobić żeby program sam sczytywał ile wyrazów jest w pliku?
    int i;

    if (tablica == NULL){
        printf("Error Reading File\n");
        exit (0);    // co to robi?
    }

    for (i = 0; i < 7; i++){
        fscanf(tablica, "%d,", &a[i] );
    }

    for (i = 0; i < 7; i++){
        printf("%d" , i);
        printf("wyraz ciagu: %d \n", a[i]);
    }

    fclose(tablica);

 

komentarz 9 stycznia przez j23 Mędrzec (173,020 p.)

Funkcja realloc twoim przyjacielem ;)

komentarz 9 stycznia przez VBService Mędrzec (163,370 p.)

@Sway22, 

if (tablica == NULL){
        printf("Error Reading File\n");
        exit (0);    // co to robi?
}

 

exit(0)

komentarz 9 stycznia przez Sway22 Początkujący (270 p.)
ale co to robi? po co to tam jest?
1
komentarz 9 stycznia przez VBService Mędrzec (163,370 p.)

Jeżeli jest jakikolwiek problem z "otwarciem" pliku Ciąg.txt, exit(0) powoduje natychmiastowe zamknięcie programu.

1 odpowiedź

0 głosów
odpowiedź 10 stycznia przez Wojciech Rokicki Użytkownik (850 p.)
edycja 11 stycznia przez Wojciech Rokicki

Aby automatycznie wczytywać nieznany nam rozmiar danych należy wykorzystać wskaźniki i dynamiczne alokowanie pamięci. Poniższy kod jest poszukiwanym przez Ciebie rozwiązaniem:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

int main(int argc, char *argv[]){
    FILE *fp;
    int32_t temp;
    int32_t *grades = NULL;
    int32_t count = 0;

    fp = fopen("grades.txt","r");

    while(fscanf(fp,"%d",&temp) != EOF) {
        count++;
        grades = realloc(grades,sizeof(*grades)*count);
        grades[count-1] = temp;
    }   

    temp = 0;

    while(temp < count) {
        printf("the read value is %d\r\n", grades[temp]);
        temp++;
    }

    fclose(fp);

    free(grades);
    grades = NULL;
}

Inspiracja dla powyższego kodu:
https://stackoverflow.com/a/19094299

W języku C++ jest gotowa struktura vector, która jest rodzajem tablicy o zmiennym rozmiarze. Mechanizmy zawarte w strukturze zapewniają  poprawne przydzielanie i zwalnianie pamięci, co ułatwia pracę programiście.

Innym, prostszym rozwiązaniem jest po prostu przyjęcie bardzo dużego rozmiaru tablicy do wczytania wszystkich wartości.

Funkcja exit odpowiada za zakończenie działania wywołującego ją procesu. Argumentem jest status z jakim proces kończy pracę - w tym przypadku 0, czyli bez błędu.

Tutaj więcej na temat różnicy pomiędzy funkcją return, a exit:
https://stackoverflow.com/questions/3463551/what-is-the-difference-between-exit-and-return

1
komentarz 10 stycznia przez j23 Mędrzec (173,020 p.)

To rozdzielenie na malloc i realloc jest zbędne, bo jak dasz tej drugiej wskaźnik null, to zachowa się jak ta pierwsza.

sizeof(grades)*count

Na 64-bitowych współczesnych platformach grades będzie miało 8 bajtów, bo to wskaźnik, a chcemy przecież count intów, czyli 32-bitowych wartości. Tu jest błąd.

1
komentarz 10 stycznia przez Oscar Pasjonat (24,050 p.)
edycja 10 stycznia przez Oscar
Nawet pomijając ten błąd, zacytowany kod jest chaotyczny i mało edukacyjny. Nadmiar zmiennych (jedna liczy w dół a druga w górę, jedna o 1 więcej niż druga), while zamiast naturalnego w tej sytuacji for, plik otwarty do odczytu i zapisu, otwarcie w trybie binarnym a czytanie tekstowe, reallokowanie dla każdej pojedynczej danej itp.
komentarz 10 stycznia przez j23 Mędrzec (173,020 p.)

reallokowanie dla każdej pojedynczej danej itp.

To nie jest aż taki problem, bo realloc nie realokuje co każde wywołanie. Jak się dobrze wstrzeli, to może realokować dopiero po przekroczeniu (wielokrotności) wielkości strony pamięci.

komentarz 11 stycznia przez Wojciech Rokicki Użytkownik (850 p.)

@j23, Dzięki wielkie za merytoryczny komentarz. Poprawiłem kod i mam nadzieję, że teraz jest już prawidłowo. Jeśli masz jeszcze jakieś uwagi to z chęcią je przyjmę. Faktycznie alokowane było zbyt dużo pamięci, nieadekwatnie do zapotrzebowania.

1
komentarz 11 stycznia przez Wojciech Rokicki Użytkownik (850 p.)

@Oscar, Dzięki za komentarz. Faktycznie kod jest trochę chaotyczny... Usunąłem zmienną index - teraz używam count. Kod miał być w C, więc trzymałem się standardu ANSI C. Jeśli znasz jakiś wydajny/wygodny sposób na wczytywanie liczb z pliku z wykorzystaniem pętli for, to podziel się rozwiązaniem w komentarzu. Jeśli masz jeszcze jakieś uwagi, prosiłbym o ich udzielenie. Będę starać się o udoskonalenie tego fragmentu kodu do granic możliwości laugh

2
komentarz 11 stycznia przez j23 Mędrzec (173,020 p.)

@Wojciech Rokicki, w sumie zamieniłbym jeszcze wyrażenia w stylu *(grades+temp) na tradycyjne grades[temp]. Nie ma co komplikować zapisu, jeśli nic na tym nie zyskujesz.

komentarz 11 stycznia przez Wojciech Rokicki Użytkownik (850 p.)

Masz rację, dziękuję smiley

Podobne pytania

0 głosów
1 odpowiedź 85 wizyt
pytanie zadane 12 maja 2019 w C i C++ przez Aleksandra01 Użytkownik (530 p.)
0 głosów
5 odpowiedzi 2,973 wizyt
0 głosów
1 odpowiedź 1,400 wizyt
pytanie zadane 26 listopada 2017 w C i C++ przez Karol.99 Użytkownik (550 p.)

87,976 zapytań

136,557 odpowiedzi

304,510 komentarzy

58,337 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Sklep oferujący ćwiczenia JavaScript, PHP, rozmowy rekrutacyjne dla programistów i inne materiały

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...