2010-09-29 2 views
1

Я новичок в языке C. У меня проблема с распределением динамического массива.Использование динамической памяти в C

Я использовал для выделения памяти вне цикла, например a=(int*)malloc(5* sizeof(int));, и все прекрасно работало. Теперь я хочу выделить память каждому элементу один за другим в цикле, используя malloc(), но код не работает.

Я пробовал различные варианты, такие как scanf("%d",a) &a++,scanf("%d",&a[i]); и т. Д., Но не смог. Если кто-нибудь скажет мне, что я делаю неправильно, и полностью объясните мне концепцию, я буду благодарен.

Код, который у меня возникают проблемы с заключается в следующем:

#include <stdio.h> 
#include<stdlib.h> 

int main() 
{ 
    int *a; 
    int i; 
    system("clear"); 

    for(i=0;i<5; i++) 
    { 
    a=(int *)malloc(sizeof(int)); 
    printf("%u",&a); 
    printf("please enter the element in array"); 
    scanf("%d",a[i]); 
    } 
    for(i=0;i<5; i++) 
    { 
    printf("\nthe %d entry in the array %d",i,a[i]); 
    } 
    return 0; 
} 
+2

Правильно ли форматирование действительно так сложно? –

ответ

1

В каждой итерации код переписывает старое значение а. Таким образом, вы теряете адрес ранее размещенной памяти.

Каждый malloc выделяет только sapce для одного int. Неправильно разыменовывать указатель с индексом> 0. Вот почему ваш код дает неопределенное поведение.

+0

thankx для получения помощи сейчас я понимаю это полностью – snakec

0

Проблема в том, что вы создаете новый массив с размером = 1 каждый раз в цикле for.

Таким образом, каждый раз, когда «a» имеет место для одного целого.

+0

Помощь thanx 4, но есть ли способ, которым я могу дать память каждому элементу явно в цикле for – snakec

-1

Все это, честно говоря, катастрофа. Если вы учитесь и полностью сбиты с толку, попробуйте прочитать на C указателях.

Посмотрите, возможно, попробовать что-то вроде этого:

#include <stdio.h> 
#include <stdlib.h> 

int main() 
{ 
int *a; 
int i; 
system("clear"); 

a=(int *)malloc(sizeof(int)*5); 

for(i=0;i<5; i++) 
{ 
    printf("please enter the element in array"); 
    scanf("%d",a+i); 
} 

for(i=0;i<5; i++) 
{ 
    printf("\nthe %d entry in the array %d",i,a[i]); 
} 

return ; 
} 

Или, как я бы это сделать:

#include <vector.h> 
#include <stdio.h> 

int main() 
{ 
    vector<int> a; 
    int i; 
    system("clear"); 

    for(i=0;i<5;i++) 
    { 
    printf("please enter the element in array"); 
    int n; 
    scanf("%d",&n); 
    a.push_back(n); 
    } 

    for(i=0;i<5; i++) 
    { 
    printf("\nthe %d entry in the array %d",i,a[i]); 
    } 

    return ; 
} 

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

+2

Is vector.h C? Похоже, для меня это C++. – Sorpigal

+0

Вектор - это часть STL, и это действительно C++-решение. – rhino

+0

Так я и сделал бы это, и так, как я это сделал, это на C++. Я не знаю, почему кто-либо знал, что торговля будет изучать C вместо C++ (если только это не было для фона, например: обучение объекту-c, C#, ect ...) –

6

Массив - это единственный «объект» (единственная вещь), в котором есть место для множества предметов, одинакового типа.

Ваше ожидание иметь возможность как-то выделить один элемент за раз, неверно, это просто не так, как работают массивы.

Вы должны делать, как вы первый сказал, один malloc() расПредеЛение номер 5 пунктов, а затем просто хранить каждый в надлежащее положение в массиве внутри цикла.

Я бы рекомендовал использовать scanf("%d", &a[i]) для чтения и хранения в массиве. Есть и другие способы написания второго аргумента, но это (на мой взгляд) является самым ясным и лучшим для новичка. Он читается как «адрес i-го элемента в массиве a».Ответ

+0

thanx для help pal это лучший ответ для меня, я не стану пытаться сделать это снова. Thanx pal – snakec

0

UNWIND является объяснение, но вот какой-то код, чтобы продемонстрировать

#include <stdio.h> 
#include <stdlib.h> 

int main(){ 
    int *a; 
    int size = 5; 
    int i = 0; 
    a = malloc(sizeof(int)*size); 

    for(i=0;i<size;i++){ 
      printf("%u: ",&a); 
      printf(" please enter the element in the array> "); 
      scanf("%d", &a[i]); 
    } 

    for(i=0;i<size;i++){ 
      printf("index %d in the array is %d\n",i,a[i]); 
    } 

    free(a); 

    return 0; 
} 
+0

thanx pal, но я сделал это уже – snakec

1

a[i] эквивалентно *(a+i)

scanf нужен адрес, который может быть поставлен здесь с помощью &(a[i]) или просто (a+i). Вместо этого вы передаете его a[i], который относится к данным, хранящимся по адресу (a+i).

+0

Да, другие ответы, кажется, пропустили это по какой-то причине ... – wj32

+0

классная попытка, но я сказал, что я уже пробовал его с & a [i], но он не работал – snakec

1

Как все отметили, вы действительно не хотите выделять каждый элемент массива отдельно. Однако, если, несмотря на советы, вы решили сделать, то вам нужно как массив указателей и отдельные указатели:

#include <stdio.h> 
#include <stdlib.h> 
#include <inttypes.h> 
enum { ARRSIZE = 5 }; 

static void err_exit(const char *msg) 
{ 
    fprintf(stderr, "%s\n", msg); 
    exit(1); 
} 

int main() 
{ 
    int **a; 
    int i; 
    a = (int **)malloc(sizeof(*a)*ARRSIZE); 
    if (a == 0) 
     err_exit("out of memory"); 

    for (i = 0; i < ARRSIZE; i++) 
    { 
    a[i] = (int *)malloc(sizeof(int)); 
    if (a[i] == 0) 
     err_exit("out of memory"); 
    printf("%" PRIuPTR "\n", (uintptr_t)a[i]); // Print allocated address 
    printf("please enter the element in array: "); 
    if (scanf("%d", a[i]) != 1) 
     err_exit("failed to read a valid integer"); 
    } 
    for (i = 0; i < ARRSIZE; i++) 
    { 
    printf("the %d entry in the array %d\n", i, *a[i]); 
    } 
    return 0; 
} 

Дополнительные пункты:

  • Проверить, что malloc() работал.
  • Использование scanf() может привести к миру боли. Вы также должны проверить его статус возврата. Если вы наберете букву вместо цифры, ваш код будет терпеть неудачу довольно ужасно. Как правило, вам лучше использовать fgets() и sscanf().
  • Печать строк в конце строк вывода - особенно в контуре печати.
  • Используйте (свои собственные) стандартизованные функции отчетности об ошибках, аналогичные err_exit(); это всего лишь тривиальная версия того, что может быть гораздо более сложной системой функций, но наличие таких функций означает, что вы менее склонны избегать отчетов об ошибках.
  • Используйте больше свободного пространства. Используйте пространство вокруг большинства операторов. Я рекомендую использовать больший отступ, чем 2 (либо 4, либо 8).
  • Избегайте магических чисел (например, 5), если они появляются более одного раза в коде. 0 и 1 не являются магическими числами.
  • Используйте uintptr_t для печати адресов как целых чисел, а также заголовок <inttypes.h> и имена, определенные там, такие как PRIuPTR. (Я обычно печатаю адреса в шестнадцатеричном формате, но десятичный не является автоматически неправильным.) Заголовок <inttypes.h> - от C99; что может вызвать проблемы, если ваш компилятор C достаточно ретрограден, чтобы не поддерживать C99.
  • Отметьте, что это не рекомендованное решение вашей проблемы с int type; на 64-битной машине он использует намного больше памяти, чем оригинальное решение.
  • Однако, если вы имели дело с массивом отдельно распределенных больших структур, и вы не были уверены заранее, сколько вам нужно, тогда эта схема была бы более разумной. (Однако, вероятно, вы не будете привязаны к размеру фиксированного массива.)
  • Есть те, кто придирается к литой по типу возврата от malloc(). Я предпочитаю это, отчасти потому, что я изучил C на машине, где актерский состав был критическим, и отчасти потому, что актер является обязательным в C++, и мне нравится, когда мой код работает в подмножестве C на C++, даже когда я пишу в C. (Компилятор, о котором идет речь, был до того, как появился стандарт C, это была машина, написанная на языке, malloc() вернулась char *, но битовая диаграмма для char * отличалась от битовой диаграммы для anything * (например, int *) по тому же адресу ,)
0

Я считаю, что нашел решение вашего затруднительного положения. Просто выполните следующие действия:

(1) Перенести утверждение:

a=(int *)malloc(sizeof(int)); 

из для цикла (поставить его непосредственно перед тем, для), & изменить его на:

a=(int *)malloc(5 * sizeof(int)); 

(2) Измените инструкцию scanf на:

scanf("%d",&a[i]); 

Это должно сделать трюк.

Смежные вопросы