Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Реализация функции getline, для считывает потока ввода посимвольно посредством resize / 25 сообщений из 42, страница 1 из 2
28.06.2019, 07:20
    #39831445
MAGRAV
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация функции getline, для считывает потока ввода посимвольно посредством resize
Доброго времени суток господа.
Пишет вам человек, который слишком долго занимался VBA. Но речь не о том зачем это и как с этим бороться.
Речь и сложности восприятия концепции, что теперь казавшийся ранее простецкий string не так прост и с массивами в контексте VBA тоже всё было беззаботно. Но теперь нужно понимать и уметь реализовывать весь этот функционал в C++ без использования соответствующих библиотек. Только char, указатели и работа с памятью. Может что ещё забыл упомянуть.
Пытаюсь решить в образовательных целях следующую задачку:

Считываю поток ввода посимвольно пока не достигну конца потока и возвращаю C-style строку с прочитанными символами. В процессе чтения каждый раз перевыделяю память. Память возвращаемая из функции *getline() и *resize(...) будет освобождена оператором delete[].

Я как то не правильно подаю данные на вход в resize потому, что когда доходит дело до delete[], программа перестаёт выполняться корректно. Подскажите пожалуйста в чём я неправ?

Код: plaintext
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.
#include <iostream>

using namespace std;

char *resize(const char *str, unsigned size, unsigned new_size);
char *getline();

 int main()
{
	setlocale(LC_ALL, "Russian");
        char *b = getline();
	return 0;
}

char *resize(const char *str, unsigned size, unsigned new_size)
{
	char* ans = new char[new_size];
	for (int i = 0; i < size, i < new_size; ++i) {
		*(ans + i) = *(str + i);
	}
	delete[] str;
	return ans;
	/* ... */
}

char *getline()
{
	char c; 
	char * res = new char[0];
	int i = 0;
	unsigned size;
	unsigned new_size;
	//while (std::cin.get(c) && c != '\n' && c != std::cin.eof()){
	while (cin.get(c)) {
		if (c == '\n') {
			break;
		}
		if (i > 0) {
			size = i - 1;
			new_size = (++i) - 1;
			res = resize(res, i, new_size);
			res[i] = c;
		}else {
			res[i] = c;
			++i;
		}
	}
	if (i > 0) res = resize(res, i, ++i);
	res[i] = '\0';
	return res;
}
...
Рейтинг: 0 / 0
28.06.2019, 08:42
    #39831457
Cerebrum
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация функции getline, для считывает потока ввода посимвольно посредством resize
строка в C/C++ в классическом ее понимании всегда должна заканчиваться нуль-терминатором, то есть у вас не может быть по определению

Код: plaintext
1.
2.
int i = 0;
char * res = new char[0];


надо так, хотя бы:
Код: plaintext
1.
2.
3.
int i = 1;
char * res = new char[1];
memset(res, 0, sizeof(char));


но лучше на 1 символ + нуль-терминатор:
Код: plaintext
1.
2.
3.
int i = 2;
char * res = new char[2];
memset(res, 0, sizeof(char) * 2);


В противном случае вы выделяете память в ноль байт и пытаетесь с ней работать. Зачем ?
Намного лучше и эффективнее с точки зрения производительности сократить обращения к менеджеру памяти и копирование до минимума, то есть изначально выделить некоторую область памяти и использовать ее пока она не будет исчерпана. Например, выделяем память на 10 символов + нуль-терминатор:
Код: plaintext
1.
2.
3.
4.
size_t szMemLeft = sizeof(char) * 10UL;
size_t szMemSize = szMemLeft + sizeof(char);
char * res = new char[szMemSize];
memset(res, 0, szMemSize);


По мере заполнения выделенного буфера, вы уменьшаете счетчик szMemLeft и когда он достигнет отметки 0, а символ \n еще не найден, наступает момент перенести содержимое из старого буфера в новый и переинициализировать szMemLeft и szMemSize. Новый буфер опять же лучше выделять сразу больше, например, удвоенного размера по сравнению с предыдущим, чтобы не выделять память под обному байту.

Для копирования участков памяти из старого буфера в новый лучше использовать memcpy_s, а не самописный цикл
...
Рейтинг: 0 / 0
28.06.2019, 08:52
    #39831458
MAGRAV
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация функции getline, для считывает потока ввода посимвольно посредством resize
Cerebrum,
Спасибо!
Успел и сам понять:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
char *getline()
{
	char c; 
    int i = -1;
	int sise = 1;
	char * res = new char[sise];
	while (cin.get(c) && c != '\n' && c != cin.eof()){
		res[++i] = c;
		res = resize(res, sise, ++sise);
	}
	res = resize(res, sise, ++sise);
	res[++i] = '\0';
	return res;
}
...
Рейтинг: 0 / 0
28.06.2019, 09:01
    #39831460
MAGRAV
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация функции getline, для считывает потока ввода посимвольно посредством resize
Cerebrum,
По поводу последнего абзаца с кодом и пояснением отдельное спасибо!

А так мне надо было решить задачку по работе с памятью именно в С++ стайл. А это операторы New+Delete и New[]+Delete[]
Ваше пояснение, как я понимаю, имеет отношение к C-стайлу (malloc, realloc, calloc, free).
...
Рейтинг: 0 / 0
28.06.2019, 10:31
    #39831505
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация функции getline, для считывает потока ввода посимвольно посредством resize
MAGRAVА так мне надо было решить задачку по работе с памятью именно в С++ стайл. А это операторы
New+Delete и New[]+Delete[]
Ваше пояснение, как я понимаю, имеет отношение к C-стайлу (malloc, realloc, calloc, free).

Где ты там увидел у него malloc/free?

"Получить тормоза на ровном месте" это вовсе не "С++ стайл". Я бы (принимая во внимание
современные реалии) выделял память по килобайту, не меньше.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
28.06.2019, 10:44
    #39831513
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация функции getline, для считывает потока ввода посимвольно посредством resize
ИМХО если уж "С++ style", то используй std::vector .

Если "С style", то никаких new, delete, cin, т.к. это С++. Зато в С есть realloc()
...
Рейтинг: 0 / 0
28.06.2019, 10:49
    #39831520
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация функции getline, для считывает потока ввода посимвольно посредством resize
По-хорошему просто взять std::string и не заниматься велосипедостроением
...
Рейтинг: 0 / 0
28.06.2019, 11:01
    #39831524
PetroNotC Sharp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация функции getline, для считывает потока ввода посимвольно посредством resize
Dima TПо-хорошему просто взять std::string и не заниматься велосипедостроением
+1
ну или:
Код: plaintext
1.
std::vector<std::string> dataLine;


IMHO
...
Рейтинг: 0 / 0
30.06.2019, 14:15
    #39832027
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация функции getline, для считывает потока ввода посимвольно посредством resize
MAGRAV, ты уж определись что тебе по настоящему надо. С-style - это достаточно низкоуровневое
программирование где нет iostream.

Вот посмотри как в сях работают с файлами. Там файловые указатели FILE *, handles.

У тебя - какой-то микс С/C++. И правильно пишут дескыть - бери std::string. Бери и используй. Чего-тебе еще?

P.S. Вобщем... или трусы надень. Или крест сними.
...
Рейтинг: 0 / 0
30.06.2019, 15:11
    #39832038
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация функции getline, для считывает потока ввода посимвольно посредством resize
MAGRAV,
Одна из проблем в коде:
Код: plaintext
1.
for (int i = 0; i < size, i < new_size; ++i) {



В выделенном должно быть &&. А иначе только правая часть от "," ограничивает цикл, и при расширении строки вы читаете за пределами выделенного блока памяти, а при сокращении - пишете за его пределами (первое - возможный крэш, второе - гарантированно либо крэш либо поврежденная куча).

Ну а в целом перевыделять память каждый раз всего на один байт больше это перебор.
Если заранее размер не извествен, то выделять нужно в N раз больше чем предыдущий размер. N например 2 (но могут быть и другие).
И начальный размер ставьте какой-нибудь разумный типа 16 или даже 256. Потому что строка эта скорее всего короткоживущая, и лучше сократить кол-во выделений памяти чем экономить несколько сотен байт.
...
Рейтинг: 0 / 0
30.06.2019, 15:18
    #39832039
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация функции getline, для считывает потока ввода посимвольно посредством resize
Ну и:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
#include <iostream>
#include <string>

int main()
{
    std::string line;
    getline(std::cin, line);
    std::cout << line << std::endl;
}


Извините за.

ЗЫ. Хотя в образовательных целях полезно, как вы, извращаться.
...
Рейтинг: 0 / 0
30.06.2019, 18:42
    #39832074
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация функции getline, для считывает потока ввода посимвольно посредством resize
В тему статических анализаторов.

Недавно в форуме появлялся один господин который парил нам PVS-Studio.
Анализатор должен был среагировать на странное появлении операции запятая
в условии цикла.
...
Рейтинг: 0 / 0
30.06.2019, 21:51
    #39832095
полудух
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация функции getline, для считывает потока ввода посимвольно посредством resize
Dima TПо-хорошему просто взять std::string и не заниматься велосипедостроением
+1000000
нифига не понял, зачем писать велосипед
...
Рейтинг: 0 / 0
01.07.2019, 05:54
    #39832107
CEMb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация функции getline, для считывает потока ввода посимвольно посредством resize
полудухнифига не понял, зачем писать велосипедну, например, с чем я последним столкнулся (пока 11-е не вышли) - невозможно передавать в конструктор строки "всё подряд", например чиселки, чтобы на выходе получать строку из числа. int 14 -> "14".

А, так да, после VB, где среда за всем бдит сама, трудно самому следить за деталями
...
Рейтинг: 0 / 0
01.07.2019, 13:00
    #39832228
полудух
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация функции getline, для считывает потока ввода посимвольно посредством resize
CEMb, для этого не нужно писать новую ф-ю string
уже опять же всё написано до нас:
Код: plaintext
1.
string s = to_string(42);


ИЛИ
Код: plaintext
1.
auto s = to_string(42);
...
Рейтинг: 0 / 0
01.07.2019, 17:56
    #39832433
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация функции getline, для считывает потока ввода посимвольно посредством resize
полудухCEMb, для этого не нужно писать новую ф-ю string
уже опять же всё написано до нас:
Сказано же было "пока 11-е не вышли"
...
Рейтинг: 0 / 0
01.07.2019, 19:20
    #39832461
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация функции getline, для считывает потока ввода посимвольно посредством resize
Пора на Haskell переходить. Не?
...
Рейтинг: 0 / 0
01.07.2019, 19:36
    #39832467
полудух
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация функции getline, для считывает потока ввода посимвольно посредством resize
Anatoly MoskovskyполудухCEMb, для этого не нужно писать новую ф-ю string
уже опять же всё написано до нас:
Сказано же было "пока 11-е не вышли"
они вышли 8 лет назад

так мы и C начнём вспоминать, какой там был ад

здесь современная ситуация, где человек пришёл изобретать велосипед в 2019
...
Рейтинг: 0 / 0
01.07.2019, 19:36
    #39832470
полудух
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация функции getline, для считывает потока ввода посимвольно посредством resize
maytonПора на Haskell переходить. Не?
он медленнее (
...
Рейтинг: 0 / 0
01.07.2019, 19:52
    #39832477
PetroNotC Sharp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация функции getline, для считывает потока ввода посимвольно посредством resize
maytonПора на Haskell переходить. Не?c C++ не переходють). Тут очень близко к железу.
...
Рейтинг: 0 / 0
01.07.2019, 20:02
    #39832479
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация функции getline, для считывает потока ввода посимвольно посредством resize
полудухmaytonПора на Haskell переходить. Не?
он медленнее (
Возможно. Просто тут смотрю … борьба за красоту кода идет. Вот и вспомнил к месту.
...
Рейтинг: 0 / 0
01.07.2019, 22:37
    #39832514
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация функции getline, для считывает потока ввода посимвольно посредством resize
полудухтак мы и C начнём вспоминать, какой там был ад

Ад будет когда приходишь в проект, а там никто с указателями не умел работать, и тебе это разгребать
...
Рейтинг: 0 / 0
01.07.2019, 23:09
    #39832520
PetroNotC Sharp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация функции getline, для считывает потока ввода посимвольно посредством resize
Anatoly Moskovsky,
На старые проекты (легаси) наценки)) и молоко за вредность.
...
Рейтинг: 0 / 0
01.07.2019, 23:24
    #39832523
полудух
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация функции getline, для считывает потока ввода посимвольно посредством resize
"переходить" надо на клеточное программирование, вот куда надо стремиться
все эти груды железа ничто, по сравнению с маленькой точкой, которую мы всего 60 лет назад ещё толком разглядеть не могли
это самый совершенный ИИ из доступных нам
и он в "открытом доступе"
...
Рейтинг: 0 / 0
01.07.2019, 23:26
    #39832524
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Реализация функции getline, для считывает потока ввода посимвольно посредством resize
полудух"переходить" надо на клеточное программирование, вот куда надо стремиться
все эти груды железа ничто, по сравнению с маленькой точкой, которую мы всего 60 лет назад ещё толком разглядеть не могли
это самый совершенный ИИ из доступных нам
и он в "открытом доступе"
Я так понимаю... дело в шляпе.

Остался пустяк.
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / Реализация функции getline, для считывает потока ввода посимвольно посредством resize / 25 сообщений из 42, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]