"If statement" is not working properly in c - arrays

I have written a program with a function that looks at a two dimensional array ir_data[60][768].
The While loop should call the "Hotspotberechnung" function only when there is a value that equals or is over 30 in a given row.
"Hotspotberechnung" should store the given row in an array[24][32] and then print the array.
The problem is that the program prints an array without any values equal or over 30.
Unfortunately, I cannot find the mistake on my own.
The While Loop:
int8_t Temperatur[768] = {0};
while (get_ir_data( &Temperatur[0], sizeof(Temperatur)/sizeof(Temperatur[0])) == 0)
{
for(int k=0; k<768; k++)
{
if(Temperatur[k] >= 30)
{
Hotspotberechnung(Temperatur,bild);
}
}
}
The function :
bool Hotspotberechnung(int8_t tabelle1[768],int8_t tabelle2[24][32])
{
int i=0, j=0, x=0, y=0;
for(j=0; j<24; j++) //Tabellen werden gefüllt
{
for(i=0; i<32; i++)
{
tabelle2[j][i] = tabelle1[(j*24)+i];
}
}
for(j=0; j<24; j++)
{
for(i=0; i<32; i++)
{
printf("%d.%d=%d\n",j,i,tabelle2[j][i]);
}
}
get_ir_data :
int8_t get_ir_data(int8_t* data, int n)
{
static uint8_t idx = 0;
if (n != 24 * 32) {
printf("Invalid size of array data!\n");
return -1;
}
memcpy(data, ir_data[idx], n);
idx++;
if (idx >= sizeof(ir_data) / sizeof(*ir_data))
return -2;
return 0;
}

tabelle1[(j*24)+i]
This index calculation is wrong. You need
tabelle1[(j*32)+i]
To verify, calculate the maximal value of (j*24)+i, given the ranges of j (0 to 23) and j (0 to 31). Is it 767?

Related

"If statement" whith array is not working

I wrote a function where a 1-dimensional array (int8_t tabelle1[768]) is transferred into a 2-dimensional array (int8_t tabelle[24][32]).
I now want to find a "Hotspot" in the 2-dimensional array. A "Hotspot" is an 2x2 block in the array (can be located anywhere) where each value of the block has to be equal or over 30.
My Problem is now that my program is not going into my if statement.
The "Checkpoint" is not being printed.
The function:
bool Hotspotberechnung(int8_t tabelle1[768],int8_t tabelle2[24][32])
{
int i=0, j=0, x=0, y=0;
for(j=0; j<24; j++) //Transfer from 1D into 2D
{
for(i=0; i<32; i++)
{
tabelle2[j][i] = tabelle1[(j*32)+i];
}
}
for(y=0; y<24; y++) //search for hotspot
{
for(x=0; x<32; x++)
{
if(tabelle2[y][x]>=30)
{
printf ("1\n"); // checkpoint
if(tabelle2[y][x+1]>=30)
{
if(tabelle2[y+1][x]>=30)
{
if(tabelle2[y+1][x+1]>=30)
{
for(j=0; j<24; j++)
{
for(i=0; i<32; i++)
{
printf("%d.%d=%d\n",j+1,i+1,tabelle2[j][i]);
}
}
printf ("Hotspot!");
return true;
}
else
return false;
}
else
return false;
}
else
return false;
}
else
return false;
}
}
return 0;
}
It never reaches the print, because one of your many returns ends the function much sooner than you think. Specifically the one in the else of the then wich contains the print.
Use a debugger and you will see that.
Alternatively put a print next to each else, make sure to use {} for that. Also put a print after the call to the shown function.
for(y=0; y<24; y++) //search for hotspot
{
for(x=0; x<32; x++)
{
if(tabelle2[y][x]>=30)
{
/* this is not reached for y=0 and x=0, i.e. first */
printf ("1\n"); // checkpoint
/* much code deleted */
}
else
return false;
/* this is reached first,
end of the function,
end of the loop,
no printing ever */
}
}
A few things ...
The kernal width/height is 2, so we have to stop short of the array width/height or we'll go beyond the end of the array
Once we find an element that matches, we have to use that element as the upper left anchor of the 2x2 box
Here's the refactored code (it compiles, but is not tested):
#include <stdio.h>
#include <stdint.h>
#define YMAX 24
#define XMAX 32
#define BOXWID 2
#define MARG (BOXWID - 1)
int
Hotspotberechnung(int8_t tabelle1[YMAX * XMAX], int8_t tabelle2[YMAX][XMAX])
{
int i = 0,
j = 0,
x = 0,
y = 0;
// Transfer from 1D into 2D
for (j = 0; j < YMAX; j++) {
for (i = 0; i < XMAX; i++)
tabelle2[j][i] = tabelle1[(j * XMAX) + i];
}
for (y = 0; y < (YMAX - MARG); y++) {
int8_t *row = tabelle2[y];
for (x = 0; x < (XMAX - MARG); x++) {
if (row[x] < 30)
continue;
int8_t *box = &row[x];
int match = 1;
for (int yoff = 0; yoff < BOXWID; ++yoff) {
for (int xoff = 0; xoff < BOXWID; ++xoff) {
if (box[(yoff * XMAX) + xoff] < 30) {
match = 0;
break;
}
}
if (! match)
break;
}
if (! match)
continue;
for (int yoff = 0; yoff < BOXWID; ++yoff) {
for (int xoff = 0; xoff < BOXWID; ++xoff) {
int8_t val = box[(yoff * XMAX) + xoff];
printf("[%d,%d] = %d\n",y + yoff,x + xoff,val);
}
}
}
}
return 0;
}

Why I can't assign a function return to a matrix element?

Ok, so I need to input a matrix of n elements and to replace each composite number with the closest prime number. I made functions for reading the matrix, showing the matrix, finding if a number is prime or not and finding the closest prime number to a number and they work.
Here is what I did and the problem is that the replacement does not work and I get the error: Process terminated with status -1073741510 (0 minute(s), 18 second(s))
#include <stdio.h>
#include <stdlib.h>
int n;
int readMatrix(int **matrix)
{
for (int i=0; i<n; i++) {
for (int j=0; j<n; j++) {
printf("matrix[%d][%d]=", i, j);
scanf("%d", &matrix[i][j]);
}
}
return matrix;
}
void showMatrix(int **matrix)
{
for (int i=0; i<n; i++) {
for (int j=0; j<n; j++) {
printf("%d ", matrix[i][j]);
}
printf("\n");
}
}
int prime(int a)
{
int c = 0;
for (int i=1; i<a; i++) {
if (a % i == 0) {
c++;
}
}
if (c == 1) {
return 1;
} else return 0;
}
int nearPrime(int b)
{
int lp, bp, ok = 0, p;
lp = b - 1;
bp = b + 1;
while (ok != 1) {
if (prime(lp) == 1) {
ok = 1; break;
}
lp--;
}
ok = 0;
while (ok != 1) {
if (prime(bp) == 1) {
ok = 1; break;
}
bp++;
}
if ((b-lp) < (bp-b)) {
p = lp;
} else p = bp;
return p;
}
int main()
{
int **matrix, aux;
printf("n=");
scanf("%d", &n);
matrix = malloc(n*sizeof(int *));
if (matrix == NULL) exit(1);
for (int i=0; i<n; i++) {
matrix[i] = malloc(n*sizeof(int));
if (matrix[i] == NULL) exit(1);
}
readMatrix(matrix);
showMatrix(matrix);
for (int i=0; i<n; i++) {
for (int j=0; j<n; j++) {
if (prime(matrix[i][j]) == 0 && matrix[i][j] != 1) {
matrix[i][j] = nearPrime(matrix[i][j]);
}
}
}
showMatrix(matrix);
for (int i=0; i<n; i++) free(matrix[i]);
free(matrix);
return 0;
}
Can you tell me why it is not working?
UPDATE
I think I solved it. When checking if a matrix number is prime I also added the condition that it needs to be different than 1 because the program will return 0 when checking if 1 is prime number and it needs to return 1 since 1 is actually a prime number.
Thanks for all the tips!
I think I may have found the issue in your code. The problem lies in your nearPrime function. It will work for most numbers that it takes in as an argument but that is not the case if you input the number 1 for this function. Consider what will happen if it does take in the number 1.
Then, your variable lp = (1 - 1) = 0. When you then further input this into the prime function, it will not return 1 because of the way it is implemented. You then keep on decreasing this number if no prime is found and since the number is now negative, it will never even enter in the for loop in the prime function and the prime function will then always return 0. Thus, you will get stuck in the while(ok != 1) loop for a really long time and that is why your process terminates. To fix this, make sure you check that lp != 0 before proceeding to enter the loop. Since you are also checking for the nearest prime, you also need to check if lp is 0 before returning a value. In short, make the following change to your code.
int nearPrime(int b)
{
int lp, bp, ok = 0, p;
lp = b - 1;
bp = b + 1;
if (lp != 0)
{
while (ok != 1) {
if (prime(lp) == 1) {
ok = 1; break;
}
lp--;
}
}
ok = 0;
while (ok != 1) {
if (prime(bp) == 1) {
ok = 1; break;
}
bp++;
}
if (((b - lp) < (bp - b)) && lp != 0) {
p = lp;
}
else p = bp;
return p;
}
One other thing: your readMatrix function seems to expect a return type of int but you are returning the argument matrix, which is of type int**. Furthermore, in your main code, you are not actually doing anything with your returned value so probably change the return type of your readMatrix function to void (and don't return matrix, of course).

Finding Multiple modes in an Array C programming

I have this homework assignment where the user would enter 10 numbers and would find the mode of those 10 numbers. I got one mode working, my question is I dont know how to start finding multiple modes in the array. EX. 1 1 2 2 3 4 5 6 7 8 The mode of the array is 1,2
Here's the code for the mode
void displayMode(int numArray[])
{
int countArray[MAX];
int modeCount = 0;
int modeNumber;
int i = 0;
int j = 0;
for(i=0; i < MAX; i++)
{
countArray[i] = 0;
}
for(i=0; i < MAX; i++)
{
for (j = 0; j < MAX; j++)
{
if (numArray[i] == numArray[j])
countArray[i]++;
}
}
for (i=0; i < MAX; i++)
{
if (countArray[i] > modeCount)
{
modeCount = countArray[i];
modeNumber = numArray[i];
}
}
if (modeCount > 1)
printf("\nThe mode of the array is: %d",modeNumber);
else
printf("\nThe mode of the array is: None");
}
You need to use a container with size. This is easily achievable with std::vector in C++, but anyway, this is a rough (not memory efficient) implementation in C.
Use modeNumbers instead of one, and create a variable for size:
int modeNumbers[MAX];
size_t modeSize = 0;
Then, append with size:
if (countArray[i] > modeCount)
{
modeCount = countArray[i];
modeNumbers[0] = numArray[i];
modeSize = 1;
} else if (countArray[i] == modeCount) {
modeNumbers[modeSize++] = numArray[i];
}
Finally, use a for loop to output it:
if (modeCount > 1) {
printf("\nThe mode of the array is: ");
for (size_t i = 0; i < modeSize; ++i) { printf("%s%d", i == 0?"":", ", modeNumbers[i]; }
} else {
printf("\nThe mode of the array is: None");
}

how to detect duplicates in arrays & print non duplicates?

void main ()
{
int x[19]={0}, i=0, y=0, u=0, p;
while (i<=19)
{
scanf("%d",&x[i]);
i=i+1;
}
for (i=u;i<=19;i++)
{
if (x[y]!=x[i+1])
p=x[y];
else
{
u++;
y++;
}
}
printf("%d",p);
}
So I used this to check for duplicates & it should print non duplicates, but as you can see this works if all are duplicates but one, as in
x[0]=1 x[1]=1 x[3]=9 x[4]=1 ... x[19]=1;
prints
9
So how to print non duplicates ? Any help ?
This would be the easiest solution, simply nest an additional for-loop. However, this takes O(n^2). Depending on the size of the array, it could be beneficial to look at a fast sort.
void main() {
int x[4] = { 1, 3, 2, 1 };
size_t i, j;
for (i = 0; i < sizeof(x) / sizeof(int); i ++) {
// Note that we only have to go to the last value before i.
for (j = 0; j < i; j ++) {
// We break if the value is a duplicate.
if (x[i] == x[j])
break;
}
// Check if the inner loop was break'ed (j < i) or not (j == i).
if (j == i)
printf("Unique: %i\n", x[i]);
}
}
One more thing: only use sizeof(x) / sizeof(int) if the size of x is known during compilation. This is the case here, but don't use it with malloc.
One of the simplest ways is to sort the array to group the duplicates together. Then, as you go through the array you only print a number if its different from the number that came before.
// Print the unique elements of a sorted array:
for(int i=0; i<N; i++){
if (i-1 >= 0 && arr[i] == arr[i-1]) { continue; }
if (i+1 < N && arr[i] == arr[i+1]) { continue; }
printf("%d\n", arr[i]);
}
To sort the array you can use the qsort function
void main ()
{
int num[20]={0}, i=0, n=0, index_num=0, init_incr=0, unique=0, n_uniq=1, temp, check=0;
while (i<=19)
{
printf("%02d- ",i+1);
scanf("%d",&num[i]);
i=i+1;
}
for (index_num=0;index_num<19;index_num++)
{
for (n=init_incr+index_num;n<19;n++)
{
if (num[index_num]!=num[index_num+1] && num[index_num]!=num[index_num-1])
{
check++;
temp=num[index_num];
unique=temp;
for (;n_uniq<=check;n_uniq++)
printf("\tunique %02d = %d\n", n_uniq, unique);
break;
}
}
}
}

array bucket sort in C

I am trying to read list of numbers from txt file and then sort them with Bucket sort.
so here is my code:
void bucketSort(int array[],int *n)
{
int i, j;
int count[*n];
for (i = 0; i < *n; i++)
count[i] = 0;
for (i = 0; i < *n; i++)
(count[array[i]])++;
for (i = 0, j = 0; i < *n; i++)
for(; count[i] > 0; (count[i])--)
array[j++] = i;
}
int main(int brArg,char *arg[])
{
FILE *ulaz;
ulaz = fopen(arg[1], "r");
int array[100];
int i=0,j,k,n;
while(fscanf(ulaz, "%d", &array[i])!=EOF)i++;
fclose(ulaz);
n=i;
for (j = 0; j<i; j++)
{
printf("Broj: %d\n", array[j]);
}
BucketSort(array,&n);
for (k = 0; k<i; k++)
printf("%d \n", array[i]);
return 0;
}
There are no errors in code,but when i call my function instead of sorted array i get array length random numbers(example: 2 3 5 4,after sorting i get 124520 124520 124520 124520 or some other random number) since i am a beginner,could someone help me with my code and what i did wrong? (sorry for bad english)
As Cool Guy correctly pointed out you have issues with memory access but on top of it the code does not sort anything. First you should read how Bucket Sort actually works.
In general:
You divide the input data among buckets by some criteria that guarantees that the buckets will not mess up the input order
Sort each bucket either using some other sorting method or recursively with bucket sort
Concatenate the sorted data (this is why the first point has the restriction of not messing up the input order)
Here is an example of your original code, I tried to adjust it as little as possible you it is easier for you to understand. This code divides a predefined input array among 3 buckets by range:
[-infinity][-1] -> first bucket
[0;10] -> second bucket
[11;infinity] -> third bucket
then performs Quicksort on each bucket and concatenates the result. I hope this helps to understand how this algorithm works.
#include <stdio.h>
#include <stdlib.h>
struct bucket
{
int count;
int* values;
};
int compareIntegers(const void* first, const void* second)
{
int a = *((int*)first), b = *((int*)second);
if (a == b)
{
return 0;
}
else if (a < b)
{
return -1;
}
else
{
return 1;
}
}
void bucketSort(int array[],int n)
{
struct bucket buckets[3];
int i, j, k;
for (i = 0; i < 3; i++)
{
buckets[i].count = 0;
buckets[i].values = (int*)malloc(sizeof(int) * n);
}
// Divide the unsorted elements among 3 buckets
// < 0 : first
// 0 - 10 : second
// > 10 : third
for (i = 0; i < n; i++)
{
if (array[i] < 0)
{
buckets[0].values[buckets[0].count++] = array[i];
}
else if (array[i] > 10)
{
buckets[2].values[buckets[2].count++] = array[i];
}
else
{
buckets[1].values[buckets[1].count++] = array[i];
}
}
for (k = 0, i = 0; i < 3; i++)
{
// Use Quicksort to sort each bucket individually
qsort(buckets[i].values, buckets[i].count, sizeof(int), &compareIntegers);
for (j = 0; j < buckets[i].count; j++)
{
array[k + j] = buckets[i].values[j];
}
k += buckets[i].count;
free(buckets[i].values);
}
}
int main(int brArg,char *arg[]) {
int array[100] = { -5, -9, 1000, 1, -10, 0, 2, 3, 5, 4, 1234, 7 };
int i = 12,j,k,n;
n=i;
for (j = 0; j<i; j++)
{
printf("Broj: %d\n", array[j]);
}
bucketSort(array, n);
for (k = 0; k<i; k++)
printf("%d \n", array[k]);
return 0;
}
Your code exhibits Undefined Behavior as you try to write into memory location which are not owned by your program.
for (i = 0; i < *n; i++)
(count[array[i]])++;
The above loop is causing the problem. You say that i is 4 which means that *n is also 4 and array contains 2 3 5 4. In the above code,count is an array of *n elements(in this case 4 elements) and the valid indices for the array are count[0],count[1],count[2] and count[3]. Doing
count[array[i]]
when i is zero is okay as it is same as count[2]. This is the same when i is 1 as it would be count[3] . After that ,when i is 4 and 5,count[4] and count[5] are wrong as you try to write to a invalid memory location.
Also,your code dosen't sort the values.

Resources