Форум программистов, компьютерный форум, киберфорум
C для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.83/141: Рейтинг темы: голосов - 141, средняя оценка - 4.83
12 / 12 / 3
Регистрация: 27.07.2012
Сообщений: 208
1

Динамическое выделение памяти под строку

27.08.2012, 16:32. Показов 28005. Ответов 13
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Требуется написать функцию, которая считывает строку, предварительно выдели под неё память и в случае нехватки, первоначально выделенной памяти, перевыделить память.

Написал вот так, но почему-то выскакивает ошибка:

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
char *  Read(void){
    char ch;
    int i = 0;
    int size = 40;
    char *result;
    
    result = (char *) realloc(NULL,size);
    if(!result){
        cout << "memory error.\n";
        exit(1);
    }
    
    while(!isspace(ch = getchar())){
        result[i++] = ch;
        
        if(i == size){
            size*=2;
            
            if(!(result = (char *) realloc(result,1000000000000000000))){
                cout << "memory error.\n";
                exit(1);
            }
        }
    }
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
27.08.2012, 16:32
Ответы с готовыми решениями:

Динамическое выделение памяти под вводимую строку
Здравствуйте, дорогие! Я написал функцию, которая получает вводимую строку, динамически выделяя...

Динамическое выделение памяти под массив
Здравствуйте, помогите пожалуйста сделать в процедуре input динамическое выделение памяти под...

Динамическое выделение памяти под файл
Дали задание считать масив чисел с файла Ф1, сделать над ним некоторые действия и получившийся...

Динамическое выделение памяти под массив
Доброго времени! Требуется ввести размер массива с клав-ры, заполнить массив - изменить его размер...

13
12 / 12 / 3
Регистрация: 27.07.2012
Сообщений: 208
27.08.2012, 16:34  [ТС] 2
В функции должна появиться строка "error" на экране, после чего программа должна завершиться. НО вместо этого получается какая-то ошибка. Вот фото:
Миниатюры
Динамическое выделение памяти под строку  
0
96 / 748 / 279
Регистрация: 11.04.2012
Сообщений: 971
27.08.2012, 16:57 3
Более надежный пример с точки зрения выделения памяти:
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
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <ctype.h>
 
int main()
{
    char* str = NULL; size_t size = 32;
    if ((str = (char*)malloc(size)) == NULL)
        printf("Unable to allocate 256 bytes of memory for character buffer\n");
 
    int n = 0;
 
    for (;;)
    {
        char ch = '\0'; 
        while ((ch = _getch()) && !isspace(ch) && n < size)
        {
            str[n] = ch;
            printf("%c",str[n++]);
        }
 
        if ((str = (char*)realloc(str, size + 32)) == NULL)
            printf("Unable to reallocate memory for character buffer\n");
 
        printf("\n\n%s\n",str);
 
        size+=32;
    }
 
    _getch();
 
    return 0;
}
2
12 / 12 / 3
Регистрация: 27.07.2012
Сообщений: 208
27.08.2012, 17:38  [ТС] 4
А что у меня за ошибка получается? С чем это связано?
0
96 / 748 / 279
Регистрация: 11.04.2012
Сообщений: 971
27.08.2012, 17:40 5
С выделением астрономического количества байтов при выполнении realloc'а.
0
12 / 12 / 3
Регистрация: 27.07.2012
Сообщений: 208
27.08.2012, 17:43  [ТС] 6
Чем этот способ надёжнее?
0
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
12736 / 7566 / 1764
Регистрация: 25.07.2009
Сообщений: 13,954
27.08.2012, 17:43 7
Цитата Сообщение от bgm313 Посмотреть сообщение
А что у меня за ошибка получается? С чем это связано?
Цитата Сообщение от bgm313 Посмотреть сообщение
char ch;
попробуйте, как int объявить...
2
12 / 12 / 3
Регистрация: 27.07.2012
Сообщений: 208
27.08.2012, 17:44  [ТС] 8
Цитата Сообщение от zitxbit Посмотреть сообщение
С выделением астрономического количества байтов при выполнении realloc'а.
В результате такого количество выделения байтов, я хотел получить нулевой указатель, вывеси ошибку и завершить программу. Но вместо этого получил ошибку.
0
96 / 748 / 279
Регистрация: 11.04.2012
Сообщений: 971
27.08.2012, 17:45 9
Динамическое выделение память происходит при каждой итерации цикла по 32 байта см. переменную size
0
12 / 12 / 3
Регистрация: 27.07.2012
Сообщений: 208
27.08.2012, 17:47  [ТС] 10
Цитата Сообщение от easybudda Посмотреть сообщение
попробуйте, как int объявить...
ЗАРАБОТАЛО! Вы могли бы объяснить почему объявление переменной как char вызывало ошибку?
0
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
12736 / 7566 / 1764
Регистрация: 25.07.2009
Сообщений: 13,954
27.08.2012, 18:00 11
bgm313, функция getchar объявлена возвращающей значение типа int. Мало того, при возникновении ошибки или по окончании ввода возвращает значение EOF тоже типа int. При присвоении его переменной типа char происходит отбрасывание старших разрядов, на что по сути он и ругается. Где-то в мелкостудии эти проверки отключаются, но это при условии, что точно понимаешь, что делаешь. А так пусть лучше ругается...
1
12 / 12 / 3
Регистрация: 27.07.2012
Сообщений: 208
27.08.2012, 18:11  [ТС] 12
Вообще странно, что возникают ошибки. Это же не какой-нибудь C#.
0
310 / 233 / 15
Регистрация: 01.07.2011
Сообщений: 812
Записей в блоге: 1
27.08.2012, 22:04 13
Цитата Сообщение от bgm313 Посмотреть сообщение
В результате такого количество выделения байтов, я хотел получить нулевой указатель, вывеси ошибку и завершить программу. Но вместо этого получил ошибку.
О-о-о, мсье знает толк в экзотических развлечениях!
Завершение ввода (EOF) имеет тип int.
0
0 / 0 / 0
Регистрация: 29.01.2017
Сообщений: 1
30.01.2017, 01:36 14
Доделал вариант zitxbit в виде метода структурного типа.

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
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
 
// определяем структуру для хранения строк
struct MyString {
    // сама строка
    char *string;
    // её длина в символах
    size_t sizec;
    // взято под неё байт памяти
    size_t sizeb;
};
 
// Метод динамически выделяет память для строки кусками по 32 байта
struct MyString getMyStr() {
    struct MyString myStr;
    myStr.string = NULL;
    // выбираем минимальный размер строки в 32 байта
    myStr.sizeb = 32;
    myStr.sizec = 0;
    short memoryTest = 1;
    // изначально рабочая переменная пустая
    char ch = '\0';
    // проверяем память перед первым выделением
    if ((myStr.string = (char *) malloc(myStr.sizeb)) == NULL) {
        memoryTest = 0;
        printf("Unable to allocate %d bytes of memory for character buffer\n", myStr.sizeb);
    }
    while (1) {
        // если тест памяти 0, то мы сразу выходим и возвращаем 0
        while (memoryTest != 0 && ch != 13 && myStr.sizec < myStr.sizeb - 1) {
            ch = (char) _getch();
            myStr.string[myStr.sizec] = ch;
            myStr.sizec++;
        }
        // если при попытке расширения памяти неудача, то выходим с ошибкой
        if (memoryTest == 1 && (myStr.string = (char *) realloc(myStr.string, myStr.sizeb + 32)) == NULL)
            memoryTest = 0;
        // если нажат ввод или ошибка памяти - выходим
        if ((ch == 13) || memoryTest == 0) {
            if (memoryTest == 0) {
                // будет возвращён 0 - код ошибки
                myStr.string = NULL;
                myStr.sizeb = 0;
                myStr.sizec = 0;
                printf("Unable to reallocate memory for character buffer.\n");
            }
            if (ch == 13) {
                myStr.string[myStr.sizec] = '\0';
                // возвратим длину строки без символа окончания
                myStr.sizec--;
            }
            puts(myStr.string);
            return myStr;
        } else {
            myStr.sizeb += 32;
        }
    }
}
 
int main() {
    struct MyString testStr;
    testStr = getMyStr();
    printf("V stroke %d simbolov.\n", testStr.sizec);
    printf("V stroke %d bytov.\n", testStr.sizeb);
    printf("Poluchena stroka: %s\n", testStr.string);
    free(testStr.string);
    return 0;
}
Добавлено через 1 час 54 минуты
Цитата Сообщение от temnojed Посмотреть сообщение
Доделал вариант zitxbit в виде метода структурного типа.

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
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
 
// определяем структуру для хранения строк
struct MyString {
    // сама строка
    char *string;
    // её длина в символах
    size_t sizec;
    // взято под неё байт памяти
    size_t sizeb;
};
 
// Метод динамически выделяет память для строки кусками по 32 байта
struct MyString getMyStr() {
    struct MyString myStr;
    myStr.string = NULL;
    // выбираем минимальный размер строки в 32 байта
    myStr.sizeb = 32;
    myStr.sizec = 0;
    short memoryTest = 1;
    // изначально рабочая переменная пустая
    char ch = '\0';
    // проверяем память перед первым выделением
    if ((myStr.string = (char *) malloc(myStr.sizeb)) == NULL) {
        memoryTest = 0;
        printf("Unable to allocate %d bytes of memory for character buffer\n", myStr.sizeb);
    }
    while (1) {
        // если тест памяти 0, то мы сразу выходим и возвращаем 0
        while (memoryTest != 0 && ch != 13 && myStr.sizec < myStr.sizeb - 1) {
            ch = (char) _getch();
            myStr.string[myStr.sizec] = ch;
            myStr.sizec++;
        }
        // если при попытке расширения памяти неудача, то выходим с ошибкой
        if (memoryTest == 1 && (myStr.string = (char *) realloc(myStr.string, myStr.sizeb + 32)) == NULL)
            memoryTest = 0;
        // если нажат ввод или ошибка памяти - выходим
        if ((ch == 13) || memoryTest == 0) {
            if (memoryTest == 0) {
                // будет возвращён 0 - код ошибки
                myStr.string = NULL;
                myStr.sizeb = 0;
                myStr.sizec = 0;
                printf("Unable to reallocate memory for character buffer.\n");
            }
            if (ch == 13) {
                // вместо enter записываем \0
myStr.string[myStr.sizec-1] = '\0';
 
                // возвратим длину строки без символа окончания
                myStr.sizec--;
            }
            puts(myStr.string);
            return myStr;
        } else {
            myStr.sizeb += 32;
        }
    }
}
 
int main() {
    struct MyString testStr;
    testStr = getMyStr();
    printf("V stroke %d simbolov.\n", testStr.sizec);
    printf("V stroke %d bytov.\n", testStr.sizeb);
    printf("Poluchena stroka: %s\n", testStr.string);
    free(testStr.string);
    return 0;
}
Вместо:
Цитата Сообщение от temnojed Посмотреть сообщение
50 myStr.string[myStr.sizec] = '\0';
Поставить:
// вместо enter записываем \0
myStr.string[myStr.sizec-1] = '\0';

Иначе она enter тоже посчитает.
0
30.01.2017, 01:36
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
30.01.2017, 01:36
Помогаю со студенческими работами здесь

Динамическое выделение памяти под структуры
Такая ситуация. Необходимо написать функцию ввода структуры c консоли void vvod(student &amp;man). Так...

Динамическое выделение памяти под структуру
Задание, выделить динамически память под структуру и вывести список того что мы внесли туда....

Динамическое выделение памяти под массива стуктур
Есть структура struct DATA { char number; char name; char team; int point1; int point2;...

Динамическое выделение памяти под массив структур
Подскажите, пожалуйста, как верно выделить память под массив структур, размер которого вводится в...


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

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru