четверг, 9 января 2014 г.

Упражнение 1.16.

    Я долго думал над этим упражнением, но к сожалению не смог его решить ((
Наученный опытом опечаток во время перевода, я глянул на текст оригинала.

Перевод:
Перепишите main предыдущей программы так, чтобы она могла печатать самую длинную строку без каких-либо ограничений на ее размер.

Оригинал:
Revise the main routine of the longest-line program so it will correctly print the length of arbitrary long input lines, and as much as possible of the text.

    Итак, задача упрощается, необходимо напечатать правильную длину строки и как можно больше содержимого этой строки при условии, что сама строка может быть длиннее максимального размера вводимой строки, определенного как MAXLINE. Только непонятно, что подразумевается под main routine, все-таки функция main или главная процедура (рутина) самой программы.

    Переписать функцию main оказалось не так просто. Поэтому, для начала перепишем функцию getstr, которая читает строку из текстового потока и будет возвращать ее правильную длину.

$ vim ex_1_16_4.c
#include <stdio.h>
#define MAXLINE 10 /* уменьшим до 10 размер строки */


int getstr(char line[], int maxline);

void copy(char to[], char from[]);

int main(void)

{
    int len;    /* длина текущей строки */
    int max;    /* длина максимальной из просмотренных строк */
    char line[MAXLINE]; /* текущая строка */
    char longest[MAXLINE];      /* самая длинная строка */

    int i;
    for (i = 0; i < MAXLINE; ++i)
            line[i] = longest[i] = 0;

    max = 0;

    /* есть ли еще строка */
    while ((len = getstr(line, MAXLINE)) > 0 )
    {
        if (len > max)
        {
            max = len;
            copy(longest, line);
        }
    }
    if (max > 0)        /* была ли хоть одна строка? */
    {
        printf("Длина самой длинной строки равна %d символа(ов)\n", max);
        printf("%s\n", longest);
    }

    return 0;
}

/* getline: читает строку в s, возвращает длину */
int getstr(char s[], int lim)
{
    int c;
    int i; /* длина строки */
    int index; /* индекс массива s[] */


    /* Убираем ограничение на длину строки в for-цикле */
   for (i = 0, index = 0; (c = getchar()) != EOF && c != '\n'; ++i)
    {
        /* i продолжает расти при вводе символов
         * даже если массив s[] "почти" полон*/
        if (i < lim - 1)/* массив s[] не должен превышать MAXLINE */
        {
            s[index] = c; /* наполнение массива s[] символами */
            ++index;
        }
    }

    if (c == '\n')
    {
        s[index] = c;
        ++index;
        ++i;
    }
    s[index] = '\0';    /* в конец строки дописывам "0" */
    return i;   /* функция возвращает длину строки */
}

/* copy: копирует из 'from' в 'to'*/
void copy(char to[], char from[])
{
    int i;
    i = 0;
    while ((to[i] = from[i]) != '\0')
        ++i;
}
$ cc -g -O0 -Wall -o a.out ex_1_16_4.c
$ ./a.out
До сих пор мы пользовались готовыми функциями вроде main, getchar и putchar, теперь настала пора нам самим написать несколько функций.<Enter>
Механизм использования функции в Си удобен, легок и эффективен.<Enter>
Нередко вы будете встречать короткие функции, вызываемые лишь единожды; они оформлены в виде функции с одной-единственной целью — получить более ясную программу.<Enter>
<Ctrl>+<D>
Длина самой длинной строки равна 162 символа(ов)
Нередко в

    Для проверки точности полученного результата используем программу wc (print newline, word, and byte counts for each file), о которой упоминалось на 36 странице книги.
$ wc -m -
Нередко вы будете встречать короткие функции, вызываемые лишь единожды; они оформлены в виде функции с одной-единственной целью — получить более ясную программу.<Enter>
<Ctrl>+<D>
162 -

    Снова возвращаемся к функции main. Алгоритм решения упражнения, по условию которого необходимо измененить функцию main, приведен на рисунке ниже.


#include <stdio.h>
#define MAXLINE 10      /* максимальный размер вводимой строки */

int getstr(char line[], int maxline);
void copy(char to[], char from[]);

int main(void)
{
    int len;    /* длина текущей строки */
    int max;    /* длина максимальной из просмотренных строк */
    char line[MAXLINE]; /* текущая строка */
    char longest[MAXLINE];      /* самая длинная строка */
    char temp[MAXLINE]; /* для временного хранения фрагмента потока */

    /* Сигнализировать о том, что текстовый поток имеет длину
     * более, чем объявлено в MAXLINE
     * wait = 1 - предыдущий фрагмент потока больше MAXLINE
     * wait = 0 - предыдущий фрагмент потока меньше или равен MAXLINE*/
    int wait;
    wait = 0;

    int iNt; /* промежуточная длина текстового потока */
    iNt = 0;

    int i; /* для for-цикла */
    for (i = 0; i < MAXLINE; ++i)
        line[i] = longest[i] = temp[i] = 0;

    max = 0;
    /* есть ли еще строка */
    while ((len = getstr(line, MAXLINE)) > 0 )
    {
        if(line[len-1] != '\n')
        {
            if (wait == 0)
                copy(temp, line);
            iNt = iNt + len;
            if (max < iNt)
                max = iNt;
            wait = 1;
        }

        else
        {
            if (wait == 1)
            {
                if (max < (iNt + len))
                {
                    max = iNt + len;
                    copy(longest, temp);
                }
                wait = 0;
            }
            else if (len > max)
            {
                max = len;
                copy(longest, line);
            }
            iNt = 0;
        }
    }
    if (max > 0)        /* была ли хоть одна строка? */
    {
        printf("%s\n", longest);
        printf("Длина самой длинной строки %d символа(ов)\n", max);
    }

    return 0;
}

/* getstr: читает строку в s, возвращает длину */
int getstr(char s[], int lim)
{
    int c, i;


    for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i)
        s[i] = c;
    if (c == '\n')
    {
        s[i] = c;
        ++i;
    }
    s[i] = '\0';        /* в конец строки дописывам "0" */
    return i;   /* функция возвращает длину строки */
}

/* copy: копирует из 'from' в 'to'; to достаточно большой */
void copy(char to[], char from[])
{
    int i;

    i = 0;
    while ((to[i] = from[i]) != '\0')
        ++i;
}

Комментариев нет:

Отправить комментарий