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

Wczytaj, dodaj i wyświetl

42 Warsaw Coding Academy
0 głosów
466 wizyt
pytanie zadane 30 marca 2020 w C i C++ przez Hubertius Bywalec (2,970 p.)

Hej :)

Mam problem z usprawnieniem mojego programu do pewnego zadania.

Treść jest taka:

Napisz program, który pobierze od użytkownika nazwę pliku, a następnie odczyta i wyświetli na ekranie sumę liczb z pliku. Liczby w pliku oddzielone będą białym znakiem (np. spacja, enter, tabulator).

Jeżeli podany przez użytkownika plik nie istnieje program powinien wyświetlić komunikat Couldn't open file i zakończyć działanie z kodem błędu 4. Jeżeli w plik będą znajdowały się dane inne niż liczby, program powinien wyświetlić komunikat File corrupted i zakończyć działanie z kodem błędbu 6

Jeżeli udało się obliczyć sumę liczb, zawartych w podanym pliku, program powinien ją wyświetlić zwrócić wartość 0.

Przykładowa interakcja z programem (dla pliku wejściowego text.txt):

Podaj sciezke do pliku:⏎
text.txt⏎
Suma wczytanych liczb wynosi: 200
Przykładowa interakcja z programem - brak pliku:

Podaj sciezke do pliku:⏎
diestartyellowsubtractbloc⏎
Couldn't open file⏎
Przykładowa interakcja z programem - uszkodzony plik (zawiera cokolwiek innego, niż liczby):

dawajta sciezke do pliku:⏎
question.txt⏎
File corrupted
Uwaga

W programie nie wolno używać funkcji alokujacych pamięć.
W programie można zadeklarować tylko tablice na 30 znaków (do przechowywania nazw plików). Deklaracja musi wyglądać następująco: nazwa_zmiennej[31];.
W programie nie wolno używać operatora [].

A oto mój kod:

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

int main()
{
    char tab[31]={0};
    char input[31]={0};
    char *tab_i=&(*(tab+0)), *input_i=&(*(input+0));



    int i;
    printf("Podaj sciezke do pliku\n");
    scanf(" %31[^\n]", input_i);
    for(i=0; i<30; i++)
    {
        *(tab_i+i)=*(input_i+i);
    }

    FILE *f= fopen(tab_i,"rb");
    if(f==NULL)
    {
        printf("Couldn't open file");
        return 4;
    }

    int suma = 0;
    char znak;
    int znak_int;


    while(fread(&znak,1,1,f) != 0 )
    {
        if(znak>=48 && znak<=57)
        {

        }
        else if(znak==' ' || znak=='\n' || znak=='\t' || znak=='\0' || znak==13 || znak=='-')
        {

        }
        else
        {
            //printf("%c",znak);
            fclose(f);
            printf("File corrupted");
            return 6;
        }

        fscanf(f,"%d",&znak_int);
        //printf("\n%d\n",znak_int);
        suma+= znak_int;

        ;
    }
    printf("%d",suma);
    fclose(f);
    return 0;
}

Przy sprawdzaniu zadania na testach zauważyłem, że wyskakuję ciągle niepoprawne wartości (sumy liczb z mojego programu różnią się nieznacznie od tego co powinno wychodzić na testach, ale jednak się różni). Zauważyłem między innymi problem w przypadku pojawienia się pustej linijki w moim pliku tekstowym. Wtedy najczęściej dochodzi do dziwnych pomyłek. Np. dla tak zapisanych przeze mnie danych w pliku tekstowym:

2

3 
5

3

1 3

policzyło ostateczną wartość jako...18. Tak więc czy jest coś, o czym zapomniałem podczas wykonywania przeze mnie tego zadania? Jeżeli tak, to jak mogę to zaimplementować? 

komentarz 30 marca 2020 przez j23 Mędrzec (195,240 p.)

Dlaczego nie użyjesz fscanf do czytania liczb?

komentarz 30 marca 2020 przez Hubertius Bywalec (2,970 p.)

@j23 No teoretycznie używam pod sam koniec pętli:

fscanf(f,"%d",&znak_int);

 

komentarz 30 marca 2020 przez j23 Mędrzec (195,240 p.)

To co tam fread robi?

komentarz 30 marca 2020 przez Hubertius Bywalec (2,970 p.)
edycja 30 marca 2020 przez Hubertius

fread de facto czyta znak po znaku aż w końcu dojdzie do końca pliku i zwróci wartość mniejszą od count (czyli w tym przypadku zero). Czyli mogę na spokojnie warunek wykonywania pętli zastąpić fscanf?

Zapisałem coś w tym stylu:

while(fscanf(f,"%d",&znak_int)==1)
    {
        suma += znak_int;
    }
    printf("%d",suma);

I teraz zlicza mi wszelkie znaki, niezależnie od tego czy są spacje i entery-y pomiędzy liczbami. Pozostaje jednak tylko pytanie jakie zabezpieczenie mogę zrobić na przypadek "File corrupted"?

EDIT

Udało mi się poprawnie wykonać to zadanie. Oto ostateczny kod:

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

int main()
{
    char tab[31]={0};
    char input[31]={0};
    char *tab_i=&(*(tab+0)), *input_i=&(*(input+0));



    int i;
    printf("Podaj sciezke do pliku\n");
    scanf(" %31[^\n]", input_i);
    for(i=0; i<30; i++)
    {
        *(tab_i+i)=*(input_i+i);
    }

    FILE *f= fopen(tab_i,"rb");
    if(f==NULL)
    {
        printf("Couldn't open file");
        return 4;
    }

    int suma = 0;
    int znak_int;
    char znak;
    while(fread(&znak,1,1,f) != 0)
    {
        if(znak>=48 && znak<=57)
        {

        }
        else if( znak==13 || znak=='\t' || znak=='\0' || znak=='-' || znak==' ' || znak=='\n')
        {

        }
        else
        {
            fclose(f);
            printf("File corrupted");
            return 6;
        }
    }
    fseek(f,0,SEEK_SET);

    while(fscanf(f,"%d",&znak_int)==1)
    {
        suma += znak_int;
    }
    printf("%d",suma);
    fclose(f);
    return 0;
}

 

komentarz 30 marca 2020 przez j23 Mędrzec (195,240 p.)

@Hubertius,  zamiast tej pierwszej pętli while testującej, czy nie ma innych znaków, po prostu sprawdzaj co zwraca fscanf - jeśli zwróci zero, to znaczy, że napotkała na coś, co nie jest liczbą.

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

Podobne pytania

0 głosów
0 odpowiedzi 238 wizyt
pytanie zadane 31 marca 2020 w C i C++ przez Hubertius Bywalec (2,970 p.)
0 głosów
1 odpowiedź 848 wizyt
0 głosów
1 odpowiedź 705 wizyt
pytanie zadane 4 kwietnia 2020 w C i C++ przez Hubertius Bywalec (2,970 p.)

93,377 zapytań

142,380 odpowiedzi

322,529 komentarzy

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

VMware Cloud PRO - przenieś swoją infrastrukturę IT do chmury
...