This is the algorithm for traversing a matrix in spiral fashion and printing the traversal as an array in Python:
def spiralTraverse(array):
result = []
startRow, endRow = 0, len(array) - 1
startCol, endCol = 0, len(array[0]) - 1
while startRow <= endRow and startCol <= endCol:
for col in range(startCol, endCol + 1):
result.append(array[startRow][col])
for row in range(startRow + 1, endRow + 1):
result.append(array[row][endCol])
for col in reversed(range(startCol, endCol)):
if startRow == endRow:
break
result.append(array[endRow][col])
for row in reversed(range(startRow + 1, endRow)):
if startCol == endCol:
break
result.append(array[row][startCol])
startRow += 1
endRow -= 1
startCol += 1
endCol -= 1
return result
So if sample input is
array = [[1, 2, 3, 4],[12, 13, 14, 5],[11, 16, 15, 6],[10, 9, 8, 7]]
Output will be
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
I am trying to translate this into C with pointers but the function fails to print the final array. The file compiles but with warnings related to the multidimensional array as argument in spiralTraverse().
I call the spiralTraverse function from main() as follows: spiralTraverse(*array[r], r, c), where r=rows and c=cols are number of rows and columns respectively.
This is what I did:
void spiralTraverse(int *vector[], int rows, int cols)
{
int i, indx_col, indx_row;
int indx_array = 0;
int startRow = 0;
int endRow = rows-1;
int startCol = 0;
int endCol = cols-1;
int new_array[rows*cols];
while ((startRow <= endRow) && (startCol <= endCol))
{
for (indx_col=startCol;indx_col<endCol+1;indx_col++)
new_array[indx_array++] = *(*(vector+startRow)+indx_col);
for (indx_row=startRow+1;indx_row<endRow+1;indx_row++)
new_array[indx_array++] = *(*(vector+indx_row)+endCol);
for (indx_col=endCol;indx_col>startCol;indx_col--)
{
if (startRow == endRow)
break;
new_array[indx_array++] = *(*(vector+endRow)+indx_col);
}
for (indx_row=endRow;indx_row>startRow+1;indx_row--)
{
if (startCol == endCol)
break;
new_array[indx_array++] = *(*(vector+indx_row)+startCol);
}
startRow++;
endRow--;
startCol++;
endCol--;
}
puts("");
puts("The array below displays the elements in spiral order");
for (i=0;i<(rows*cols);i++)
printf("%d, ", new_array[i]);
puts("");
}
}
Why is the program failing to print my final one-dimensional array?
Function argument
The file compiles but with warnings related to the multidimensional array as argument in spiralTraverse().
Please refer to those others Q&A for details about the proper way to allocate and pass multidimensional arrays as function parameters in C:
Correctly allocating multi-dimensional arrays
What's the point of VLA anyway?
How to pass a multidimensional array to a function in C and C++
Given the array
int array[][4] = {
{ 1, 2, 3, 4},
{12, 13, 14, 5},
{11, 16, 15, 6},
{10, 9, 8, 7}
};
The function signature could be one of those
// Declaring m as a Variable Length Array (since C99, optional from C11)
void spiral_traverse(int rows, int cols, int m[rows][cols]);
// or as a pointer to arrays of size 4
void spiral_traverse(int rows, int *m[4]);
Keep It Simple
The C implementation of the algorithm has an issue with the extemes of the loops, in particular the second and the third:
for ( indx_row = startRow + 1; indx_row < endRow + 1; indx_row++ )
// ^^^^^^^^^^^^
/* ... */ = *(*(vector+indx_row)+endCol);
for ( indx_col = endCol; indx_col > startCol; indx_col-- )
// ^^^^^^^^^^^^^^^^^
/* ... */ = *(*(vector+endRow)+indx_col);
The last element visited by the first (well, second) loop is vector[endRow][endCol], which is the same one visited first by the other loop.
The following version produces the expected output.
Note that I changed the extremes of the loops.
#include <stdio.h>
void spiral_traverse(int rows, int cols, int m[rows][cols]);
int main(void)
{
int array[][4] = {
{ 1, 2, 3, 4},
{12, 13, 14, 5},
{11, 16, 15, 6},
{10, 9, 8, 7}
};
spiral_traverse(4, 4, array);
spiral_traverse(3, 4, array); // Elements are stored row-major.
}
void spiral_traverse(int rows, int cols, int m[rows][cols])
{ // m is a Variable Length Array ^^^^^^^^^^^^^^^^^
int startRow = 0;
int endRow = rows - 1;
int startCol = 0;
int endCol = cols - 1;
int new_array[rows*cols]; // <-- Another VLA
int i = 0;
while ((startRow <= endRow) && (startCol <= endCol))
{
for (int col = startCol; col < endCol; ++col, ++i)
{ // ^ ^^^^^
new_array[i] = m[startRow][col];
} // ^^^^^^^^^^^^^^^^
for (int row = startRow; row < endRow; ++row, ++i)
{ // ^^^^^^^^^^ ^ ^^^^^
new_array[i] = m[row][endCol];
} // ^^^^^^^^^^^^^^
for (int col = endCol; col > startCol; --col, ++i)
{ // ^^^^^^^^ ^ ^^^^^
new_array[i] = m[endRow][col];
} // ^^^^^^^^^^^^^^
for (int row = endRow; row > startRow; --row, ++i)
{ // ^^^^^^^^ ^ ^^^^^
new_array[i] = m[row][startCol];
} // ^^^^^^^^^^^^^^^^
startRow++;
endRow--;
startCol++;
endCol--;
}
puts("\nThe array below displays the elements in spiral order");
for (i=0;i<(rows*cols);i++)
printf("%d, ", new_array[i]);
putchar('\n');
}
Of course, if the goal is only to print the elements, you don't really need to copy all of them into another array. Also, introducing a function pointer parameter, the function could become more generic (see e.g. here).
This function f is to find common elements in an array and return result array and i am using 4 four loops to accomplish this task which i feel is no the best use of the loops,
Another problem is, how can i determine the size of the returned array so that my loop is within bounds
here is the code
#include <stdio.h>
#include <stdlib.h>
int *f(int first[], int second[], int size_first, int size_second);
int main(void) {
int arr1[]={1, 8, 3, 2, 6};
int arr2[]= {2, 6, 1};
int size1 = sizeof(arr1)/sizeof(arr1[0]);
int size2 = sizeof(arr2)/sizeof(arr2[0]);
int *intersection = f(arr1, arr2, size1, size2);
for(int i=0;i<3; i++){
printf("%d ", intersection[i]);
}
return 0;
}
// function to find common elements in 2 arrays
int *f(int first[], int second[], int size_first, int size_second){
int k=0, count=0;
//loop through the array to find the number common elements and store in count for dynamic memory allocation in future
for(int i=0;i<size_first;i++){
for(int j=0;j<size_second;j++){
if(first[i]==second[j]){
count ++;
}
}
}
// allocate memory for the common elements by making use of count
int * common_elements = (int*)malloc(count*sizeof(int));
// store the common elements in the new memory location
for(int i=0;i<size_first;i++){
for(int j=0;j<size_second;j++){
if(first[i]==second[j]){
common_elements[k]=first[i];
k++;
}
}
}
return common_elements;
free(common_elements);
}
If you are allowed to waste some memory, note that the intersection cannot have cardinality larger than the number of elements in the smaller set. Therefore, you can allocate more memory than you might need and avoid having to count first and allocate later.
Or, you can realloc as you go.
In general, you need a good data structure for checking set membership more quickly than scanning an entire array although for small sizes which fit in various caches, the linear scan will not perform too shabbily either.
For larger sets, however, you'll want to load the larger of the sets into an AVL tree or Scapegoat tree.
For really large data sets, you'll need to look into Bloom filters and related data structures depending on the use case.
I am including below the most naive improvement in your code which still has the nested loop and wastes memory up to the size of the smaller set to avoid counting common elements first.
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
// TODO: What about duplicates in smaller set?
int *
int_set_intersection(
const int *first,
const int *second,
const size_t size_first,
const size_t size_second,
size_t *n
)
{
size_t K = 0; // number of common elements
const int is_first_smaller = (size_first < size_second);
// Done this way so I can declare variables as consts
const int *set_smaller = is_first_smaller ? first : second;
const int *set_larger = is_first_smaller ? second : first;
const size_t size_smaller = is_first_smaller ? size_first : size_second;
const size_t size_larger = is_first_smaller ? size_second : size_first;
int *common = malloc(size_smaller * sizeof(*common));
if (!common) {
fprintf(stderr, "Failed to allocate memory for %z ints\n", size_smaller);
perror("Cannot allocate memory for common elements");
exit(EXIT_FAILURE);
}
for (size_t i = 0; i < size_smaller; ++i) {
for (size_t j = 0; j < size_larger; ++j) {
if (set_smaller[i] == set_larger[j]) {
common[K] = set_smaller[i];
++K;
break;
}
}
}
*n = K;
return common;
}
void
int_set_print(const int *set, size_t n, FILE *f)
{
FILE *out = f ? f : stdout;
size_t i = 0;
fputs("{ ", out);
for (i = 0; i < n - 1; ++i) {
fprintf(out, "%d, ", set[i]);
}
fprintf(out, "%d }\n", set[i]);
}
int
main(void) {
int arr1[] = {1, 8, 3, 2, 6};
int arr2[] = {2, 5, 1};
size_t n = 0;
const int *intersection = int_set_intersection(
arr1,
arr2,
sizeof(arr1)/sizeof(arr1[0]),
sizeof(arr2)/sizeof(arr2[0]),
&n
);
int_set_print(intersection, n, NULL);
free(intersection); // not really needed, but good hygiene
return 0;
}
For larger arrays, one option is to sort the contents first to make it easier to check for common elements, as shown in the code below. If the original array contents cannot be changed, first copy them into dynamically allocated memory. Dynamically allocated memory is also needed to hold the list of common elements, but that can use the same storage as one of the copies.
OP's original function returns a pointer to dynamically allocated memory containing the array of common elements, but does not indicate the length of the array. I added a parameter to return the length.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int *f(int first[], int second[], int size_first, int size_second, int *size_common);
int main(void) {
int arr1[]={1, 8, 3, 2, 6};
int arr2[]= {2, 6, 1};
int size1 = sizeof(arr1)/sizeof(arr1[0]);
int size2 = sizeof(arr2)/sizeof(arr2[0]);
int size_common;
int *intersection = f(arr1, arr2, size1, size2, &size_common);
for(int i=0;i<size_common; i++){
printf("%d ", intersection[i]);
}
free(intersection);
return 0;
}
static int cmp_int(const void *ap, const void *bp) {
int a = *(const int *)ap;
int b = *(const int *)bp;
return (a > b) - (a < b);
}
// function to find common elements in 2 arrays
int *f(int first[], int second[], int size_first, int size_second,
int *size_common) {
int *copy1;
int *copy2;
int idx1;
int idx2;
int count;
// allocate memory local copies of the arrays
copy1 = malloc(size_first * sizeof (int));
copy2 = malloc(size_second * sizeof (int));
if (!copy1 || !copy2) {
// allocation error
free(copy1);
free(copy2);
*size_common = -1; // use -1 to report error
return NULL;
}
// copy the arrays
memcpy(copy1, first, size_first * sizeof (int));
memcpy(copy2, second, size_second * sizeof (int));
// sort the copies in ascending order
qsort(copy1, size_first, sizeof (int), cmp_int);
qsort(copy2, size_second, sizeof (int), cmp_int);
// find common elements
idx1 = 0;
idx2 = 0;
count = 0;
while (idx1 < size_first && idx2 < size_second) {
if (copy1[idx1] < copy2[idx2]) {
idx1++;
} else if (copy1[idx1] > copy2[idx2]) {
idx2++;
} else {
// common element found!
// use copy1[] to store common elements
copy1[count] = copy1[idx1];
count++;
idx1++;
idx2++;
}
}
// common elements are in copy1[].
// finished with copy2, so free it.
free(copy2);
if (count == 0) {
// no common elements
free(copy1); // free the memory
copy1 = NULL; // and make the function return NULL
} else {
// try to reduce memory for common elements
copy2 = realloc(copy1, count * sizeof (int));
if (copy2) {
// reallocation successful
copy1 = copy2;
} // else, never mind, copy1 is still valid
}
// return the common elements
*size_common = count;
return copy1;
}
If your arrays are of comparable elements (you use integers, which are comparable), the best way in my opinion is to sort both arrays and traverse both in parallel, looking at both sides and comparing the elements at both sides. If there's a lowest element, advance its pointer, leaving the other waiting.... if there's a match (they are equal), you can mark it (more on this later) and advance both pointers, until you reach the end in one array (the sortest). You will get the marks on the matching positions, but if you reorder the array, exchanging the found element with the first of the yet, unmatched elements, you will have all matching elements in the first positions of both arrays, letting you to return only the number of matches from the function and the matches themselves in the first positions of both arrays.
The complexity of this algorithm should be O(n*log(n)) (because of the quicksorts) if you use quicksort, plus O(n) (which doesn't affect the final O) for the matching, so O(n*log(n)) should be the big O complexity, as a general case. Below is a sample code, with a run:
comp.c
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#define N(arr) (sizeof(arr)/sizeof((arr)[0]))
void swap(int *ref_a, int *ref_b)
{
if (ref_a == ref_b)
return; /* nothing to do. */
int temp = *ref_a;
*ref_a = *ref_b;
*ref_b = temp;
}
int int_cmp(const void *_a, const void *_b)
{
const int *a = _a, *b = _b;
return *a - *b;
}
void print(int v[], int v_sz, const char *fmt, ...)
{
va_list p;
va_start(p, fmt);
vprintf(fmt, p);
va_end(p);
char *sep = "[";
for (int i = 0; i < v_sz; i++) {
printf("%s%d", sep, v[i]);
sep = ", ";
}
printf("]\n");
}
int find_matches(int a[], int b[], int a_sz, int b_sz)
{
print(a, a_sz, "a(unsorted)");
print(b, b_sz, "b(unsorted)");
qsort(a, a_sz, sizeof a[0], int_cmp);
qsort(b, b_sz, sizeof b[0], int_cmp);
print(a, a_sz, "a(sorted)");
print(b, b_sz, "b(sorted)");
int i = 0;
for (int i_a = 0, i_b = 0; i_a < a_sz && i_b < b_sz;) {
if (a[i_a] < b[i_b]) {
i_a++;
continue;
} else if (a[i_a] > b[i_b]) {
i_b++;
continue;
}
/* a[i_a] == b[i_b] */
swap(&a[i_a], &a[i]);
swap(&b[i_b], &b[i]);
print(a, a_sz, "after #%d, a:", i);
print(b, b_sz, "after #%d, b:", i);
i_a++; i_b++; i++;
}
return i;
}
int main()
{
int arr1[] = {1, 8, 3, 2, 6, 7};
int arr2[] = {2, 6, 1, 7, 4, 1, 9, 6};
int size1 = N(arr1);
int size2 = N(arr2);
int match = find_matches(arr1, arr2, size1, size2);
for (int i = 0; i < match; i++) {
printf("Match #%d: %d\n", i, arr1[i]);
}
}
It will produce:
$ comp
a(unsorted)[1, 8, 3, 2, 6, 7]
b(unsorted)[2, 6, 1, 7, 4, 1, 9, 6]
a(sorted)[1, 2, 3, 6, 7, 8]
b(sorted)[1, 1, 2, 4, 6, 6, 7, 9]
after #0, a:[1, 2, 3, 6, 7, 8]
after #0, b:[1, 1, 2, 4, 6, 6, 7, 9]
after #1, a:[1, 2, 3, 6, 7, 8]
after #1, b:[1, 2, 1, 4, 6, 6, 7, 9]
after #2, a:[1, 2, 6, 3, 7, 8]
after #2, b:[1, 2, 6, 4, 1, 6, 7, 9]
after #3, a:[1, 2, 6, 7, 3, 8]
after #3, b:[1, 2, 6, 7, 1, 6, 4, 9]
Match #0: 1
Match #1: 2
Match #2: 6
Match #3: 7
$ _
A good interface is to switch in both algorithms the matched elements with the first of the non-yet-matched elements in both arrays, so in this way you can return an integer (the one you use to know the start of the non-yet-matched elements) that tells you the number of matched elements, and you will get them from any of the two arrays.
If the elements are not comparable, and they can be just be compared for equity, then you have to compare each element with any other for a match, take them off from the arrays (this can be done swapping them with the first of the not yet matched elemnts, and advance the pointers), and start again with the reduced versions of them. Some way of doing this is, when you find a match, to exchange them with the first, second, third elements of each array, and use a variation of the above algorithm (you reorder as you match) In this case you compare at first time n*m (but not all), when you get a match, (n-1)*(m-1), ... and so until the last comparition in which you fail all comparitions to (m-k)*(n-k). This is, in the average, m*n/2 + (m-1)*(n-1)/2 +...+ (m-k)*(n-k). something in the range of m(m-1)*n(n-1)/k^2, which is O(m^2*n^2):
comp2.c
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#define N(arr) (sizeof(arr)/sizeof((arr)[0]))
void swap(int *ref_a, int *ref_b)
{
if (ref_a == ref_b)
return; /* nothing to do. */
int temp = *ref_a;
*ref_a = *ref_b;
*ref_b = temp;
}
int int_cmp(const void *_a, const void *_b)
{
const int *a = _a, *b = _b;
return *a - *b;
}
void print(int v[], int v_sz, const char *fmt, ...)
{
va_list p;
va_start(p, fmt);
vprintf(fmt, p);
va_end(p);
char *sep = "[";
for (int i = 0; i < v_sz; i++) {
printf("%s%d", sep, v[i]);
sep = ", ";
}
printf("]\n");
}
int find_matches(int a[], int b[], int a_sz, int b_sz)
{
print(a, a_sz, "a(unsorted)");
print(b, b_sz, "b(unsorted)");
int i = 0;
loop:
for (int i_a = 0; i_a + i < a_sz; i_a++) {
for (int i_b = 0; i_b + i < b_sz; i_b++) {
/* we can only compare for equality */
if (a[i + i_a] == b[i + i_b]) {
swap(&a[i + i_a], &a[i]);
swap(&b[i + i_b], &b[i]);
i++;
goto loop;
}
}
}
print(a, a_sz, "a(final)");
print(b, b_sz, "b(final)");
return i;
}
int main()
{
int arr1[] = {1, 8, 3, 2, 6, 7};
int arr2[] = {2, 6, 1, 7, 4, 1, 9, 6};
int size1 = N(arr1);
int size2 = N(arr2);
int match = find_matches(arr1, arr2, size1, size2);
for (int i = 0; i < match; i++) {
printf("Match #%d: %d\n", i, arr1[i]);
}
}
which produces, when running, the following output:
$ comp2
a(unsorted)[1, 8, 3, 2, 6, 7]
b(unsorted)[2, 6, 1, 7, 4, 1, 9, 6]
a(final)[1, 2, 6, 7, 3, 8]
b(final)[1, 2, 6, 7, 4, 1, 9, 6]
Match #0: 1
Match #1: 2
Match #2: 6
Match #3: 7
$ _
You can reorder the values, there's no difference, in this case you had a two level for loop, mixed with a third level go back to the beginning and start again loop. The loop is warranted to finish, as when you go back to the top, you have increased i, which means the nested for loops will be shorter each time. We can rewrite the find_matches routine in this case by adjusting the array start points, in this manner:
comp3.c
/* ... as before */
int find_matches(int a[], int b[], int a_sz, int b_sz)
{
print(a, a_sz, "a(unsorted)");
print(b, b_sz, "b(unsorted)");
int i = 0;
loop:
for (int i_a = 0; i_a < a_sz; i_a++) {
for (int i_b = 0; i_b < b_sz; i_b++) {
/* we can only compare for equality */
if (a[i_a] == b[i_b]) {
swap(&a[i_a], &a[0]);
swap(&b[i_b], &b[0]);
i++;
print(a++, a_sz--, "a(after match)");
print(b++, b_sz--, "b(after match)");
goto loop;
}
}
}
print(a, a_sz, "a(final)");
print(b, b_sz, "b(final)");
return i;
}
/* ... as before */
that will produce this result (I changed the initial sort order to see how it affects the final result):
$ comp3
a(unsorted): [7, 8, 2, 3, 6, 1]
b(unsorted): [2, 6, 1, 7, 4, 1, 9, 6]
a(after match): [7, 8, 2, 3, 6, 1]
b(after match): [7, 6, 1, 2, 4, 1, 9, 6]
a(after match): [2, 8, 3, 6, 1]
b(after match): [2, 1, 6, 4, 1, 9, 6]
a(after match): [6, 3, 8, 1]
b(after match): [6, 1, 4, 1, 9, 6]
a(after match): [1, 8, 3]
b(after match): [1, 4, 1, 9, 6]
a(final): [8, 3]
b(final): [4, 1, 9, 6]
Match #0: 7
Match #1: 2
Match #2: 6
Match #3: 1
$ _
So, I have this so far. I'm trying to find the two largest numbers in an array and return them. I looked up a lot of resources online, and most of them say "call by reference" is the way to go. But I've no idea how to make it work with my program. For example, I saw this example online:
void Calculate(int x, int y, int* prod, int* quot)
{
*prod = x*y;
*quot = x/y;
}
int x = 10,y = 2, prod, quot;
Calculate(x, y, &prod, ")
How does the above program actually "return"? How do I print the return values to the console?
#include "stdio.h"
void largest_two( int numbers[], int len, int *largest, int *next_largest){
int i, temp;
*largest = numbers[0];
*next_largest = numbers[1];
if(*largest < *next_largest){
temp = *next_largest;
*largest = *next_largest;
*next_largest = temp;
}
for (i=0; i<sizeof(numbers); i++) {
if(numbers[i]>= *largest){
*largest = numbers[i];
*next_largest = *largest;
}
else if ( numbers[i] > *next_largest){
*next_largest = numbers[i];
}
}
}
int main() {
int numbers[] = {3, 1, 2, 3, 6, 2, 8, 0, 0, 0};
int len = 3;
int largest, next_largest;
//==>??? printf("%d %d", largest_two(numbers, len, &largest, &next_largest));
}
Sides' from the pointer issues (you should read a tutorial / book on them), your main problem is that you're attempting to print the single return value of a function with return type void which means it won't return at all.
Your code:
int main() {
int numbers[] = {3, 1, 2, 3, 6, 2, 8, 0, 0, 0};
int len = 10; // sizeof(numbers)
int largest, next_largest;
largest_two(numbers, len, &largest, &next_largest);
printf("%d %d", largest, next_largest);
}
Keep in mind this is still not entirely correct, but it does adress your problem of printing the numbers.
Also, passing len means you shouldn't do this for (i=0; i<sizeof(numbers); i++) but this instead for (i=0; i<len; i++)
Firstly, this line:
for (i=0; i<sizeof(numbers); i++)
is not correct. You want this to be instead:
for (i=0; i<len; i++)
which should be passed to largest_two() as sizeof numbers/sizeof numbers[0], which is the actual length of the array.
I also suggest setting largest and next_largest to INT_MIN from <limits.h>, and then finding these values from their. It seems you are also having trouble with pointers, and it would be best to use them only when needed.
Here is an example which simplifies your approach, which finds the largest and second largest element in one loop of the array. It also only uses pointers when needed.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define ARRAYSIZE(x) (sizeof x/sizeof x[0])
void largest_two(int numbers[], size_t len, int *largest, int *next_largest);
int main(void) {
int numbers[] = {3, 1, 2, 3, 6, 2, 8, 0, 0, 0};
int largest, next_largest;
largest_two(numbers, ARRAYSIZE(numbers), &largest, &next_largest);
printf("largest = %d\nnext_largest = %d\n", largest, next_largest);
}
void largest_two(int numbers[], size_t len, int *largest, int *next_largest) {
int max, smax;
max = smax = INT_MIN;
for (size_t i = 0; i < len; i++) {
if (numbers[i] > max) {
smax = max;
max = numbers[i];
} else if (numbers[i] > smax && numbers[i] < max) {
smax = numbers[i];
}
}
*largest = max;
*next_largest = smax;
}
Output:
largest = 8
next_largest = 6
Second dataset:
int numbers[] = {3, 1, 6, 3, 6, 2, 8, 0, 8, 7};
Output:
largest = 8
next_largest = 7
I am a rookie, and I hope this question is not a naive one!
I have the following function, where I use elements of one array as indices of another. However, despite my making no changes to the former, I see that the elements are being modified. The code is as follows:
void convert_to_bitmap(int n_shapes, int sizex, int sizey,
int ll_x[n_shapes], int ll_y[n_shapes],
int ur_x[n_shapes], int ur_y[n_shapes],
int shapes_ll_bitmap[sizex][sizey],
int shapes_ur_bitmap[sizex][sizey] )
{
int i;
for (i = 0; i < n_shapes; i++)
{
printf("%d, %d, %d, %d check1\n", ll_x[i], ll_y[i], ur_x[i], ur_y[i]);
}
for (i = 0; i < n_shapes; i++)
{
shapes_ll_bitmap[ll_x[i]][ll_y[i]] = 1;
shapes_ur_bitmap[ur_x[i]][ur_y[i]] = 1;
printf("%d, %d, %d, %d check2\n", ll_x[i], ll_y[i], ur_x[i], ur_y[i]);
}
}
And, the output shows that the first array has changed when I do so. Is there some way to keep it immutable?
Output:
0, 0, 0, 7 check1
0, 9, 0, 15 check1
1, 0, 1, 7 check1
1, 9, 1, 15 check1
2, 13, 2, 15 check1
2, 17, 2, 24 check1
2, 26, 2, 32 check1
0, 0, 0, 7 check2
0, 9, 0, 15 check2
1, 0, 1, 7 check2
1, 9, 1, 15 check2
1, 13, 2, 15 check2
2, 1, 2, 1 check2
1, 26, 2, 32 check2
This is how I invoke the function in main():
convert_to_bitmap(n_shapes, sizex, sizey, ll_x, ll_y, ur_x, ur_y, shapes_ll_bitmap, shapes_ur_bitmap);
And the declaration and initialization of the matrices in int main() is as follows:
int ll_x[n_shapes];
int ll_y[n_shapes];
int ur_x[n_shapes];
int ur_y[n_shapes];
int sizex;
int sizey;
int shapes_ll_bitmap[sizex][sizey];
int shapes_ur_bitmap[sizex][sizey];
for (i=0; i < sizex; i++)
{
for (j = 0; j < sizey; j++)
{
shapes_ll_bitmap[i][j] = 0;
shapes_ur_bitmap[i][j] = 0;
}
printf("\n");
}
Thank you!
Edit:
Here's some self-contained code:
int main(void)
{
enum { MAX_SHAPES = 100000 };
struct Rectangle rect_array[MAX_SHAPES];
int n_shapes = read_shapes_rpt("shapes.rpt", MAX_SHAPES, rect_array);
int i, j;
float pitch_x = 0.044;
float pitch_y = 0.042;
float ll_x_flt[n_shapes];
float ll_y_flt[n_shapes];
float ur_x_flt[n_shapes];
float ur_y_flt[n_shapes];
int ll_x[n_shapes];
int ll_y[n_shapes];
int ur_x[n_shapes];
int ur_y[n_shapes];
int sizex;
int sizey;
int shapes_ll_bitmap[sizex][sizey];
int shapes_ur_bitmap[sizex][sizey];
for (i=0; i < sizex; i++)
{
for (j = 0; j < sizey; j++)
{
shapes_ll_bitmap[i][j] = 0;
shapes_ur_bitmap[i][j] = 0;
}
printf("\n");
}
if (n_shapes > 0)
{
transform_to_shape_bit_locations(n_shapes, rect_array, ll_x_flt, ll_y_flt, ur_x_flt, ur_y_flt, ll_x, ll_y, ur_x, ur_y, &pitch_x, &pitch_y, &sizex, &sizey);
convert_to_bitmap(n_shapes, sizex, sizey, ll_x, ll_y, ur_x, ur_y, shapes_ll_bitmap, shapes_ur_bitmap);
printf("%d\n%d\n%d\n", n_shapes, sizex, sizey);
/* Use the shapes that were read */
}
return 0;
}
My shapes.rpt file contained the following csv values:
1.408,529.237,1.43,529.523
1.408,529.597,1.43,529.883
1.452,529.237,1.474,529.523
1.452,529.597,1.474,529.883
1.496,529.777,1.518,529.883
1.496,529.957,1.518,530.243
1.496,530.317,1.518,530.564
Your variables sizex and sizey are left uninitialized. Which means that your matrices shapes_ll_bitmap and shapes_ur_bitmap have unpredictable size (the behavior is actually undefined).
Note that when you actually assign meaningful values to your your sizex and sizey later, it is already too late. The matrices are already declared with indeterminate sizes and that's final. Once the matrices are declared, any changes to the values of sizex and sizey will have no effect on the matrices.
Your matrices end up with some indeterminate size, which results in out-of-bounds access inside convert_to_bitmap function and destruction of unrelated memory values.