Я пытаюсь создать простое приложение на C, которое будет читать строки из файла, аналогично тому, как я это сделал на C#. Однако я столкнулся с проблемой: когда цикл for выполняется повторно, память для **ptext не выделяется, и я не знаю, как это исправить. Кроме того, количество символов в выделенной памяти почему-то не равно 2 байтам, а может варьироваться. Я не понимаю, почему использование функции *alloc ведет к таким странным результатам. Я проводил проверки на NULL (которые не срабатывали, и я вернул всё как было), и не думаю, что на моем ПК не хватает 3 байтов. Вот часть кода, с которой я работаю: <pre><code class="c">#include <stdio.h> #include <stdlib.h> #define _CRT_SECURE_NO_WARNINGS FILE* create_filestream(const char* filepath, char* buffer); int read_text_in_file(FILE* filestream, char*** ptext, size_t* text_size); int main() { char buffer[32]; FILE* f = create_filestream("map.txt", &buffer); char **text; size_t text_size = NULL; read_text_in_file(f, &text, &text_size); } int read_text_in_file(FILE* filestream, char*** ptext, size_t* text_size){ char buffer[32],* data = NULL; size_t bytes_read, nums = 0, j = 0; *text_size = 0; *ptext = malloc(sizeof(char**)); **ptext = malloc(sizeof(char*)); while (!feof(filestream)) { bytes_read = fread(&buffer, sizeof(char), sizeof(buffer), filestream); if (ferror(filestream) || bytes_read == 0) return -1; for (size_t i = 0; i < bytes_read; i++) { if (buffer[i] == '\0') { nums++; j = 0; if(*ptext = (char**)realloc(*ptext, sizeof(*ptext) + sizeof(char**))) return -2; continue; } (*text_size)++; data = reallo Пожалуйста, объясните, что я делаю неправильно и как можно устранить эти проблемы.
Проблемы, с которыми вы столкнулись, касаются нескольких аспектов управления динамической памятью в языке C. Давайте разберем ваш код и выделим проблемы и места для улучшения. 1. **Неинициализированные указатели**: Переменная `text_size` должна быть типа `size_t`, но вы инициализируете её как `NULL`. Следует использовать правильное значение, например `0`, вместо `NULL` для переменной, которая предназначена для увеличения счётчика. ```c size_t text_size = 0; // Исправлено ``` 2. **Выделение памяти**: В строке `*ptext = malloc(sizeof(char**));` вы выделяете память для указателя на указатели. Это не совсем корректно, так как стоит выделять по количеству строк, а не по количеству указателей. Также стоит учесть, что вы хотите выделить память для множества строк. Исходный фрагмент кода выделяет память для одного указателя. 3. **Функция `realloc`**: Вы используете `realloc` неправильно. Вместо проверок на успех выделения памяти, вы просто возвращаете -2 в случае успеха. Правильный синтаксис должен быть таким: ```c char **temp = realloc(*ptext, (nums + 1) * sizeof(char*)); if (temp == NULL) { // Обработка ошибки, memory allocation failed return -2; } *ptext = temp; ``` 4. **Чтение данных из файла**: При использовании `fread` вы передаете `&buffer`, что неправильно. Вам нужно передать `buffer` без амперсанда, поскольку `buffer` уже является указателем на его первый элемент. 5. **Обработка строки**: У вас не хватает логики для создания и сохранения строк в динамически выделенной памяти. В частности, строки нужно копировать в `*ptext`. 6. **Проблема с передачей аргументов**: Вы неправильно передаете указатель на `ptext` и `text_size` в функции. Вместо `&text` используйте `ptext`, чтобы указывать на указатель, в который будет записываться адрес динамически выделенной памяти. Вот скорректированная версия вашей функции `read_text_in_file`: ```c int read_text_in_file(FILE* filestream, char*** ptext, size_t* text_size) { char buffer[32]; char* data = NULL; size_t bytes_read, nums = 0; *text_size = 0; *ptext = NULL; // Инициализация указателя на указатели while (!feof(filestream)) { bytes_read = fread(buffer, sizeof(char), sizeof(buffer) - 1, filestream); buffer[bytes_read] = '\0'; // Обеспечить завершение строки if (ferror(filestream) || bytes_read == 0) return -1; for (size_t i = 0; i < bytes_read; i++) { if (buffer[i] == '\n') { // Используем '\n' для разделения строк nums++; *text_size += 1; char** temp = realloc(*ptext, nums * sizeof(char*)); if (temp == NULL) { // Обработка ошибки return -2; } *ptext = temp; (*ptext)[nums - 1] = strndup(buffer, i); // Копируем строку buffer[0] = '\0'; // Очищаем буфер break; } } } return 0; // Успех } ``` Обратите внимание на: - Я заменил условие для разделения строк на `'\n'`. - Добавил функцию `strndup()` для дублирования строки. Не забудьте включить `<string.h>`, если вы будете использовать `strdup()`, и очистить память для каждой строки, когда они больше не нужны. Эти изменения должны помочь вам устранить проблемы с памятью и обеспечить правильную обработку строк, извлекаемых из файла.
Ваш вопрос не по C++, а по C, это разные языки.
sizeof(buffer) в функции create_filestream() вернёт размер указателя (4 или 8 байт), а не размер буфера buffer из функции main, т. к. функция create_filestream про него ничего не знает. Скорее всего, это не то, чего Вы хотите.
Строка "if(*ptext = (char**)realloc(*ptext, sizeof(*ptext) + sizeof(char**)))", по-видимому, должна к текущему размеру данных, ассоциированных с *ptext, добавлять размер ещё одного указателя. По факту sizeof(*ptext) - это размер char**, т. е. размер указателя, т. е. у Вас всегда будет здесь или 8 байт (сумма размеров двух указателей на 32-битной платформе), или 16 (на 64-битной). Получить размер массива, который в данный момент ассоциирован с указателем, оператором sizeof() нельзя и в общем случае вообще нельзя, его нужно хранить отдельно.
Перечитайте внимательно главу про обращение с указателями. Пока у Вас каша, которая вряд ли будет работать ожидаемым образом. Нужно чётко понимать, что такое char*, char**, char***, sizeof(ptext), sizeof(*ptext) и т. д.