zadanie z książki Język ANSI C

0

Witam mam prośbę odnośnie oceny programu do zadania 1.18 z książki "Język ANSI C"
Generalnie chodzi mi o to czy program jest przejrzysty, zrozumiały, poprawny i czy jest to dobry styl programowania i poprawne myślenie algorytmiczne.
Cała idea opiera się na tym, że wczytujemy znaki do tablicy do momentu znaku nowego wiersza lub przepełnienia tablicy
Jeśli nastąpi któreś z tych zdarzeń, to sprawdzamy czy wczytywaliśmy białe znaki jeśli tak, to opuszczamy je i znak końca tablicy umieszczamy za ostatnim poprawnym znakiem.

poniżej kod źródłowy funkcji getline, która realizuje to zadanie.

 
int getline(char line[],int mx)
{
        int i,c,lbznakow;
        int stan;

        lbznakow = 0;
        stan = OUT;
        for(i=0;i<mx-1&&(c=getchar())!=EOF&&c!='\n';i++)
        {
                if(c!=' ' && c!='\t')
                {
                        lbznakow = 0;
                        stan = IN;
                }
                if(c==' '||c=='\t')
                {
                        lbznakow++;
                        stan = OUT;
                }
                line[i]=c;
        }
        if(i==mx-1)
        {
                fflush(stdin);
                if(stan==OUT)
                {
                        if(i==lbznakow)
                        {
                                line[i-lbznakow]=c;
                                i = i-lbznakow;
                                i++;
                        }
                        else
                        {
                                line[i-lbznakow]=c;
                                i=i-lbznakow;
                        }
                }

        }
        if(c=='\n')
        {
                if(stan==OUT)
                {
                        line[i-lbznakow]=c;
                        i=i-lbznakow;
                }
                if(stan == IN)
                {
                        line[i] = c;
                }
                i++;
        }
        line[i]='\0';
return i;
}

Test czy wiersz jest pusty(biały) czy nie zrealizowane jest w funkcji głównej programu. Kod źródłowy poniżej

 
while((len=getline(wiersz,MAXLINE))>0)
        {
                if(len==1&&(wiersz[len-1]=='\n'||wiersz[len-1]=='\t'||wiersz[len-1]==' '))
                        printf("Wiersz pusty\n");
                else
                        printf("%s",wiersz);
        }
0

Generalnie chodzi mi o to czy program jest przejrzysty, zrozumiały,

Nie wiem. Ja bym tak zrobił:

int getline(char line[],int mx) {
 if( max < 1 ) 
  abort();
 int i=0;
 while(true) {
   const int c = getchar();
   if( i==mx-1 || c == EOF || c == '\n' ) {
   line[i] = 0;
   break;
  } else {
   line[i++] = c;
   }
 while( i>0 && ( ine[i-1] == '\t' || line[i-1] == ' ' ) )
   line[--i] = 0;
 return i;
}

Pozdrawiam

0

Dziękuję za odpowiedź. Bardzo zgrabnie napisany kawałek kodu. Ale funkcja po napotkaniu znaku nowego wiersza, albo przepełnienu tablicy nieoczekiwanie kończy działanie mimo, że nie otrzymała znaku EOF. Poza tym funkcja nie wczytuje znaku nowego wiersza. To na pewno drobne korekty ale i tak trzeba byłoby dokonac zmian w kodzie. Generalnie redukujesz liczbe kodu w stosunku do mojego programu, unikasz wprowadzania zmiennej, nie jest już potrzebne definiowanie stałych symbolicznych, ale mam pytanie odnośnie tego, czy mój kod byłby zaakceptowany na zaliczeniu na przykład z programowania w języku C. Albo z drugiej strony czy taki styl i takiego rodzaju algorytmy byłyby zaakceptowane przez potencjalnego pracodawcę.

1

To powinno być proste rozwinięcie oryginalnego kodu.
Wersja "na szybko":

int getline(char s[], int lim)
{
  int c, i, lastp;
  do {
     for (i= 0, lastp = 0; i < lim - 1 && (c = getchar()) != EOF &&  c != '\n'; ++i)
     {
        if (c != ' ' && c != '\t') 
           lastp = i + 1;
     }
     s[lastp] = '\0';
  while (c != EOF && lastp == 0);
  return lastp;
}
0
Gonska Balbinka napisał(a):

Ale funkcja po napotkaniu znaku nowego wiersza...

int getline(char line[],int mx) {
 int c,i=0;
 if( max < 1 ) abort();
 while( (c = getchar()) != EOF && c != '\n' && i<max-1 ) line[i++] = c;
 while( c != EOF && c != '\n' )  c = getchar();
 while( i>0 && (line[i-1]==' ' || line[i-1]=='\t' ) ) i--;
 line[i] = 0;
 return i;
 }
Gonska Balbinka napisał(a):

Poza tym funkcja nie wczytuje znaku nowego wiersza.

To najczęściej jest pożądana cecha.

czy mój kod byłby zaakceptowany na zaliczeniu na przykład z programowania w języku C.

Włąśnie nie wiem, w oczach mi się nie kompilowało, ale to nie oznacza, że z Twoim kodem coś jest nie tak.

Gonska Balbinka napisał(a):

Albo z drugiej strony czy taki styl i takiego rodzaju algorytmy byłyby zaakceptowane przez potencjalnego pracodawcę.

To jest bardzo różnie.

Pozdrawiam

P.S.
Sorrki że nie sprawdzam nawet czy te kody się kompilują, to jest tylko kod poglądowy.

0

Jeśli chodzi o kod, to

  1. jeśli przekazujesz ilość, to uzyj typu unsigned, albo najlepiej size_t
  2. fflush(stdin); jest błędem
  3. z uwag to musisz troszeczkę przejrzeć kod względem mnozenia niepotrzebnego kodu, przykład:
if(i==lbznakow)
{
    line[i-lbznakow]=c;
    i = i-lbznakow;
    i++;
}
else
{
    line[i-lbznakow]=c;
    i=i-lbznakow;
}

można przecież napisać:

 
line[i-lbznakow]=c;
i = i-lbznakow;
if(i==lbznakow)
  i++;

Eliminując kod nadmiarowy spowodujesz, że to co napisałeś będzie czytelniejsze, a dodatkowo jeśli będziesz chciał zmienić później sposób działania, to zmieniasz w jednym miejscu a nie w wielu.
4) brak obsługi błędów (hint: wyjście przez abort nie jest właściwą obsługą błedu)

0

Czym zastąpic fflush(stdin)?. Chodzi o to, żeby funkcja nie wczytywała danych nadmiarowych. To znaczy funkcja wczytuje znaki do bufora o rozmiarze np 10 znaków a reszta znaków w wierszu jest ignorowana.

1 użytkowników online, w tym zalogowanych: 0, gości: 1