Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.70/121: Рейтинг темы: голосов - 121, средняя оценка - 4.70
1 / 1 / 0
Регистрация: 23.09.2015
Сообщений: 42

Реализация своей функции getline

12.10.2015, 09:08. Показов 23952. Ответов 57
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте! Не могу решить задачку.

Постановка:
Реализуйте функцию getline, которая считывает поток ввода посимвольно, пока не достигнет конца потока или не встретит символ переноса строки ('\n'), и возвращает C-style строку с прочитанными символами.

Обратите внимание, что так как размер ввода заранее неизвестен, то вам нужно будет перевыделять память в процессе чтения, если в потоке ввода оказалось больше символов, чем вы ожидали.

Память, возвращенная из функции будет освобождена оператором delete[]. Символ переноса строки ('\n') добавлять в строку не нужно, но не забудьте, что в конце C-style строки должен быть завершающий нулевой символ.

Мой код:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
using namespace std;
 
char *getline()
{
    char *m = new char[1];
    char c;
    cin >> c;
    int i = 1;
 
    while ((c != '\n') && (c != '\0')) {
        m = new char[i];
        m[i-1] = c;
        i++;
    }
    
    m[i] = '\0';
 
    return m;
    
}
 
int main(void) {
    char *example = getline();
    system("pause");
    return 0;
}
Вопрос:
В чем ошибка ? Консоль зависает после перехода на новую строку.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
12.10.2015, 09:08
Ответы с готовыми решениями:

Реализация getline
Добрый день. Новичок в программировании. Нужна помощь. Есть код: #include &lt;iostream&gt; #include &lt;algorithm&gt; #include...

Реализация функций getline
Помогите разобраться , как производится подсчет строк в этом коде. #include &quot;pch.h&quot; #include &lt;iostream&gt; ...

Delim в функции getline()
Здравствуйте. Встала проблема, что при чтении файла нужно использовать разные разделяемые символы (.,!? и т.д.). Пробовал использовать...

57
1 / 1 / 0
Регистрация: 23.09.2015
Сообщений: 42
19.10.2015, 10:55  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от DrOffset Посмотреть сообщение
Вставь вывод размеров (старые и новый) в функцию resize. Отлаживайся на маленьких приращениях, например, - 4. Отладь у себя, прежде чем постить код в систему.
Кликните здесь для просмотра всего текста

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
char * resize(const char *str, unsigned size, unsigned new_size)
{
    char * ptr = new char[new_size]; // новая память
                                     // копируем старые значения в новую память
                                     // с учетом того, что новая память может занимать меньше, чем старая
    cout << "Old size: " << size << endl;
    cout << "New size: " << new_size << endl;
    cout << endl;
 
    unsigned len = min(size, new_size);
    for (unsigned i = 0; i < len; i++)
    {
        ptr[i] = str[i]; // старая память только для чтения, поэтому const не мешает
    }
    delete[] str; // освобождаем старую
 
    return ptr; // возвращаем новую
}


Вроде бы правильно все. Проверил для 10.
Миниатюры
Реализация своей функции getline  
0
21 / 21 / 20
Регистрация: 07.02.2016
Сообщений: 87
21.06.2016, 15:55
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
 
char *getline()
{
    const int BUF_LEN = 50; 
 
    int len = BUF_LEN;
    int i = 0;
 
    char * str=(char*)malloc(BUF_LEN*sizeof(char)), c;  
    while(std::cin.get(c) && c!='\n') {
        if(i==len) 
            str=(char*)realloc(str, len += BUF_LEN);
        str[i++] = c;       
    }
    
    char * rez = new char[i+1];
    for(int j = 0; j < i; ++j)
        rez[j] = str[j];
    rez[i] = 0;
 
    free(str);
    return rez;
}
2
0 / 0 / 0
Регистрация: 22.05.2017
Сообщений: 6
22.05.2017, 02:15
Столкнулся со следующей проблемой Failed test #1. Memory limit exceeded
Не понимания из за чего возникает сия ошибка.

Код:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
using namespace std;
 
char* getline()
{
    char c;
    unsigned i = 0, size = 64;
 
    char* str = (char*)malloc(size * sizeof(char));
    for (cin.get(c); c != '\n'; cin.get(c) , i++)
    {
        if (i == size)
            str = (char*)realloc(str, size += size * sizeof(char));
        str[i] = c;
    }
 
    char* result_str = new char[i];
 
    for (unsigned j = 0; j < i; j++)
        result_str[j] = str[j];
    result_str[i] = '\0';
 
    free(str);
    str = 0;
 
    return result_str;
}
p.s. Код предыдущего поста на этом тесте не валится.
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
22.05.2017, 02:25
WeDin, потому что нужно
C++
1
char* result_str = new char[i+1];
0
0 / 0 / 0
Регистрация: 22.05.2017
Сообщений: 6
22.05.2017, 02:30
TRam_, i там на 1 больше длинны массива.
Но на всякий случай проверил. Ошибка не изменилась.
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
22.05.2017, 03:05
Цитата Сообщение от WeDin Посмотреть сообщение
TRam_, i там на 1 больше длинны массива.
Ну а кто делает вот это ?
C++
1
result_str[i] = '\0';
У меня ошибки после этого исправления не даёт. И да, мож перевести этот на memcpy, быстрее работать будет...

Добавлено через 1 минуту
И я б на односвязный список это перевёл.
0
0 / 0 / 0
Регистрация: 22.05.2017
Сообщений: 6
22.05.2017, 03:26
Верно подправил на
C++
1
    char* result_str = new char[i + 1];
У меня почему то не выдавал ошибки. По этому поводу.

Но ошибка так и осталась Failed test #1. Memory limit exceeded.

Но код из этого поста: Реализация своей функции getline не падает.
0
440 / 432 / 159
Регистрация: 21.05.2016
Сообщений: 1,338
22.05.2017, 03:54
Если память выделяете с помощью malloc, то удалять надо с помощью delete[], а не free
Для result_str пямять выделена и не освобождена
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
22.05.2017, 04:09
Цитата Сообщение от oldnewyear Посмотреть сообщение
Если память выделяете с помощью malloc, то удалять надо с помощью delete[], а не free
C чего это? Если alloc/malloc/realloc, то удаляется через через free. А если new[], то delete[].
1
440 / 432 / 159
Регистрация: 21.05.2016
Сообщений: 1,338
22.05.2017, 04:14
Цитата Сообщение от TRam_ Посмотреть сообщение
C чего это? Если alloc/malloc/realloc, то удаляется через через free. А если new[], то delete[].
точно, не проснулся еще, голова не варит
0
Модератор
Эксперт по электронике
8982 / 6749 / 921
Регистрация: 14.02.2011
Сообщений: 23,876
22.05.2017, 04:28
Цитата Сообщение от WeDin Посмотреть сообщение
size += size * sizeof(char)
а нет ли здесь UB???
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
22.05.2017, 05:42
Вариант с самописным списком
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <iostream>
#include <limits>
 
struct dir_list
{
    dir_list *p_next;
    int len;
    char *str_part;
};
 
void alloc_new_part(dir_list **p_list, const int length)
{
    *p_list = new dir_list();
    (*p_list)->str_part = new char[length];
    (*p_list)->len = length;
    (*p_list)->p_next = nullptr;
}
 
dir_list *free_part(dir_list *p_list)
{
    dir_list *next_p = p_list->p_next;
    delete[] p_list->str_part;
    delete p_list;
    return next_p;
}
 
char* getline()
{
    char c;
    dir_list *begin;
    int part_cnt = 1;
    int local_i = 0;
    int part_size = 50;
    long int full_size = 0;
 
    alloc_new_part(&begin, part_size);
    dir_list *it = begin;
 
    while(std::cin.get(c) && (c != '\n'))
    {
        if(local_i == it->len)
        {
            full_size += local_i;
            part_cnt++;
            if(part_size < (INT_MAX - part_size))
                part_size *= 2;
            alloc_new_part(&(it->p_next), part_size);
            it = it->p_next;
            local_i = 0;
        }
        it->str_part[local_i++] = c;
    }
 
    full_size += local_i;
    it = begin;
    char* result_str = new char[full_size+1];
    long int pos = 0;
 
    for(int i = 0; i < (part_cnt - 1); i++)
    {
        memcpy(result_str + pos, it->str_part, sizeof(char) * it->len);
        pos += it->len;
        it = it->p_next;
    }
    if(local_i > 0)
    {
        memcpy(result_str + pos, it->str_part, sizeof(char) * local_i);
        pos += local_i;
    }
    result_str[pos] = '\0';
 
    while(begin != nullptr)
        begin = free_part(begin);
 
    return result_str;
}
0
0 / 0 / 0
Регистрация: 22.05.2017
Сообщений: 6
22.05.2017, 15:26
ValeryS, да неоднозначно. Поменял.
TRam_, к сожалению, я не обратил на часть условия: пока не достигнет конца потока или не встретит символ переноса строки ('\n')
Поэтому из за отсутствия проверки конца потока, код не проходил тестирование.

Написал два верных решения задачи в стиле C-style и C++.

C++:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
using namespace std;
 
char* resize(const char* str, unsigned size, unsigned new_size)
{
    char* new_str = new char[new_size];
    for (int i = 0; i < new_size && i < size; i++)
    {
        *(new_str + i) = *(str + i);
    }
    delete[] str;
    return new_str;
}
 
char* getline()
{
    char c;
    const unsigned ALLOC_SIZE = 64;
    unsigned i = 0, size = 64;
 
    char* str = new char[size];
    while (cin.get(c) && c != '\n')
    {
        if (i == size)
            str = resize(str, i, size += ALLOC_SIZE);
        str[i++] = c;
    }
 
 
    str[i] = '\0';
 
    return str;
}
C-style:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
using namespace std;
 
char* getline()
{
    char c;
    const unsigned ALLOC_SIZE = 64;
    unsigned i = 0, size = 32;
 
    char* str = (char*)malloc(size);
    while (cin.get(c) && c != '\n')
    {
        if (i == size)
            str = (char*)realloc(str, size += ALLOC_SIZE );
        str[i++] = c;
    }
 
    char* result_str = new char[i + 1];
 
    for (unsigned j = 0; j < i; j++)
        result_str[j] = str[j];
    result_str[i] = '\0';
 
    free(str);
    str = 0;
 
    return result_str;
}

Вопрос почему код C-style:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
using namespace std;
 
char* getline()
{
    char c;
    const unsigned ALLOC_SIZE = 64;
    unsigned i = 0, size = 32;
 
    char* str = (char*)malloc(size);
    while (cin.get(c) && c != '\n')
    {
        if (i == size)
            str = (char*)realloc(str, size += ALLOC_SIZE );
        str[i++] = c;
    }
 
    str[i] = '\0';
 
    return str;
}
при отсутствии выделения памяти через new и копировании массива падает с ошибкой:

Failed test #1. Runtime error:
terminate called after throwing an instance of 'std::logic_error'
what(): You didn't allocate dynamic mamory
Aborted (core dumped)


Как я понимаю и в том и в этом случает память должна выделяться в хипе. Но похоже память выделяется в стеке.
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
22.05.2017, 15:37
WeDin, нет, не из-за этого. Из-за того что malloc/realloc требует освобождения памяти через free(), у вас видимо оставался delete[] в коде.

Добавлено через 1 минуту
И по условию -
Цитата Сообщение от JustForStudy Посмотреть сообщение
Память, возвращенная из функции будет освобождена оператором delete[].
то есть результат realloc'а не будет соответствовать условию задачи.
0
0 / 0 / 0
Регистрация: 22.05.2017
Сообщений: 6
22.05.2017, 15:57
TRam_, с чем связано требование высвобождение памяти после realloc?
В хипе хранятся актуальные данные, в итоге я на них и возвращаю указатель.
Поэтому не совсем понятна логика требующая копировать данные в свежевыделенную память.

p.s. В Visual Studio 2015 работает, в g++ стандарт 2003 года нет
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
22.05.2017, 16:14
WeDin, логика не в том, что память выделенная new[] это не то же самое, что память, выделенная через alloc(), и это важно не в самой функции, а вне её, где вызывается деструктор для этого выделения. И деструктор delete[] не для всех компиляторов делает то же что free().
1
0 / 0 / 0
Регистрация: 22.05.2017
Сообщений: 6
22.05.2017, 16:24
TRam_, тогда возникает вопрос как написать так чтобы использовать C-style подход. И код был рабочим.
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
22.05.2017, 16:43
WeDin, заменить в вызывающей функции delete[] на free().

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

Ну нельзя так делать, чтоб массив конструировался как в С, а деструктор к нему применялся от С++.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
22.05.2017, 16:43

Какой правильный вызов у функции getline()?
FILE *db; char file = &quot;Quiz.csv&quot;; string str; db = fopen(file, &quot;r&quot;); getline(db, str, &quot;/n&quot;); Quiz.cpp|90|error: no matching...

Третий аргумент функции sdt :: getline
Можно ли использовать в качестве третьего аргумента слово в функции std :: getline ? Если можно, то как ? Нужно нечто похожее на это : ...

Отсутствуют экземпляры перегруженной функции getline
не могу решить проблему #define _CRT_SECURE_NO_WARNINGS #include &quot;stdafx.h&quot; #include &quot;conio.h&quot; #include &quot;stdio.h&quot; #include...

Некорректный ввод строк с использованием функции getline
Здравствуйте столкнулся с магической проблемой функция getline(); криво работает когда вызывается с другой функции. #include...

Использование функции в своей программе из своей dll
Среда разработки Visual Studio 2008 Язык C++ Написал dll как в примере на сайте...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
58
Ответ Создать тему
Новые блоги и статьи
Копировать Windows на новый диск на UEFI
damix 17.10.2026
https:/ / uriesk. wordpress. com/ 2016/ 11/ 01/ move-window-10-to-ssd-on-a-uefi-dualboot-system-with-basic-linux-tools/ TL DR Вставляем диск, а старый подключаем через переходник, грузимся с лайва. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru