LINUX.ORG.RU

Вопросы по коду из K&R readlines() strcpy(p, line)

 , ,


0

1

Добрый день!

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

Пожалуйста, помотрите функцию readlines из K&R, страница 109. Я не очень поняла strcpy(p, line). Пожалуйста, исправьте и дополните мои рассуждения:

Предположим input string «Hello world».

- до того как вызвана функция strcpy(p, line), функция readlines() вызывала ( called) фукцию getline(), которая вернула значение переменной i, равное 11. - readlines() путем line[len - 1] убрала newline character '\n', и в итоге line[10] = '\0'; пока все просто и понятно; - дальше readlines() вызывает strcpy(p, line): - правильно я понимаю, что поскольку line заявлена как character array, то когда была вызвана функция getline(line, MAXLEN), то line в данном случае была pointer и в результате array line в фукции realines получила значения «Hello world»; поэтому когда вызывается strcpy(p, line), то line[] = «Hello world», и именно это значение должно быть скопировано в p? Верно ли это?

- также я хотела бы уточнить: p - pointer, то есть получается что strcpy копирует адреса каждой буквы из line в p? или какой именно процесс происходит? Вот сама функция (и плюс ниже getline()):

/* readlines: read input lines */
int readlines(char *lineptr[], int maxlines)
{
    int len, nlines;
    char *p, line[MAXLEN];
    nlines = 0;
    
    while ((len = get_line(line, MAXLEN)) > 0)
    {
        if (nlines >= maxlines || (p = alloc(len)) == NULL)
        {
            return -1;
        }
        else
        {
            line[len - 1] = '\0'; /* delete newline */
            strcpy(p, line);
            lineptr[nlines++] = p;
        }
    }
    return nlines;
}
/* getline: read a line into s, return length */

int get_line (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';
    
    return i;
}

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


Последнее исправление: Ducol (всего исправлений: 1)

...то line[] = «Hello world», и именно это значение должно быть скопировано в p? Верно ли это?

Да, совершенно верно.

p - pointer, то есть получается что strcpy копирует адреса каждой буквы из line в p? или какой именно процесс происходит?

Нет, ни в коем случае. p — pointer, т. е. он указывает на начало некоторого куска памяти, т. е. массива байт (предварительно полученного у ОС функцией alloc()).

Функция strcpy() принимает два указателя на начала соответствующих кусков памяти (массивов байт) и копирует байты подряд из второго в первый, пока не встретит байт, равный нулю (в Си — маркер конца строки). Внимание: «байт, равный нулю» — это не то же самое, что «байт, кодирующий цифру 0».

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 2)

Терминология:

  • array — массив
  • character array — массив символов (очень часто «символ» используется как синоним слову «байт», т. е. это совершенно необязательно человекочитаемые символы)
  • pointer — указатель
  • string — строка
intelfx ★★★★★
()
Ответ на: комментарий от intelfx

Спасибо огромное! Теперь я поняла. До Вашего ответа я думала, что - переменная ( variable) line[] была изначально обозначена именно как массив символов (спасибо Вам за сообщение с терминологией), а не как указатель; - при этом переменная p изначально обозначена как указатель, поэтому не очень поняла их взаимодействие. Да, я изучила, что по большому счету само название массива работает как указатель при использовании, например, в функциях. Спасибо!

Ducol
() автор топика
Ответ на: комментарий от intelfx

Спасибо Вам. Но я смотрю на само свое сообщение и вижу, что формат ввода не сохранился. Я пыталась сделать list вопросов, а получилось все в одну строку. То есть newline character не поддерживатся при вводе текста здесь ) В результате мой текст действительно получился сложночитаемым.

Ducol
() автор топика
Ответ на: комментарий от intelfx

так и скажи что на сиськи повелся ;)

anonymous
()
Ответ на: комментарий от Ducol

Ненене. Переменная line[] — это именно массив, память под который выделяется на стеке при объявлении переменной. А line — это адрес его начала. line — это не совсем переменная; нельзя сделать line = чтонибудь;.

А вот с *p всё по-другому. char *p — это указатель, т. е. переменная, которая хранит адрес. Ты делаешь alloc(), т. е. запрашиваешь у ОС новый свободный кусок памяти (не на стеке, а где-то там) и присваиваешь адрес его начала переменной p.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 3)
Ответ на: комментарий от Ducol

Вот пример кода, который это иллюстрирует. Его полезно запустить под отладчиком в режиме трассировки и посмотреть значения всех переменных после каждой строчки.

void f()
{
    char line[10]; /* на стеке выделилось 10 байт, line -- адрес первого байта из них; в самих 10 байтах -- мусор */

    char *p; /* на стеке выделилось 4 или 8 байт под абстрактрый адрес чего-нибудь; в этих байтах сейчас мусор */

    strcpy(line, "test"); /* первые 5 байт из тех десяти теперь равны 't', 'e', 's', 't' и нулю */

    p = malloc(5); /* переменная p теперь содержит не мусор, а адрес нового куска памяти размером в 5 байт (выделенного операционной системой откуда-то) */

    strcpy(p, line); /* теперь в тех пяти байтах, что мы выделили malloc()'ом (и адрес которых лежит в переменной p) не мусор, а те же самые символы 't', 'e', 's', 't', 0 */
}
intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.