Confusing values when copying to another array - c

I am trying to copy values from one array to another in C. The original array is of type long int, and it is inputted to the function as *pixel_frequency. The array I want to copy to is temp, and it is a 2D array. However, when I try to copy the values, pixel_frequency is fine but temp gives strange results. Below is the relevant code and some sample output.
Code:
struct node *generate_nodes(long int *pixel_frequency) {
int i;
int temp[max_value + 1][2];
for (i = 0; i < (max_value + 1); i++) {
temp[i][0] = i;
temp[i][1] = pixel_frequency[i];
printf("Frequency for %d is %d\n", temp[i][0], temp[i][1]);
}
...
Output (each frequency is supposed to be 256):
Frequency for 0 is 150160
Frequency for 1 is 256
Frequency for 2 is 256
Frequency for 3 is 256
Frequency for 4 is 255
...
Frequency for 254 is 892677956
Frequency for 255 is 1868789101

Below is an example version of code using your code snippet, take care of the return type and other things.
Instead of using a global variable for array size, you can pass it as a function argument so , it will be easy to identify the size of array you passed.
void generate_nodes(long int *pixel_frequency, size_t size) {
size_t i;
long int temp[size][2];
for (i = 0; i < size; i++) {
temp[i][0] = i;
temp[i][1] = pixel_frequency[i];
printf("Frequency for %ld is %ld\n", temp[i][0], temp[i][1]);
}
}
If you have declared pixel_frequency as a local variable in a function and used the address of array after the variable went out of scope, will lead to undefined behaviour.
int main(void) {
size_t max_len = 5000;
size_t i;
long int* pixel_frequency = malloc(max_len*sizeof(long int));
for( i = 0; i < max_len; ++i) {
pixel_frequency[i] = (i%256);
}
generate_nodes(pixel_frequency, max_len);
return 0;
}

Related

False min and max assignments in function

I have a function which is supposed to find min and max in an array using struct.
But somehow the function assigns wrong values to min and max variables. Could someone please explain where do I have the mistake? Thank you very much. P.S. In my assignment the function doesn't need to take the first element of the array
min_max_t min_max(unsigned int *array, int size)
{
min_max_t flag;
flag.min = array[1];
flag.max = array[1];
printf("Flag.min: %d | ", flag.min);
printf("Flag.max: %d\n", flag.max);
for (int i = 1; i < size; i++)
{
printf("i = %d - [A:%d - Min:%d - Max:%d]\n", i, array[i], flag.min, flag.max);
if(array[i] > flag.max)
{
flag.max = array[i];
}
else if (array[i] < flag.min)
{
flag.min = array[i];
}
printf("i = %d - [A:%d - Min:%d - Max:%d]\n\n", i, array[i], flag.min, flag.max);
}
return flag;
}
Screenshot of function process
There is nothing wrong with the logic for finding min and max.
The problem with your code is that you print unsigned int using %d. When printing unsigned int values use %u.
Another issue, that you may consider to handle, is illegal values of the function parameter size. Your function requires that size is at least 2. To avoid undefined behavior you may want to check for that.
In the start of the function you could for instance add
assert(size >= 2);
or
if (size < 2)
{
// return some suitable value
}
That said you can also just document the function to require size being at least 2. In C it's not uncommon to set such contract requirements for functions. Several stdlib functions have such requirements.
BTW: If you add check for size you should probably also check for array not being NULL.
BTW: Your Screenshot indicates that you pass an array of int to the function. If that's true then you have a bug in the caller-code. Don't pass an array of int to a function expecting an an array of unsigned int.
For starters the function should be declared like
min_max_t min_max( const unsigned int *array, size_t size );
and the structure min_max_t should contain two data members that will store indices to minimum and maximum elements. For example
typedef struct min_max_t
{
size_t min;
size_t max;
} min_max_t;
Otherwise the function can invoke undefined behavior when for example the user passed as the second argument 0.
Indices in arrays start from 0. So you skipped within the function the first element of the passed array.
As the array has elements of the type unsigned int then the expression -1 is converted implicitly to the maximum value of the type unsigned int. So you need to decide whether indeed you want to deal with unsigned integer arrays or with signed integer arrays.
Using the conversion specifier %d instead of %u in a call of printf to output an object of the type unsigned int can invoke undefined behavior if the value of the object does not fit in an object of the type int.
So your function can look the following way
typedef struct min_max_t
{
size_t min;
size_t max;
} min_max_t;
min_max_t min_max( const unsigned int *array, size_t size )
{
min_max_t flag = { .min = 0, .max = 0 };
printf( "Flag.min: %zu | ", flag.min );
printf( "Flag.max: %zu\n", flag.max );
for ( size_t i = 1; i < size; i++ )
{
printf( "i = %zu - [A:%u - Min:%u - Max:%u]\n", i, array[i], array[flag.min], array[flag.max] );
if ( array[flag.max] < arra[i] )
{
flag.max = i;
}
else if ( array[i] < array[flag.min] )
{
flag.min = i;
}
printf( "i = %zu - [A:%u - Min:%u - Max:%u]\n\n", i, array[i], array[flag.min], array[flag.max] );
}
return flag;
}

GCC Compilation Error on array assignment

I am trying to convert a string into its equivalent matrix form in C. The matrix would have 3 rows and as many columns as required. The following code doesn't compile, and I haven't figured out what's going wrong.
The error that GCC throws is:
app.c:10:25: error: subscripted value is not an array, pointer, or vector
printf("%d\n", arr[i][k]);
~~~^~
1 error generated.
Main file (app.c):
#include <stdio.h>
#include "converter.h"
int main() {
char source[] = "This is the source. "; // placeholder text
int arr = convert(source);
for (int i = 0; i < 21; i++) {
for (int k = 0; k < 3; k++) {
printf("%d\n", arr[i][k]); // error occurs at this line.
}
}
return 0;
}
converter.c file:
// Converts an input string to its respective ASCII matrix.
#include <string.h>
#include <stdio.h>
#include "converter.h"
// Converts the entire string into an multi-dimensional array.
int convert(char text[]){
// copy the input text into a local store.
char store[strlen(text)];
strcpy(store, text);
// make sure the length of the input string is a multiple of 3 or make it so.
int excess = strlen(store)%3;
char excess_spaces[3] = " ";
if (excess != 0) {
strncat(store, excess_spaces, 3-excess);
}
// covert the source into an array
int arr[3][strlen(store)/3];
int steps = strlen(store)/3;
for (int i = 0; i < steps; i++) {
int t[3];
for (int k = 0; k < 3; k++) {
t[k] = (int) store[3*i+k];
arr[k][i] = t[k];
}
}
return arr;
}
converter.h file:
int convert(char text[]);
There are multiple issues in this code.
The allocating storage for string, one must include one byte for a null terminator. Replace:
char store[strlen(text)];
with:
char store[strlen(text) + 1];
Additionally store must be big enough to contain the excess which is up to 3 spaces.
char store[strlen(text) + 3 + 1];
In C you cannot use an array as a value. It is converted to a pointer to it's first element in pretty must every context. Therefore it is not possible to return an array directly. It could be workaround by wrapping an array with a struct but it a topic for another day.
As result return arr will be equivalent to return &arr[0] which is int (*)[XXX] a pointer to int array of size XXX.
Never ever return a pointer to an object with automatic storage. It's Undefined Behaviour. I know that the intention was returning an array not a pointer to it. Create an object with dynamic storage with malloc-like function to safely return a pointer.
Returning Variable Length Array (VLA) by value is not possible because Variably Modified (VM) types cannot be defined at file scope.
It looks that indices are swapped in:
printf("%d\n", arr[i][k]);
I guess it should be arr[k][i].
Now... let's solve it.
Returning VLA is tricky. One solution is to pass a pointer to VLA as an argument. See https://stackoverflow.com/a/14088851/4989451.
The issue with this solution is that the caller must be able to compute the dimensions.
The other way it to wrap the result of the convert() to a struct. Note that the function and the struct can share the name. The result with have the sizes of VLA as n and m members and the pointer to the data as arr. The caller need to cast it to proper VM type.
To cumbersome casts between the non-trivial pointer types, one can cast via void*.
When all work with the array is done, release it memory with free().
// Converts an input string to its respective ASCII matrix.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
// Converts the entire string into an multi-dimensional array.
struct convert {
int n, m;
int *arr;
} convert(char text[]){
// copy the input text into a local store.
size_t textlen = strlen(text);
char store[textlen + 3 + 1];
strcpy(store, text);
// make sure the length of the input string is a multiple of 3 or make it so.
int excess = textlen % 3;
char excess_spaces[3] = " ";
if (excess != 0) {
strncat(store, excess_spaces, 3-excess);
}
size_t storelen = strlen(store);
// allocate VLA with dynamic storage
int (*arr)[storelen / 3] = malloc(3 * sizeof *arr);
// covert the source into an array
int steps = storelen / 3;
for (int i = 0; i < steps; i++) {
int t[3];
for (int k = 0; k < 3; k++) {
t[k] = (int) store[3*i+k];
arr[k][i] = t[k];
}
}
return (struct convert){ .n = 3, .m = steps, .arr = (int*)arr };
}
int main() {
char source[] = "This is the source. "; // placeholder text
struct convert res = convert(source);
int n = res.n, m = res.m;
int (*arr)[m] = (void*)res.arr;
for (int i = 0; i < n; i++, puts("")) {
for (int k = 0; k < m; k++) {
printf("%d ", arr[i][k]); // error occurs at this line.
}
}
free(arr);
return 0;
}

How to categorize elements of array in C

I have a problem regarding arrays.
So, I have an array with the size of 255 (let's call it array(255)). I have an integer named block also.
I want to categorize this arrays (I hope the term is right).
What I want is:
If the chosen array element is
From (0-63) , block = 0
From (64-127) , block = 1
From (128-191), block = 2
From (192-255), block = 3
I know with this case I can just use if statement. But what if I scale up my array size into thousands?
I can't use rows of If statement.
Is there any simpler and more efficient solution for this?
You can simply do it with an integer division:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdint.h>
#include <inttypes.h>
int main(void)
{
uint8_t array[255] = {0};
srand(time(NULL));
for(size_t i=0; i<sizeof(array)/sizeof(array[0]); i++)
{
array[i] = rand() % 256;
printf("Array[%zu]= %"PRIu8"\tblock= %"PRIu8"\n", i, array[i], array[i] / 64 );
}
}
You should do something like:
int array[255];
...
int getArrayItemByCateg(int category, int index) {
return array[category * 64 + index];
}
If you have only an pointer to your element in your code you could use something like the following function:
int getBlock(void* array, void* arrayElement, size_t size)
{
return (int)((arrayElement - array) / (size * 64));
}
This function can be uses for different array types but the origin array has to be known when you are calling this function. See the following examples:
uint32_t array_u32[256];
uint16_t array_u16[256];
printf("array u32 index 32 is block %d\n", getBlock(array_u32, &array_u32[32], sizeof(array_u32[0])));
printf("array u32 index 129 is block %d\n", getBlock(array_u32, &array_u32[129], sizeof(array_u32[0])));
printf("array u16 index 32 is block %d\n", getBlock(array_u16, &array_u16[32], sizeof(array_u16[0])));
printf("array u16 index 129 is block %d\n", getBlock(array_u16, &array_u16[129], sizeof(array_u16[0])));
The following result will be printed:
array u32 index 32 is block 0
array u32 index 129 is block 2
array u16 index 32 is block 0
array u16 index 129 is block 2
Also see the code at IDEONE.
How about a multidimensional array? Information: Tutorials Point - Multidimensional Arrays
This may not be an elegant solution but it is pretty simple. This may not be ideal for larger scale data however larger scale data may be best using a binary or quad tree anyhoo.
Multidimensional Array:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
const int COLUMN_SIZE = 64;
const int ROW_SIZE = 4;
// Access index of row using the labels below
const int BLOCK_ONE = 0;
const int BLOCK_TWO = 1;
const int BLOCK_THREE = 2;
const int BLOCK_FOUR = 3;
int main(int argc, char* argv[]) {
int array[ROW_SIZE][COLUMN_SIZE] = {0};
srand(time(NULL));
/* Initialise array */
for(int x = 0; x < ROW_SIZE; x++) {
for(int i = 0; i < COLUMN_SIZE; i++) {
array[x][i] = rand() % (ROW_SIZE * COLUMN_SIZE);
}
}
/* Test */
for(int x = 0; x < ROW_SIZE; x++) {
for(int i = 0; i < COLUMN_SIZE; i++) {
printf("Array[%d][%d]: %d\n", x, i, array[x][i]);
}
printf("\n");
}
return 0;
}

Passing entire array to the function in C

I have written a program for insertion shot like following:
int _tmain(int argc, _TCHAR* argv[])
{
int arr[10] = {1,2,3,10,5,9,6,8,7,4};
int value;
cin >> value ;
int *ptr;
ptr = insertionshot(arr); //here Im passing whole array
BinarySearch(arr,value);
return 0;
}
int * insertionshot(int arr[])
{
//Changed after a hint (now, its fine)
int ar[10];
for(int i =0;i < 10; i++)
{
ar[i] = arr[i];
}
//Changed after a hint
int arrlength = sizeof(ar)/sizeof(ar[0]); //here array length is 1, it should be 10
for(int a = 1; a <= arrlength -1 ;a++)
{
int b = a;
while(b > 0 && ar[b] < ar[b-1])
{
int temp;
temp = ar[b-1];
ar[b-1] = ar[b];
ar[b] = temp;
b--;
}
}
return ar;
}
The problem is after passing the whole array to the function, my function definition only shows 1 element in array and also "arraylength" is giving 1.
int arr[] in a function formal parameter list is a syntax quirk, it is actually processed as int *arr. So the sizeof trick doesn't behave as you expect.
In C it is not possible to pass arrays by value; and furthermore, at runtime an array does not remember its length.
You could include the length information by passing a pointer to the whole array at compile time:
int * insertionshot(int (*arr)[10])
Of course, with this approach you can only ever pass an array of length 10. So if you intend to be able to pass arrays of differing length, you have to pass the length as another parameter.

Finding the length of a dynamically allocated array of unsigned long long

I have an array of unsigned long long numbers. I initialize the first 12 elements. The array changes size throughout the programs runtime. How can I find out the length of the array.
I can't use sizeof(array)/sizeof(unsigned long long) since it doesn't work correctly in this case.
I tried using this loop:
count = 0;
while ( array[count] ) count++;
return count;
The problem with this method is that it still returns the wrong length.
Here is the basic rundown of the code.
unsigned long long *prime = (unsigned long long *)calloc(1000, sizeof(unsigned long long);
prime[0] = 3;
prime[1] = 5;
....
prime[11] = 41;
unsigned long long *ptrEmpty = &prime[12];
int sizeComp;
//User can change change the size of the array here to create a larger list of primes.//
for( i = 43, sizeComp = 12; sizeComp < length(prime); i += 2 ){
// Do stuff...
}
How can I find this length?
One way is to keep a counter every time an element is inserted into the array. Maybe you can encapsulate the array in a struct e.g:
typedef struct int_arr
{
int* arr_ptr;
size_t max_size;
int curr_elem;
} int_arr;
Then you can specify init, add and get_max_size and get_curr_size functions.
Init:
int_arr* arr_init(int_arr* ptr, size_t size)
{
ptr = calloc(size, sizeof(int);
ptr->max_size = size;
ptr->curr_elem = 0;
return ptr;
}
Add:
void add(int_arr* ptr, int value)
{
if (ptr->curr_elem < ptr->max_size)
ptr->arr_ptr[ptr->curr_elem++] = value;
else
printf("Max size reached!\n");
}
Get total size:
size_t get_total_size(int_arr* ptr) { return ptr->max_size; }
Get current size:
int get_curr_size(int_arr* ptr) { return ptr->curr_elem; }
Obviously replace int with your desired type.

Resources