вторник, 7 января 2014 г.

Символьные массивы

    Чтобы проиллюстрировать использование символьных массивов и работающих с ними функций, авторы книги предлагают написать программу, которая читает набор текстовых строк и печатает самую длинную из них. Схема данной программы:


    while (есть ли еще строка?)
    if (данная строка длиннее самой длинной из предыдущих)
    запомнить ее
    запомнить ее длину
    напечатать самую длинную строку


    Функция getline получает строку, выдает ее длину или нуль если строки нет. Функция copy копирует строку в "надежное" место.
$ vim char_array_1.c
#include <stdio.h>
#define MAXLINE 1000    /* максимальный размер вводимой строки */

int getline(char line[], int MAXLINE);
void copy(char to[], char from[]);

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

    max = 0;
    /* есть ли еще строка */
    while ((len = getline(line, MAXLINE)) > 0 )
        if (len > max) /* данная строка длиннее самой длинной из предыдущих*/
        {
            max = len;  /* запоминаем длину самой длинной строки */
            copy(longest, line);        /* запоминаем самую длинную строку */
        }
    if (max > 0)        /* была ли хоть одна строка? */
        printf("%s", longest);
    return 0;
}

/* getline: читает строку в s, возвращает длину */
int getline(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;
}
$ cc -g -O0 -Wall -o a.out char_array_1.c
char_array_1.c:4:30: error: expected ';', ',' or ')' before numeric constant
char_array_1.c: In function 'main':
char_array_1.c:16:5: warning: passing argument 1 of 'getline' from incompatible pointer type
/usr/include/stdio.h:671:20: note: expected 'char ** __restrict__' but argument is of type 'char *'
char_array_1.c:16:5: warning: passing argument 2 of 'getline' makes pointer from integer without a cast
/usr/include/stdio.h:671:20: note: expected 'size_t * __restrict__' but argument is of type 'int'
char_array_1.c:16:5: error: too few arguments to function 'getline'
/usr/include/stdio.h:671:20: note: declared here
char_array_1.c: At top level:
char_array_1.c:28:5: error: conflicting types for 'getline'
/usr/include/stdio.h:671:20: note: previous declaration of 'getline' was here


    Ошибка в 4 строке на 30 символе сообщает об ожидании компилятором символов ';'или ',', или ')' перед числовой константой. Так как ранее мы определили именованную константу MAXLINE. Использование константы в качестве аргумента в прототипе функции getline недопустимо и является опечаткой во время перевода книги на русский язык. В оригинале книги используется переменная целого типа maxline.
    
    Все последующие ошибки связаны с тем, что функция с именем getline уже объявлена в заголовочном файле /usr/include/stdio.h. Решением будет переименование функции в getstr.

   С учетом указанных изменений текст программы будет выглядеть так:
$ vim char_array_2.c
#include <stdio.h>
#define MAXLINE 1000    /* максимальный размер вводимой строки */

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];      /* самая длинная строка */

    max = 0;
    /* есть ли еще строка */
    while ((len = getstr(line, MAXLINE)) > 0 )
        if (len > max) /* данная строка длиннее самой длинной из предыдущих*/
        {
            max = len;  /* запоминаем длину самой длинной строки */
            copy(longest, line);        /* запоминаем самую длинную строку */
        }
    if (max > 0)        /* была ли хоть одна строка? */
        printf("%s", longest);
    return 0;
}

/* getline: читает строку в 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;
}
$ cc -g -O0 -Wall -o a.out char_array_2.c
    Компиляция прошла без ошибок и предупреждений.
$ ./a.out
До сих пор мы пользовались готовыми функциями вроде main, getchar и putchar, теперь настала пора нам самим написать несколько функций.
Механизм использования функции в Си удобен, легок и эффективен.
Нередко вы будете встречать короткие функции, вызываемые лишь единожды; они оформлены в виде функции с одной-единственной целью — получить более ясную программу.
<Ctrl>+<D>
Нередко вы будете встречать короткие функции, вызываемые лишь единожды; они оформлены в виде функции с одной-единственной целью — получить более ясную программу.

    Программа напечатала самую длиную из трёх, введенных мною, строк.

2 комментария:

  1. Большое спасибо!!!!!

    Однако вы уверены в том, что Использование константы в качестве аргумента в прототипе функции недопустимо?????

    ОтветитьУдалить