LINUX.ORG.RU

K&R Задача 1.16

 ,


0

1

Всем привет. Сразу сорри за нубизм, я только учусь. Пытаюсь решить задачу:

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

#define MAXLINE 2

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

int main() {

    int len;
    int max;
    char c;

    char *buf;
    char *longest;
    max = 0;

    while ((len = _getline(buf, MAXLINE)) > 0) {

        if (buf[len-1] != '\n')
            while ((c = getchar()) != EOF && c != '\n')
                buf[len++] = c;

        buf[len+1] = '\0';

        if (len > max) {
            max = len;
            if ((longest = malloc(sizeof(char) * len)) == NULL)
                printf("error alloc memory");

            copy(longest, buf);
            longest[len] = '\0';
        }
    }
    if (max > 0)
        printf("%d\n%s", max, longest);

    return 0;
}

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

void copy(char to[], char from[]) {
    int i;
    i = 0;
    while ((to[i] = from[i]) != '\0')
        i++;
}

Но почему-то ловлю сегфолт при выводе longest. В чем дело?

Deleted

Последнее исправление: Deleted (всего исправлений: 2)
Ответ на: комментарий от MKuznetsov

И чем тебе форк поможет? Делать по форку каждый раз, как буфера не хватает, а потом по пулу пидов высчитывать длину? Но это не решит проблему сохранения содержимого буфера. А пидов не так уж и много...

Единственным рабочим вариантом, ограничивающим суммарный размер строк размером свободного объема на HDD, является запись на диск. Все остальные варианты имеют значительно худшее ограничение (даже до размера оперативы не дотянут).

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Cactus64k

Где написано что sizeof(char) == 1?

В стандарте. Все остальные размеры вычисляются в этих.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

И чем тебе форк поможет? Делать по форку каждый раз, как буфера не хватает, а потом по пулу пидов высчитывать длину? Но это не решит проблему сохранения содержимого буфера. А пидов не так уж и много...

я-ж говорю, что это __экзаменационная__ задача. В словах «Unix C Programmer» важны все 3. То есть тупо в лоб оно не решается :-)

MKuznetsov ★★★★★
()
Ответ на: комментарий от Eddy_Em

Угу. Пишем модуль ведра, предоставляющий новый сисвызов...

а потом пытаемся его собрать в BSD и идём улицу мести?

PS/ всё на уровне классики - керниган,ричи,пайк

MKuznetsov ★★★★★
()
Ответ на: комментарий от Cactus64k

Где написано что sizeof(char) == 1? Мб это тебе твой любимый компилятор сказал? Не верь ему.

6.5.3.4 The sizeof operator

[...]

3 When applied to an operand that has type char, unsigned char, or signed char, (or a qualified version thereof) the result is 1. [...]

Утечки тут нет. Иди изучай описание функций. После realloc нельзя использовать старый адрес памяти а, не переменную, в которой этот адрес хранился.

realloc не освобождает уже выделенную память, если выделить новый блок не удалось.

AptGet ★★★
()
Ответ на: комментарий от MKuznetsov

«Огласите весь список!»

mmap, calloc - нельзя? memcpy как бибилиотечный вызов нельзя или в принципе нельзя память копировать?

AptGet ★★★
()
Ответ на: комментарий от AptGet

Там первая глава, вообще ничего, связанного с alloc, нельзя. memcpy там уже реализован в виде отдельной функции (см. листинг примера).

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от AptGet

Про char да. Чего то меня переклинило на том, что в char может и не быть 8 бит. И с возвращаемым нулем тоже проглядел. Надо перестать писать на лор неспавши. Во всяком случае можно сунуть assert рядом с вызовом realloc. Смысла работать дальше без памяти нет никакого.

Cactus64k
()
Ответ на: комментарий от AptGet

mmap, calloc - нельзя? memcpy как бибилиотечный вызов нельзя или в принципе нельзя память копировать?

mmap,calloc нельзя. Дин.память не трогаем - считаем что hip отсутствует как класс:-)

memcpy - опционально. Просто при отсутствии дин.памяти проще сразу писать в нужные места, а не таскать байты по адресному пространству. Минимизируешь копирование, можешь добавить ещё «Embedded» :-)

MKuznetsov ★★★★★
()

в код не вникал, но вот так делать нельзя

void copy(char to[], char from[]) {
    int i;
    i = 0;
    while ((to[i] = from[i]) != '\0')
        i++;
}
Если по каким-то причинам to будет короче чем from, то ты словишь сегфолт. Такие вещи надо проверять.

Aswed ★★★★★
()

И где вообще у тебя выделяется память на buf?

Aswed ★★★★★
()
Ответ на: комментарий от Aswed

Расскажи это авторам glibc, что так делать нельзя: strcpy, внезапно, так же работает.

mix_mix ★★★★★
()

хух, осилил так:

int main() {

    int len, max  = 0;
    char c;
    char *buf     = malloc(MAXLINE * sizeof(char));
    char *longest = malloc(MAXLINE * sizeof(char));

    while ((len = _getline(buf, MAXLINE)) > 0) {

        if (buf[len-1] != '\n')
            while ((c = getchar()) != EOF && c != '\n') {
                buf[len++] = c;
                if (len <= strlen(buf))
                    buf = realloc(buf, len * len);
            }

//      buf[len + 1] = '\0';

        if (len > max) {
            max = len;
            if ((longest = realloc(longest, sizeof(char) * len)) == NULL)
                printf("error realloc");

            copy(longest, buf);
            longest[len] = '\0';
        }
    }
    if (max > 0)
        printf("%d\n%s", max, longest);
    return 0;
}

стоит расслабиться, или есть косяки?))

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

В задаче 1.16 не надо было использовать динамическую память, надо было сделать это[1] на паре статических массивов.

[1]

/* 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. */

Соответственно sizeof(char) от нубаса, четыре дня немогущего написать 20 строчек, выглядит просто потрясающе.

aedeph_ ★★
()
Ответ на: комментарий от aedeph_

Вот-вот, я про ошибку в условии в переводе ещё 4 дня назад написал :) По заданию там вообще немного подправить main нужно было.

grem ★★★★★
()
Ответ на: комментарий от grem

K&R Задача 1.16 (комментарий)

Объём подправки зависит от формализации понятия «как можно больше текста», мой вариант с выводом начала и конца для длинных строк раздувал main в два раза, например.

aedeph_ ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.