Member 12955853 Ответов: 4

- Моя программа показывает правильные результаты...потом грохот."


Итак, я пытаюсь создать программу, которая выделяет достаточно места для 5 целых чисел, используя malloc и указатель, чтобы действовать как массив, и через функцию я удваиваю размер "массива", используя realloc, вставляя квадрат каждого числа из первых 5 в 5 следующих пробелов. Это трудно объяснить так что вот пример:

Исходный массив перед "realloc"
arr[0]=1
arr[1]=2
arr[2]=3
arr[3]=4
arr[4]=5

После перераспределения и расчетов:

arr[5]=1
arr[6]=2
arr[7]=9
arr[8]=16
arr[9]=25

Таким образом, в основном содержимое массива[x] помещается в квадрат и вставляется в массив[x+5]

Проблема в том, что моя программа работает нормально, я получаю вышеприведенный массив в результате, но как только он показывает результаты, он падает, и я не могу понять почему. Вот мой код:

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


int * double_old(int *old, int old_size, int new_size);

int main(void)
{
	int *old;
	int old_size = 5;
	int new_size;
	
	old=(int*) malloc(old_size*sizeof(int));
	
	
	printf("Enter 5 integers: \n\n\n");
	
	for(old_size = 0; old_size < 5; old_size++)
		{
			scanf("%d", &old[old_size]);	
		}
		
	printf("The original array is: \n");
	
	for(old_size = 0; old_size < 5; old_size++)
		{
			printf("old[%d] = %d\n", old_size, old[old_size]);
		}
		
	printf("\n\n\n");	
	double_old(old, old_size, new_size); 
										
										
	free(old);  
	
}

int * double_old(int *old, int old_size, int new_size)
{		
	int i=5, a=0;
	new_size = old_size*3;
	old = realloc(old, new_size);
	
	printf("The results based on the 5 previous numbers: \n");

	for(;old_size<10;old_size++)
	{
		old[old_size] = old[old_size-i]* old[old_size-i];				
		printf("old[%d] = %d\n", old_size, old[old_size]);
	}
}


Что я уже пробовал:

Последние 2 дня я пытался понять, что делаю не так, но пока не нашел никаких решений. Может быть, это как-то связано с malloc, так как я не совсем понимаю, как он работает, так как я новичок в C и программировании.

Jochen Arndt

Вы уже получили решение от Ричарда.

Но должно быть предупреждение компилятора типа
"нет оператора return в функции, возвращающей Non-void"

Если нет, увеличьте уровень предупреждения компилятора.
С использованием GCC-стена. С помощью VisualStudio используйте /Wall (установите его в настройках проекта).

Наличие таких предупреждений и исправление кода до тех пор, пока все предупреждения не исчезнут, сэкономит вам много времени.

Member 12955853

Решение мистера Ричарда, к сожалению, не сработало. Однако ответ ppolymorphe исправил это для меня. Проблема заключалась в том, что при перераспределении я ставил "old = realloc(old, new_size);"
с "new_size", равным 10. Я думал, что это означает, что перераспределение резервирует пространство для 10 целых чисел, но забыл, что я должен был поставить:
old = realloc(old, new_size*sizeof(int));


Я использую Dev C++ btw, который использует Gcc. Да, я знаю, что это отстой, но это тот, который они сказали нам использовать в университете

Jochen Arndt

Извините, я не проверил ответ и подумал, что это исправило проблему.

Но вы все равно должны установить уровень предупреждения.

Я не знаю Dev C++, но у него должна быть опция конфигурации.
Быстрый поиск предполагает, что он находится на вкладке Инструменты - Параметры компилятора - предупреждения.

Richard MacCutchan

Да, жаль, что я пропустил этот момент.

4 Ответов

Рейтинг:
24

Patrice T

Когда вы выделяете, это 5 целых чисел

old=(int*) malloc(old_size*sizeof(int));

При перераспределении он составляет 15 байт, независимо от размера целого числа.
new_size = old_size*3;
old = realloc(old, new_size);


Member 12955853

О, Кажется, я понимаю, о чем ты. Я изменился:
old = realloc(old, new_size); to
old = realloc(old, new_size*sizeof(int));

и теперь он не разобьется. Спасибо.

nv3

Хорошо подмечено!

Patrice T

Спасибо

Рейтинг:
2

Richard MacCutchan

Вы забыли вернуть обновленный указатель из double_old функция. Код должен быть:

	old = double_old(old, old_size, new_size); 								
										
	free(old);  
	
}

int * double_old(int *old, int old_size, int new_size)
{		
	int i=5, a=0;
	new_size = old_size*3; // why times 3?
	old = realloc(old, new_size);
	
	printf("The results based on the 5 previous numbers: \n");

	for(;old_size<10;old_size++)
	{
		old[old_size] = old[old_size-i]* old[old_size-i];				
		printf("old[%d] = %d\n", old_size, old[old_size]);
	}
    return old; // return the realloc'ed array pointer
}


Member 12955853

Это странно. Я исправил это, как вы сказали, но программа все равно вылетает, как только показывает результаты.
Что касается" old_size*3", то он должен был быть" old_size*2", но я изменил его, чтобы проверить что-то, и забыл изменить его обратно. Вот мой код после исправления:

старый = double_old(старый, old_size, new_size);


бесплатно(старый);
}

инт * double_old(инт *старый, инт old_size, тип int new_size)
{
int i=5;
new_size = old_size*2;
old = realloc(old, new_size);

printf ("результаты, основанные на 5 предыдущих числах: \n");

для(;old_size&ЛТ;new_size;old_size++)
{
старый[old_size] = старик[old_size-я]* старый[old_size-я];
функции printf("старый [на%D] = %Д\П", old_size, старый[old_size]);
}
вернуть старое;
}

Рейтинг:
2

CPallini

Не связывайся со мной. old_size. Пробовать

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


int * double_old(int *old, int old_size);

int main(void)
{
  int *old;
  const int old_size = 5;
  int i;

  old=(int*) malloc(old_size*sizeof(int));


  printf("Enter 5 integers: \n\n\n");

  for(i = 0; i< old_size; i++)
    {
      scanf("%d", &old[i]);
    }

  printf("The original array is: \n");

  for(i = 0; i < old_size; i++)
    {
      printf("old[%d] = %d\n", i, old[i]);
    }

  printf("\n\n\n");
  old = double_old(old, old_size);

  free(old);
}

int * double_old(int *old, int old_size)
{
  int i;
  int new_size = old_size * 2;
  printf("old = %p\n", old);
  old = realloc(old, new_size*sizeof(int));

  printf("The results based on the 5 previous numbers: \n");
  for(i = old_size;i<new_size;i++)
  {
    old[i] = old[i-old_size]* old[i-old_size];
    printf("old[%d] = %d\n", i, old[i]);
  }
  return old;
}


Рейтинг:
1

nv3

Ричард уже указал на ошибку в вашей программе. К этому нечего добавить.

Поскольку вы новичок в программировании, вы должны попытаться с самого начала приобрести правильные привычки. Поэтому я хочу указать вам на пару вещей, которые вы могли бы сделать лучше в этом маленьком примере и которые сделают вещи более понятными для вас и для читателя ваших программ.

1. Именования
Почему вы вызываете указатель на свой массив old Всегда используйте имена, которые говорят что-то о том, что хранится в переменной, структуре или массиве. В этом случае мы не знаем, что именно здесь хранится, так почему бы нам не назвать это values (обратите внимание на использование множественного числа!). А ваша переменная old_size на самом деле должна содержать текущий размер массива, так почему бы нам просто не вызвать ее size.

Теперь перейдем к вашей функции. Основная цель функции-вычислить квадраты всех значений во входном массиве. Так что это должно называться что-то вроде CalcSquares.

2. Будьте последовательны в использовании индексов цикла
В основном вы выделяете массив и должны сразу же установить переменную размера. Мы знаем, что массив имеет такой размер, поэтому сразу же сохраняем его:

int size;
...
size = 5;
values = (int*) malloc (size * sizeof(int));

Не злоупотребляйте size переменная как индекс цикла. Используйте для этого отдельную переменную и ссылайтесь на размер массива всегда и только по вашей переменной размера:
int i:
...
for (i = 0; i < size; ++)
{
   ...
}

Если вы сформируете свои петли таким образом,то будет очень легко определить любые ошибки.

3. Понимаю, передача параметров
Вероятно, самый большой недостаток в вашей программе - это new_size параметр функции old_double. Он передается по значению. Но позже вы используете его так, как будто ожидаете, что он будет передан по ссылке. "По значению"означает, что значение, которое вы установили внутри old_double, никогда не будет передано обратно вызывающему! Если вы хотите, чтобы вызывающий объект знал, каков новый размер массива, используйте передачу "по ссылке" или в обычном старом языке Си, который передает указатель:

int* CalcSquares (int* pValues, int size, int* pNewSize)
{
  int i, newSize;

  // allocate the array extension
  newSize = size * 2;
  pValues = realloc (pValues, newSize * sizeof(int));
  if (pValues == 0)
  {
    *pNewSize = 0;
    return 0;
  }

  // calculate the squares
  for (i = size; i < newSize; ++i)
    pValues [i] = pValue[i-size] * pValue[i-size];

  // return the result
  *pNewSize = newSize;
  return pValues;
}


4. Избегайте печати в ваших рабочих функциях
Вы хотите, чтобы ваша функция выполняла одну конкретную задачу, в этом случае вычисляя квадраты. Не смешивайте эти вещи с печатью. Если вы хотите использовать свою функцию позже в другом контексте, вам, вероятно, не понравится печать внутри функции, но сделайте это где-то снаружи с помощью вызывающего кода.

5. Не делайте выделение памяти сложным
Я предполагаю, что вы делаете это упражнение, чтобы узнать о realloc и это прекрасно. Но в "нормальном" коде вы постарались бы сохранить распределение памяти и интерфейс вашей функции как можно более простыми.


Richard MacCutchan

Как и я, вы упустили тот факт, что realloc звонок был неправильным. См. ответ ppolymorphe.

nv3

Ой, ты совершенно прав, Ричард. Исправил это в своем ответе.

Member 12955853

@nv3 спасибо Вам за все советы, они действительно помогли мне понять концепцию функций. Что касается имен, которые вы упомянули(например, old, old_size), то нам их дал профессор, и я решил пойти с ними, обычно я бы не использовал эти имена, так как они не имеют большого смысла, но я не хочу, чтобы профессор ныл о том, что я не использовал имена переменных, которые мне дали бла-бла-бла... Ты знаешь, что я имею в виду.