Finding Median of an Array - arrays

I am trying to write a C program to find the median of an array, but the task requires to not sort the array. The current code I have works, but fails when there is a repeated number. I am struggling to find a way to account for this case. Any help would be appreciated.
#include <stdio.h>
#include <stdlib.h>
int median_finder(int size, int* data) {
int n1, n2;
int count = 0;
for (int t = 0; t < size; t ++) {
int piv = data[t];
int higher = 0;
int lower = 0;
int median;
if (size % 2 != 0) {
for (int j = 0; j < size; j++) {
if (piv < data[j]) {
higher++;
} else if (piv > data[j]) {
lower++;
}
}
if (higher != 0 && lower == higher) {
printf("MEDIAN: %d\n", piv);
return 0;
}
} else {
//int num = 0;
for (int j = 0; j < size; j++) {
if (piv < data[j]) {
higher++;
} else if (piv > data[j]) {
lower++;
}
}
if (higher != 0 && (lower == size/2 || higher == size/2)) {
count++;
if (count == 1) {
n1 = piv;
} if (count == 2) {
n2 = piv;
}
}
} if (count == 2) {
if (n1 > n2) {
median = n2;
} else {
median = n1;
}
printf("Median: %d\n", median);
return 0;
}
}
}
int main(int argc, char** argv) {
int size = atoi(argv[1]);
argv++;
argv++;
int data[size];
for (int i = 0; i < size; i++) {
data[i] = atoi(argv[i]);
}
median_finder(size, data);
}

The median for an unsorted array with possible duplicate values a of length n is the element with the value a[i] where half of the remaining elements (n-1)/2 (rounded down) are between less than (lt) or less than and equal (lt + eq) to a[i]:
#include <assert.h>
#include <stdio.h>
int median(size_t n, int *a) {
assert(n > 0);
for(size_t i = 0; i < n; i++) {
size_t lt = 0;
size_t eq = 0;
for(size_t j = 0; j < n; j++) {
if(i == j) continue;
if(a[j] < a[i]) lt++;
else if(a[j] == a[i]) eq++;
}
if((n-1)/2 >= lt && (n-1)/2 <= lt + eq)
return a[i];
}
assert(!"BUG");
}
// tap-like
void test(size_t test, int got, int expected) {
printf("%sok %zu\n", got == expected ? "" : "not ", test);
if(got != expected) {
printf(" --\n"
" got: %d\n"
" expected: %d\n"
" ...\n", got, expected);
}
}
int main(void) {
struct {
size_t n;
int *a;
} tests[] = {
{1, (int []) {0}},
{2, (int []) {0, 1}},
{3, (int []) {-1, 0, 1}},
{4, (int []) {-1, 0, 0, 1}},
};
for(int i = 0; i < sizeof tests / sizeof *tests; i++) {
test(i+1, median(tests[i].n, tests[i].a), 0);
}
}

Related

how to get different array in for loop every time?

#include<stdio.h>
#include<time.h>
int main(void)
{
srand(time(NULL));
int answer;
int treatment = rand() % 4;
printf("###발모제 찾기###\n\n");
int cntShowBottle = 0;
int prevCntShowBottle = 0;
int ptr[4] = { 0,0,0,0 };
int bottle[4] = { 0, 0, 0, 0 };
int isincluded = 0;
for (int i = 1; i <= 3; i++)
{
do {
cntShowBottle = rand() % 2 + 2;
} while (cntShowBottle == prevCntShowBottle);
prevCntShowBottle = cntShowBottle;
printf(" %d 번째 시도 : ", i);
for (int j = 0; j < cntShowBottle; j++)
{
int randBottle = rand() % 4;
if (bottle[randBottle] == 0)
{
bottle[randBottle] = 1;
if (randBottle == treatment)
{
isincluded = 1;
}
}
else
{
j--;
}
}
}
if (bottle[0] == ptr[0] && bottle[1] == ptr[1] && bottle[2] == ptr[2] && bottle[3] == ptr[3])
{
int bottle[4] = { 0,0,0,0 };
for (int j = 0; j < cntShowBottle; j++)
{
int randBottle = rand() % 4;
if (bottle[randBottle] == 0)
{
bottle[randBottle] = 1;
if (randBottle == treatment)
{
isincluded = 1;
}
}
else
{
j--;
}
}
}
else
{
return 0;
}
for (int i = 0; i < 4; i++)
{
ptr[i] = bottle[i];
}
for (int k = 0; k < 4; k++)
{
if (bottle[k] == 1)
printf("%d ", k + 1);
}
printf("번 물약을 머리에 바릅니다.\n\n");
if (isincluded == 1)
{
printf("성공!\n");
}
else
{
printf("실패...\n");
}
printf("\n ...계속 하려면 아무키나 누르세요...");
getchar(0);
printf("\n\n발모제는 몇 번? : ");
scanf_s("%d", &answer);
if (answer == treatment+1)
{
printf("\n 정답! \n");
}
else
{
printf("\n 실패! \n 정답은 %d 였습니다.\n", treatment+1);
}
return 0;
}
in this loop, for (int j = 0; j < cntShowBottle; j++), 'bottle' array will be [0,1,1,1] or [1,1,0,0] etc. In this loop, how to get different array without overlapping(like [0,1,1,0] and again [0,1,1,0])?? I tried comparing each elements, if it takes overlapping array, makes 'bottle' array again. but it didn't run properly. please help..

Possible mode error

I've made this program that computes the mean, the median and the mode from an array. Although I've tested with some examples, I found out there might be a case that I have forgotten as for many of the inputs I've tested it works but the testing program that my teacher is using gave me an error for a certain test, but I was not presented with its input. Maybe someone can have a look and see if I am making a mistake at the mode point of the code:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
void *safeMalloc(int n) {
void *p = malloc(n);
if (p == NULL) {
printf("Error: malloc(%d) failed. Out of memory?\n", n);
exit(EXIT_FAILURE);
}
return p;
}
int main(int argc, char *argv[]) {
int n, i;
scanf("%d", &n);
int *array = safeMalloc(n * sizeof(int));
for (i = 0; i < n; i++) {
int value;
scanf("%d", &value);
array[i] = value;
}
//mean
double mean;
double sum = 0;
for (i = 0; i < n; i++) {
sum = sum + (double)array[i];
}
mean = sum / n;
printf("mean: %.2f\n", mean);
//median
float temp;
int j;
for (i = 0; i < n; i++)
for (j = i + 1; j < n; j++) {
if (array[i] > array[j]) {
temp = array[j];
array[j] = array[i];
array[i] = temp;
}
}
printf("median: %d\n", array[n / 2]);
//mode
int val = array[0], noOfRepetitions = 1, valMax = array[0], maxRepetitions = 1, possibleMax = 1;
for (i = 1; i < n; i++) {
if (array[i] == val) {
noOfRepetitions++;
}
if (array[i] != val) {
val = array[i];
noOfRepetitions = 1;
}
if (noOfRepetitions == possibleMax) {
maxRepetitions = 1;
continue;
}
if (noOfRepetitions > maxRepetitions) {
valMax = val;
maxRepetitions = noOfRepetitions;
possibleMax = maxRepetitions;
}
}
if (maxRepetitions > 1) {
printf("mode: %d\n", valMax);
} else {
printf("mode: NONE\n");
}
return 0;
}
My idea for mode was because the numbers are sorted when just transverse it. If the next element is the same as the previous one, increase the noOfRepetitions. If the noOfRepetition is bigger than the maxRepetitions until now, replace with that. Also store the last maximum val needed if we have for example more than 2 numbers with the same number of repetitions.
EDIT: The mode of an array should return the number with the maximum number of occurrences in the array.If we have 2 or more number with the same number of maximum occurrences , there isn't a mode on that array.
I've discovered my mistake. I didn't think of the case when I have numbers with same maximum frequency and after that came one with lower frequency but still bigger than others. For example : 1 1 1 2 2 2 3 3 4 5 6.With my code , the result would have been 3 . I just needed to change the comparison of noOfRepetitions with oldMaxRepetition.
There seems to be no purpose for the variable possibleMax. You should just remove these lines:
if(noOfRepetitions==possibleMax){
maxRepetitions=1;
continue;
}
They cause maxRepetitions to be reset erroneously.
You could detect if the distribution is multimodal and print all mode values:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
void *safeMalloc(int n) {
void *p = malloc(n);
if (p == NULL) {
printf("Error: malloc(%d) failed. Out of memory?\n", n);
exit(EXIT_FAILURE);
}
return p;
}
int main(int argc, char *argv[]) {
int n, i;
if (scanf("%d", &n) != 1 || n <= 0)
return 1;
int *array = safeMalloc(n * sizeof(int));
for (i = 0; i < n; i++) {
if (scanf("%d", &array[i]) != 1)
return 1;
}
//mean
double sum = 0;
for (i = 0; i < n; i++) {
sum = sum + (double)array[i];
}
printf("mean: %.2f\n", sum / n);
//median
int j;
for (i = 0; i < n; i++) {
for (j = i + 1; j < n; j++) {
if (array[i] > array[j]) {
int temp = array[j];
array[j] = array[i];
array[i] = temp;
}
}
}
printf("median: %d\n", array[n / 2]);
//mode
int val = array[0], noOfRepetitions = 1, valMax = array[0], maxRepetitions = 1;
for (i = 1; i < n; i++) {
if (array[i] == val) {
noOfRepetitions++;
if (noOfRepetitions > maxRepetitions) {
valMax = val;
maxRepetitions = noOfRepetitions;
}
} else {
val = array[i];
noOfRepetitions = 1;
}
}
if (maxRepetitions == 1) {
printf("mode: NONE\n");
} else {
printf("mode: %d", valMax);
val = array[0];
noOfRepetitions = 1;
for (i = 1; i < n; i++) {
if (array[i] == val) {
noOfRepetitions++;
} else {
if (noOfRepetition == maxRepetitions && val != valMax) {
printf(", %d", val);
}
val = array[i];
noOfRepetitions = 1;
}
}
if (noOfRepetition == maxRepetitions && val != valMax) {
printf(", %d", val);
}
printf("\n");
}
return 0;
}
Your code to search a mode seems too complicated. Compare this:
//mode
int val = array[0], noOfRepetitions = 1,
valMax = array[0], maxRepetitions = 1;
for (i = 1; i < n; i++) {
if (array[i] == val) {
if (++noOfRepetitions > maxRepetitions) {
valMax = val;
maxRepetitions = noOfRepetitions;
}
}
else
{
val = array[i];
noOfRepetitions = 1;
}
}
It's probably the simplest code to do what you need, but it overwrites maxVal and maxRepetitions much too often.
The following version overwrites the two 'max' variables only once per each new maximum found – at the cost of duplicating some part of code:
//mode
int val = array[0], noOfRepetitions = 1,
valMax = array[0], maxRepetitions = 1;
for (i = 1; i < n; i++) {
if (array[i] == val) {
++noOfRepetitions;
}
else
{
if (noOfRepetitions > maxRepetitions) {
valMax = val;
maxRepetitions = noOfRepetitions;
}
val = array[i];
noOfRepetitions = 1;
}
}
if (noOfRepetitions > maxRepetitions) {
valMax = val;
maxRepetitions = noOfRepetitions;
}

Comparing sorting methods in C

I have to compare these 3 sorting functions (bubble, insertion, and selection), in their worst, best, and the random possible way to sort an array (when talking about the idea of numbers of comparison).
I built and ran the program. The compiler is working, everything seems fine. The problem is that after the cmd window appears, nothing happens. The program is not returning anything (neither 0 (because of return 0) or writing sth in the file). How can I fix it?
#include <stdio.h>
#include <stdlib.h>
int b[11000];
int w[11000];
int r[11000];
int n;
int comp;
int attr;
FILE*f;
//CREAREA SIRURILOR
//best, worst, random
void sir(int n)
{ int i;
for(i=0; i<n; i++)
{
b[i] = i;
r[i] = rand() % n;
w[i] = n-i-1;
}
}
//INSERTION SORT
void insertion (int a[1000])
{
int j, i, index;
comp = 0;
attr = 0;
for (i = 0; i < n; i++)
{
index = a[i];
j = i;
attr+=1;
while ((j > 0) && (a[j-1] > index))
{ comp++;
a[j] = a[j-1];
j = j-1;
attr+=1;
}
while ((j > 0) || (a[j-1] > index))
{ comp++;
}
a[j] = index;
attr++;
}
fprintf(f,"\t%d\t", comp);
fprintf(f,"\t%d\t", attr);
fprintf(f,"\t%d\t", attr+comp);
}
//Selection Sort
void selection (int a[1000])
{
int j, i, min, temp;
comp = 0;
attr = 0;
for (i = 0; i < n-1; i++)
{
min = i;
for (j = i+1; j < n; j++){
comp++;
if (a[j] < a[min])
min = j;
}
temp = a[i];
a[i] = a[min];
a[min] = temp;
attr+=3;
}
fprintf(f,"\t%d\t", comp);
fprintf(f,"\t%d\t", attr);
fprintf(f,"\t%d\t", attr+comp);
}
//Bubble Sort
void bubblesort (int array[2000])
{
int sorted;
int swap,d;
int c;
comp = 0;
attr = 0;
for (c = 0 ; c < ( n - 1 ); c++)
{
for (d = 0; d < n - c - 1; d++)
{
comp++;
if (array[d] > array[d + 1])
{
swap = array[d];
array[d] = array[d + 1];
array[d + 1] = swap;
attr += 3;
}
}
}
fprintf(f,"\t %d\t", comp);
fprintf(f,"\t %d\t", attr);
fprintf(f,"\t%d\t", attr+comp);
}
void InsertionSort()
{
insertion(b);
insertion(r);
insertion(w);
}
void SelectionSort()
{
selection(b);
selection(r);
selection(w);
}
void BubbleSort()
{
bubblesort(b);
bubblesort(r);
bubblesort(w);
}
int main ()
{
f = fopen("iesire.txt","w+");
if(f == NULL)
{
printf("Error!");
exit(-1);
}
fprintf(f,"\n Bubble Sort\t\n");
fprintf(f,"\tBest\t\t\t\t\t\tAverage\t\t\t\t\t\tWorst\t\t\n");
fprintf(f,"\tComparatii\t\tAtribuiri\t\tComp+Atr\t\tComparatii\t\tAtribuiri\t\tComp+Atr\t\tComparatii\t\tAtribuiri\t\tComp+Atr\n");
for (n = 100; n<=10000; n+=500)
{
sir(n);
BubbleSort();
fprintf(f,"\n");
}
fprintf(f,"\n\n Selection Sort\t\n");
fprintf(f,"\tBest\t\t\t\t\t\tAverage\t\t\t\t\t\tWorst\t\t\n");
fprintf(f,"\tComparatii\t\tAtribuiri\t\tComp+Atr\t\tComparatii\t\tAtribuiri\t\tComp+Atr\t\tComparatii\t\tAtribuiri\t\tComp+Atr\n");
for (n = 100; n<=10000; n+=500)
{
sir(n);
InsertionSort();
fprintf(f,"\n");
}
fprintf(f,"\n\n Insertion Sort\t\n");
fprintf(f,"\tBest\t\t\t\t\t\tAverage\t\t\t\t\t\tWorst\t\t\n");
fprintf(f,"\tComparatii\t\tAtribuiri\t\tComp+Atr\t\tComparatii\t\tAtribuiri\t\tComp+Atr\t\tComparatii\t\tAtribuiri\t\tComp+Atr\n");
for (n = 100; n<=10000; n+=500)
{
sir(n);
SelectionSort();
fprintf(f,"\n");
}
fclose(f);
printf(" Result: 'iesire.txt'.");
return 0;
}

How to blur a .pgm file?

I've written this code, which is supposed to blur a .pgm file. Works perfectly on Linux, but it gives a wrong result on Windows. The program should be run like this: "filter.exe enb.pgm enb_filtered.pgm qs 3", where the 4th argument can be qs/cnt/ins, depending on what sorting algorithm wants the user to use, while the 5th one it's an odd number and gives the width of the blurring window (it should go at least until 21). 1st argument is our .exe, the 2nd one is the initial image, while the 3rd one is the final image. On Linux, the result is the expected one, while on Windows the enb.filtered.pgm file is all black and it has wrong dimensions. Can you, guys, help me?
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#define HI(num) (((num) & 0x0000FF00) >> 8)
#define LO(num) ((num) & 0x000000FF)
typedef struct _PGMData {
int row;
int col;
int max_gray;
int **matrix;
} PGMData;
void quick_sort (int *a, int n) {
int i, j, p, t;
if (n < 2)
return;
p = a[n / 2];
for (i = 0, j = n - 1;; i++, j--) {
while (a[i] < p)
i++;
while (p < a[j])
j--;
if (i >= j)
break;
t = a[i];
a[i] = a[j];
a[j] = t;
}
quick_sort(a, i);
quick_sort(a + i, n - i);
}
void insertion_sort (int *a, int n) {
int i, j, t;
for (i = 1; i < n; i++) {
t = a[i];
for (j = i; j > 0 && t < a[j - 1]; j--) {
a[j] = a[j - 1];
}
a[j] = t;
}
}
void counting_sort(int *array, int n)
{
int i, j, k, min, max, *count;
min = max = array[0];
for(i=1; i < n; i++) {
if ( array[i] < min ) {
min = array[i];
}
else if ( array[i] > max ) {
max = array[i];
}
}
count = (int *)calloc(max - min + 1, sizeof(int));
for(i = 0, k = 0; i < n; i++) {
count[array[i] - min]++;
}
for(i = min; i <= max; i++) {
for(j = 0; j < count[i - min]; j++) {
array[k++] = i;
}
}
free(count);
}
int **allocate_dynamic_matrix(int row, int col)
{
int **ret_val;
int i;
ret_val = (int **)malloc(sizeof(int *) * row);
if (ret_val == NULL) {
perror("memory allocation failure");
exit(EXIT_FAILURE);
}
for (i = 0; i < row; ++i) {
ret_val[i] = (int *)malloc(sizeof(int) * col);
if (ret_val[i] == NULL) {
perror("memory allocation failure");
exit(EXIT_FAILURE);
}
}
return ret_val;
}
void deallocate_dynamic_matrix(int **matrix, int row)
{
int i;
for (i = 0; i < row; ++i)
free(matrix[i]);
free(matrix);
}
void SkipComments(FILE *fp)
{
int ch;
char line[100];
while ((ch = fgetc(fp)) != EOF && isspace(ch))
;
if (ch == '#') {
fgets(line, sizeof(line), fp);
SkipComments(fp);
} else
fseek(fp, -1, SEEK_CUR);
}
PGMData* readPGM(FILE *pgmFile, PGMData *data)
{
char version[3];
int i, j;
int lo, hi;
fgets(version, sizeof(version), pgmFile);
if (strcmp(version, "P5")) {
fprintf(stderr, "Wrong file type!\n");
exit(EXIT_FAILURE);
}
SkipComments(pgmFile);
fscanf(pgmFile, "%d", &(data->col));
SkipComments(pgmFile);
fscanf(pgmFile, "%d", &(data->row));
SkipComments(pgmFile);
fscanf(pgmFile, "%d", &(data->max_gray));
fgetc(pgmFile);
data->matrix = allocate_dynamic_matrix(data->row, data->col);
if (data->max_gray > 255)
for (i = 0; i < data->row; ++i)
for (j = 0; j < data->col; ++j) {
hi = fgetc(pgmFile);
lo = fgetc(pgmFile);
data->matrix[i][j] = (hi << 8) + lo;
}
else
for (i = 0; i < data->row; ++i)
for (j = 0; j < data->col; ++j) {
lo = fgetc(pgmFile);
data->matrix[i][j] = lo;
}
fclose(pgmFile);
return data;
}
/*and for writing*/
void writePGM(const char *filename, const PGMData *data)
{
FILE *pgmFile;
int i, j;
int hi, lo;
pgmFile = fopen(filename, "wb");
if (pgmFile == NULL) {
perror("cannot open file to write");
exit(EXIT_FAILURE);
}
fprintf(pgmFile, "P5 ");
fprintf(pgmFile, "%d %d ", data->col, data->row);
fprintf(pgmFile, "%d ", data->max_gray);
if (data->max_gray > 255) {
for (i = 0; i < data->row; ++i) {
for (j = 0; j < data->col; ++j) {
hi = HI(data->matrix[i][j]);
lo = LO(data->matrix[i][j]);
fputc(hi, pgmFile);
fputc(lo, pgmFile);
}
}
} else {
for (i = 0; i < data->row; ++i)
for (j = 0; j < data->col; ++j) {
lo = LO(data->matrix[i][j]);
fputc(lo, pgmFile);
}
}
fclose(pgmFile);
deallocate_dynamic_matrix(data->matrix, data->row);
}
int main ( int argc, char *argv[] )
{
PGMData *initialImage, *finalImage;
int **initialMatrix=NULL, **finalMatrix=NULL;
int n=atoi(argv[4]);
int i, j, k, l, counter;
int *buffer=NULL;
//Time count
clock_t start, end;
double cpu_time_used;
start = clock();
if ( argc != 5 ) /* argc should be 5 for correct execution */
{
/* We print argv[0] assuming it is the program name */
printf( "usage: %s filename", argv[0] );
}
else
{
// We assume argv[1] is a filename to open
FILE *file = fopen( argv[1], "r" );
/* fopen returns 0, the NULL pointer, on failure */
if ( !file )
{
printf( "Could not open file\n" );
}
else
{ initialImage = (PGMData *)malloc(1 * sizeof(PGMData));
initialImage = readPGM (file, initialImage);
initialMatrix = (int **)malloc(initialImage->row * sizeof(int*));
for(i = 0; i < initialImage->row; i++) {
initialMatrix[i] = (int *)malloc(initialImage->col * sizeof(int));
}
finalMatrix = (int **)malloc(initialImage->row * sizeof(int*));
for(i = 0; i < initialImage->row; i++) {
finalMatrix[i] = (int *)malloc(initialImage->col * sizeof(int));
}
if (initialMatrix == NULL || finalMatrix == NULL) {
puts ("Unable to allocate memory for matrix");
}
for (i = 0; i < initialImage->row; i++){
for (j = 0; j < initialImage->col; j++){
initialMatrix[i][j] = initialImage->matrix[i][j];
}
}
buffer = (int *) malloc(n * n * sizeof (int));
if (buffer == NULL) {
puts ("Unable to allocate memory for buffer");
}
for (i = 0; i < initialImage->row; i++){
for (j = 0; j < initialImage->col; j++){
counter = 0;
for (k = -(n/2); k <= n/2; k++){
for (l = -(n/2); l <= n/2; l++){
/*top left corner*/ if (i-k <= 0 && j-l <= 0) {
buffer[counter]=initialMatrix[0][0];
}
/*left side*/ else if (i-k <= 0 && j-l >= 0 && j-l <= initialImage->col-1) {
buffer[counter]=initialMatrix[0][j-l];
}
/*top side*/ else if (j-l <= 0 && i-k >= 0 && i-k <= initialImage->row-1) {
buffer[counter]=initialMatrix[i-k][0];
}
/*bottom left corner*/ else if (j-l <= 0 && i-k >= initialImage->row-1) {
buffer[counter]=initialMatrix[initialImage->row-1][0];
}
/*top right corner*/ else if (i-k <= 0 && j-l >= initialImage->col-1) {
buffer[counter]=initialMatrix[0][initialImage->col-1];
}
/*bottom side*/ else if (i-k >= initialImage->row-1 && j-l >= 0 && j-l <=initialImage->col-1) {
buffer[counter]=initialMatrix[initialImage->row-1][j-l];
}
/*right side*/ else if (j-l >= initialImage->col-1 && i-k >= 0 && i-k <=initialImage->row-1) {
buffer[counter]=initialMatrix[i-k][initialImage->col-1];
}
/*bottom right corner*/ else if (j-l >= initialImage->col-1 && i-k >= initialImage->row-1) {
buffer[counter]=initialMatrix[initialImage->row-1][initialImage->col-1];
}
/*rest*/ else {
buffer[counter]=initialMatrix[i-k][j-l];
}
counter++;
}
}
if(!strcmp(argv[3], "ins")) {
insertion_sort (buffer, n*n);
}
else if(!strcmp(argv[3], "qs")) {
quick_sort (buffer, n*n);
}
else if(!strcmp(argv[3], "cnt")) {
counting_sort (buffer, n*n);
}
else {
puts ("Unknown sorting algorithm");
}
finalMatrix[i][j] = buffer [n * n/2];
}
}
finalImage = (PGMData *)malloc(1 * sizeof(PGMData));
finalImage->col=initialImage->col;
finalImage->row=initialImage->row;
finalImage->max_gray = initialImage->max_gray;
finalImage->matrix = finalMatrix;
writePGM (argv[2], finalImage);
deallocate_dynamic_matrix(initialMatrix, initialImage->row);
deallocate_dynamic_matrix(initialImage->matrix, initialImage->row);
free(buffer);
free(initialImage);
free(finalImage);
}
}
end = clock();
cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
printf ("Execution time: %f seconds\n", cpu_time_used);
}

Pointers and Dynamic Memory

I have a function that returns a pointer to an array. I'm running it in a loop and free() seems to be giving me problems. I'm not sure where, but it appears that somewhere in the main loop the memory that I'm trying to free is being used. I'm using Xcode 3.2.1 in 10.6 | Debug | x86_64 build.
The program will run through the main loop one time; the second time it encounters the free() it gives me the following error:
malloc: *** error for object 0x100100180: incorrect checksum for freed object -
object was probably modified after being freed.
Can someone point out (no pun intended) what I'm doing wrong with pointers here?
Here is the program:
int main(int argc, char **argv) {
int *partition;
int lowerLimit;
int upperLimit;
// snip ... got lowerLimit and upperLimit from console arguments
// this is the 'main loop':
for (int i = lowerLimit; i <= upperLimit; i += 2) {
partition = goldbachPartition(i);
printOutput(partition[0], partition[1], i);
free(partition); // I get problems on the second iteration here
}
return 0;
}
int *goldbachPartition(int x) {
int solved = 0;
int y, z;
int *primes;
int *result;
result = intAlloc(2);
primes = atkinsPrimes(x);
for (int i = intCount(primes)-1; i >= 0; i--) {
y = primes[i];
for (int j = 0; j < y; j++) {
z = primes[j];
if (z + y >= x) {
break;
}
}
if (z + y == x) {
solved = 1;
result[0] = y;
result[1] = z;
break;
} else if (y == z) {
result[0] = 0;
result[1] = 0;
break;
}
}
free(primes);
return result;
}
int *atkinsPrimes(int limit) {
int *primes;
int *initialPrimes;
int *filtered;
int *results;
int counter = 0;
int sqrtLimit;
int xLimit;
int resultsSize;
primes = intAlloc(limit+1);
intFillArray(primes, limit+1, 0);
sqrtLimit = floor(sqrt(limit));
xLimit = floor(sqrt((limit+1) / 2));
// these loops are part of the Atkins Sieve implementation
for (int x = 1; x < xLimit; x++) {
int xx = x*x;
for (int y = 1; y < sqrtLimit; y++) {
int yy = y*y;
int n = 3*xx + yy;
if (n <= limit && n % 12 == 7) {
primes[n] = (primes[n] == 1) ? 0 : 1;
}
n += xx;
if (n <= limit && (n % 12 == 1 || n % 12 == 5)) {
primes[n] = (primes[n] == 1) ? 0 : 1;
}
if (x > y) {
n -= xx + 2*yy;
if (n <= limit && n % 12 == 11) {
primes[n] = (primes[n] == 1) ? 0 : 1;
}
}
}
}
for (int n = 5; n < limit; n++) {
if (primes[n] == 1) {
for (int k = n*n; k < limit; k += n*n) {
primes[k] = 0;
}
}
}
initialPrimes = intAlloc(2);
if (limit >= 2) {
initialPrimes[counter++] = 2;
}
if (limit >= 3) {
initialPrimes[counter++] = 3;
}
filtered = intFilterArrayKeys(primes, limit+1);
results = intMergeArrays(initialPrimes, filtered, counter, trueCount(primes, limit+1));
resultsSize = counter + trueCount(primes, limit+1);
free(primes);
free(initialPrimes);
free(filtered);
results[resultsSize] = 0;
return results;
}
int trueCount(int *subject, int arraySize) {
int count = 0;
for (int i = 0; i < arraySize; i++) {
if (subject[i] == 1) {
count++;
}
}
return count;
}
int intCount(int *subject) {
// warning: expects 0 terminated array.
int count = 0;
while (*subject++ != 0) {
count++;
}
return count;
}
void intFillArray(int *subject, int arraySize, int value) {
for (int i = 0; i < arraySize; i++) {
subject[i] = value;
}
}
int *intFilterArrayKeys(int *subject, int arraySize) {
int *filtered;
int count = 0;
filtered = intAlloc(trueCount(subject, arraySize));
for (int i = 0; i < arraySize; i++) {
if (subject[i] == 1) {
filtered[count++] = i;
}
}
return filtered;
}
int *intMergeArrays(int *subject1, int *subject2, int arraySize1, int arraySize2) {
int *merge;
int count = 0;
merge = intAlloc(arraySize1 + arraySize2);
for (int i = 0; i < arraySize1; i++) {
merge[count++] = subject1[i];
}
for (int i = 0; i < arraySize2; i++) {
merge[count++] = subject2[i];
}
return merge;
}
int *intAlloc(int amount) {
int *ptr;
ptr = (int *)malloc(amount * sizeof(int));
if (ptr == NULL) {
printf("Error: NULL pointer\n");
}
return ptr;
}
void printOutput(int num1, int num2, int rep) {
if (num1 == 0) {
printf("%d: No solution\n", rep);
exit(0);
} else {
printf("%d = %d + %d\n", rep, num1, num2);
}
}
Why is intAlloc not returning int* ?
int *intAlloc(int amount) {
int *ptr;
ptr = (int *)malloc(amount * sizeof(int));
if(ptr == NULL) {
printf("Error: NULL pointer\n");
exit(1);
}
return ptr; //like this
}
EDIT (after your update):
On atkinsPrimes() where is filtered being intAlloc()ed?
int *atkinsPrimes(int limit) {
int *primes;
int *initialPrimes;
int *filtered;
int *results;
int resultsSize;
primes = intAlloc(limit+1);
// ...
initialPrimes = intAlloc(2);
// ...
resultsSize = counter + trueCount(primes, limit+1);
free(primes);
free(initialPrimes);
free(filtered); // Where was it intAlloc()ed?
results[resultsSize] = 0; // make the array 0-terminated to make it easier to work with
return results;
}
EDIT (after your N-th update):
This is a compilable version of your code. It ran smooth on my machine, no crashes. Compiled with g++ (due to declarations of variables inside the for statement):
g++ (Debian 4.3.2-1.1) 4.3.2
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int *goldbachPartition(int x);
int *atkinsPrimes(int limit);
int trueCount(int *subject, int arraySize);
int intCount(int *subject) ;
void intFillArray(int *subject, int arraySize, int value);
int *intFilterArrayKeys(int *subject, int arraySize);
int *intAlloc(int amount);
void printOutput(int num1, int num2, int rep) ;
int *intMergeArrays(int *subject1, int *subject2, int arraySize1, int arraySize2);
int main(int argc, char **argv) {
if (argc < 3) {
printf("Usage: ./program <lower> <upper>\n");
return 0;
}
int *partition;
int lowerLimit = atoi(argv[1]);
int upperLimit = atoi(argv[2]);
// snip ... got lowerLimit and upperLimit from console arguments
// this is the 'main loop':
for (int i = lowerLimit; i <= upperLimit; i += 2) {
partition = goldbachPartition(i);
printOutput(partition[0], partition[1], i);
free(partition); // I get problems on the second iteration here
}
return 0;
}
int *goldbachPartition(int x) {
int solved = 0;
int y, z;
int *primes;
int *result;
result = intAlloc(2);
primes = atkinsPrimes(x);
for (int i = intCount(primes)-1; i >= 0; i--) {
y = primes[i];
for (int j = 0; j < y; j++) {
z = primes[j];
if (z + y >= x) {
break;
}
}
if (z + y == x) {
solved = 1;
result[0] = y;
result[1] = z;
break;
} else if (y == z) {
result[0] = 0;
result[1] = 0;
break;
}
}
free(primes);
return result;
}
int *atkinsPrimes(int limit) {
int *primes;
int *initialPrimes;
int *filtered;
int *results;
int counter = 0;
int sqrtLimit;
int xLimit;
int resultsSize;
primes = intAlloc(limit+1);
intFillArray(primes, limit+1, 0);
sqrtLimit = floor(sqrt(limit));
xLimit = floor(sqrt((limit+1) / 2));
for (int x = 1; x < xLimit; x++) {
int xx = x*x;
for (int y = 1; y < sqrtLimit; y++) {
int yy = y*y;
int n = 3*xx + yy;
if (n <= limit && n % 12 == 7) {
primes[n] = (primes[n] == 1) ? 0 : 1;
}
n += xx;
if (n <= limit && (n % 12 == 1 || n % 12 == 5)) {
primes[n] = (primes[n] == 1) ? 0 : 1;
}
if (x > y) {
n -= xx + 2*yy;
if (n <= limit && n % 12 == 11) {
primes[n] = (primes[n] == 1) ? 0 : 1;
}
}
}
}
for (int n = 5; n < limit; n++) {
if (primes[n] == 1) {
for (int k = n*n; k < limit; k += n*n) {
primes[k] = 0;
}
}
}
initialPrimes = intAlloc(2);
if (limit >= 2) {
initialPrimes[counter++] = 2;
}
if (limit >= 3) {
initialPrimes[counter++] = 3;
}
filtered = intFilterArrayKeys(primes, limit+1);
results = intMergeArrays(initialPrimes, filtered, counter, trueCount(primes, limit+1));
resultsSize = counter + trueCount(primes, limit+1);
free(primes);
free(initialPrimes);
free(filtered);
results[resultsSize] = 0;
return results;
}
int trueCount(int *subject, int arraySize) {
int count = 0;
for (int i = 0; i < arraySize; i++) {
if (subject[i] == 1) {
count++;
}
}
return count;
}
int intCount(int *subject) {
// warning: expects 0 terminated array.
int count = 0;
while (*subject++ != 0) {
count++;
}
return count;
}
void intFillArray(int *subject, int arraySize, int value) {
for (int i = 0; i < arraySize; i++) {
subject[i] = value;
}
}
int *intFilterArrayKeys(int *subject, int arraySize) {
int *filtered;
int count = 0;
filtered = intAlloc(trueCount(subject, arraySize));
for (int i = 0; i < arraySize; i++) {
if (subject[i] == 1) {
filtered[count++] = i;
}
}
return filtered;
}
int *intMergeArrays(int *subject1, int *subject2, int arraySize1, int arraySize2) {
int *merge;
int count = 0;
merge = intAlloc(arraySize1 + arraySize2);
for (int i = 0; i < arraySize1; i++) {
merge[count++] = subject1[i];
}
for (int i = 0; i < arraySize2; i++) {
merge[count++] = subject2[i];
}
return merge;
}
int *intAlloc(int amount) {
int *ptr;
ptr = (int *)malloc(amount * sizeof(int));
if (ptr == NULL) {
printf("Error: NULL pointer\n");
}
return ptr;
}
void printOutput(int num1, int num2, int rep) {
if (num1 == 0) {
printf("%d: No solution\n", rep);
exit(0);
} else {
printf("%d = %d + %d\n", rep, num1, num2);
}
}
Since you are still omitting some source, I can only imagine that the problem is hidden there.
EDIT: (my last update)
To assist your debugging, you should replace your main() function by the one below:
int main(int argc, char **argv)
{
int *primes = NULL;
primes = atkinsPrimes(44); // Evil magic number
free(primes);
return 0;
}
Having a minimal example to reproduce the behavior you pointed out is much better then the whole thing. Have fun with atkinsPrimes(44)

Resources