Я пытаюсь создать простое приложение на 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) и т. д.