passing a pointer to a structure as a parameter - c

I have a structure that I've set up, and a pointer to the structure, that is basically an array. I want to create a function that modifies specific values within the structure but can't seem to figure out how to pass in the structure pointer as a parameter.
struct deviations {
int switch;
int x;
int y;
};
struct deviations *pdevs = malloc(24 * sizeof(int));
for(int i = 0; i < 8; i++) {
(pdevs + i)->switchez = 1;
(pdevs + i)->x = 0;
(pdevs + i)->y = 0;
}
int top[3] = {0, 1, 2};
int bottom[3] = {5, 6, 7};
int left[3] = {0, 3 ,5};
int right[3] = {2, 4, 7};
for(int i = 0; i < 3; i++) {
(pdevs + top[i])->y = -1;
}
I have multiple (8) for loops like above and in each of them the basic structure is the same, except the array ("top"), lvalue ('y') and rvalue ('-1') change in each. I can't figure out how to declare a function with the structure/pointer to structure properly.
I currently have it around 26 lines of (8 for loops repeating) code and am pretty sure I can compress it down to a tidy little function if I can figure out how to pass in the pointer to the structure. Any help would be much appreciated!
This snippet is part of a larger function/program that determines whether or not to check the surrounding items (3 up top, 3 at bottom, one on each side). I have set up a structure with an on/off switch based on the position of the base item, and an x/y offset. I am trying to shift each individual cell by a certain amount +1/-1/ or 0 in the x or y position. And I am trying to flip the switch on or off depending on certain conditions about the x or y of the original cell. Malloc is probably unnecessary, but am unsure whether or not this array of structs will be used again later, if not, I will remove the call to malloc.
Thanks!

So you want a generic function that can take an array of 3 indexes, the structure member to fill in, and the value.
The array and value are simple. To handle a structure member generically, you can use the offsetof() macro.
void fill_structs(struct deviations *pdevs, size_t offset, int indexes[3], int value) {
for (int i = 0; i < 3; i++) {
*((int *)((char *)&pdevs[indexes[i]] + offset)) = value;
}
}
Then you call it like:
fill_structs(pdevs, offsetof(struct deviations, y), top, -1);
offsetof() returns the offset in bytes of a structure member from the base of the structure. So in the function you have to convert the address of the array element to char * so you can add the offset to it, then convert it to int * so you can dereference it and assign to the int member there.
BTW, you should get out of the habit of using things like
(pdevs + i) -> x
If you're using a pointer as the base of an array, use array syntax:
pdevs[i].x
It's much easier to tell that i is an array index this way.

This answer serves purely to challenge your thinking about your current approach.
Personally, unless there's some special logic involved, I would just ditch the loops completely and initialize your struct like this.
const struct deviations devs[8] = {
{ 1, -1, -1 }, // top-left
{ 1, 0, -1 }, // top
{ 1, 1, -1 }, // top-right
{ 1, -1, 0 }, // left
{ 1, 1, 0 }, // right
{ 1, -1, 1 }, // bottom-left
{ 1, 0, 1 }, // bottom
{ 1, 1, 1 } // bottom-right
};
If you then decide that you really need to allocate that dynamically then you could just copy it:
struct deviations *pdevs = malloc(sizeof(devs));
if (pdevs) memcpy(pdevs, devs, sizeof(devs));
But if you really wanted to generate this stuff in a loop, why not something like this?
int ii = 0;
for(int y = -1; y <= 1; ++y) {
for(int x = -1; x <= 1; ++x) {
if (x == 0 && y == 0) continue;
pdevs[ii].switch = 1;
pdevs[ii].x = x;
pdevs[ii].y = y;
++ii;
}
}

Related

How can I count how many horizontal brush strokes are required to draw an array of buildings?

By given an array of integers, each element represents a building. For example: int buildings[] = {1, 4, 3, 2, 3, 1}.
If I drew the buildings horizontally with a brush, how many brush strike I would use?
I should write a function that returns the number of these brush strokes. For example 5.
I can do it easily on run time O(n^2), by using 2 loops.
The external loop running on the levels of each building (according to the highest building).
The inner loop is running on the array from 0 to n, and compares the difference of the height (0 or 1) between two near elements.
How can I do this in the O(n) time and O(n) space?
A brush stroke starts whenever the height increases going from left to right, and ends when it decreases. You only need to look at when it increases, because if you just count the starting points of each stroke you will have the stroke count. Instead of looping over the height levels in an inner loop, just subtract one height level from the previous to get the difference.
In pseudo-code:
int BrushCount(int[] buildings)
{
int brushCount = 0;
int prevHeight = 0;
for(int i = 0; i < buildings.length; i++)
{
if(buildings[i] > prevHeight)
brushCount = brushCount + (buildings[i] - prevHeight);
prevHeight = buildings[i];
}
return brushCount;
}
Runs in O(n).
A little code golf :) (Based on samgak's excellent explanation.)
const f = A => A.reduce((a,b,i,A) => a + Math.max(0, b - A[i-1]));
console.log(f([1, 4, 3, 2, 3, 1]))
console.log(f([4, 1, 2, 1, 2, 2]))
Counting from the end of the array use the last element as the initial value of the result, and compare the previous one with the current one.
If they are the same value then, the result increase one;
if the previous one is smaller than the current one, do nothing;
if the previous one is bigger than the current one then, result = result +previous-current
int i=sizeof buildings;
int t=buildings[i];
while(i>0){
if(buildings[i-1]-buildings[i]>0) t+=(buildings[i-1]-buildings[i]);
else if(buildings[i-1]-buildings[i]==0) ++t;
--i;
}
return t;
public static int brushCount(int[] buildings)
{
int count=0;
for(int i=0; i<=buildings.length-1; i++){
if((i+1)<(buildings.length)){
if(buildings[i]>buildings[i+1]){
count += buildings[i]-buildings[i+1];
}
}else{
count += buildings[i];
}
}
return count;
}
You can easily see that we need a stack like approach to keep heights in increasing order and add the difference between top element and current element when our current value is less than top value.
Since we don't values before the top, we can just keep a variable for the top element.
#include <bits/stdc++.h>
using namespace std;
using ll = int64_t;
int solve(vector<int> v) {
int brushes = 0, lastMax = 0;
for (auto val: v) {
if (val > lastMax) {
brushes += lastMax - val;
}
lastMax = val;
}
brushes += lastMax;
return brushes;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
vector<int> v1 {1, 4, 3, 2, 3, 1}, v2 {4, 1, 2, 1, 2, 2};
cout << solve(v1) << ' ' << solve(v2) << endl; // 5 6
}
Kotlin version of #samgak's answer:
fun brush(nums: IntArray): Int {
var c = 0
var ph = 0
nums.forEach {
if (it > ph) c += (it - ph)
ph = it
}
return c
}
Shortly java answer:
int BrushCount(int[] buildings) {
int s=0,p=0;
for(int x:buildings) s-=(x>p?p:x)-(p=x);
return s;
}

C data format redoing

I have data stored as
float testdata3[][7] = {
{171032, 0.4448, -0.3032, -0.7655, -1.3428, 13.5803, -73.0743},
{172292, 0.0099, 0.1470, -0.7301, -17.2272, 7.0038, -11.7722},
{173547, 0.0576, 0.1333, -0.8163, -2.7847, -9.5215, 8.1177 },
...
}
where I am only interested in the second, third and fourth indexes. How can I create a function where it would return for example first, second and third index as their own table from the testdata I have.
For example
testdata_x = {0.4448, 0.099, 0.0576, ...}
testdata_y = {-0.3032, 0.1470, 0.1333, ...}
testdata_z = {-0.7655, -0.7301, -0.8163, ...}
Help would be much appreciated. I am trying to read sensor values from test data and im only interested in acceleration values in x, y and z directions.
You didn't post any code so I'm going to be a bit more vague than normal.
If we create an array of 7 elements such as: int arr[7] = {1, 2, 3, 4, 5, 6, 7};
Accessing the 2nd, third, and 4th elements is as simple as arr[1], arr[2], arr[3] respectively.
That should help with gleaning the data from the existing arrays, but as for making your new array. I don't see any reason to use a multidimensional array instead of 3 regular arrays. All you need to do from here is find out the amount of arrays in testData in order to know how much to allocate and you should be on your way.
So you want to transpose a matrix? then just iterate in the reverse order
#include <stdio.h>
int main(void)
{
double arr[][7] = {
{171032, 0.4448, -0.3032, -0.7655, -1.3428, 13.5803, -73.0743},
{172292, 0.0099, 0.1470, -0.7301, -17.2272, 7.0038, -11.7722},
{173547, 0.0576, 0.1333, -0.8163, -2.7847, -9.5215, 8.1177},
};
#define ROWS sizeof arr / sizeof arr[0]
#define COLS sizeof arr[0] / sizeof arr[0][0]
double test[COLS][ROWS]; /* 7 x 3 */
for (size_t i = 0; i < COLS; i++) {
for (size_t j = 0; j < ROWS; j++) {
test[i][j] = arr[j][i];
}
}
return 0;
}
I don't know what you are looking for but here are several approaches starting from easiest one:
1) You can directly assign a value using indexes to the new array
2) If you need function you can allocate new array inside it assign all
values and return it from a function
It's supposed that indexes never change for x,y,z.
#include <stdio.h>
#include <stdlib.h>
enum
{
X,
Y,
Z
};
float testdata3[][7] = {
{171032, 0.4448, -0.3032, -0.7655, -1.3428, 13.5803, -73.0743},
{172292, 0.0099, 0.1470, -0.7301, -17.2272, 7.0038, -11.7722},
{173547, 0.0576, 0.1333, -0.8163, -2.7847, -9.5215, 8.1177 },
};
float *get_dataa(int coordinate)
{
float *data;
switch(coordinate) {
case X:
data = malloc(sizeof(float) * 3);
data[0] = testdata3[0][1];
data[1] = testdata3[1][1];
data[2] = testdata3[2][1];
return data;
default:
return NULL;
}
}
int main(void)
{
/* first way */
float testdata_X[] = { testdata3[0][1], testdata3[1][1], testdata3[2][1] };
printf("Test number 1 for X %0.4f, %0.4f, %0.4f\n", testdata_X[0], testdata_X[1], testdata_X[2]);
/* second */
float *testdata_xX = get_dataa(X);
printf("Test number 2 for X %0.4f, %0.4f, %0.4f\n", testdata_xX[0], testdata_xX[1], testdata_xX[2]);
free(testdata_xX);
return 0;
}
output:
Test number 1 for X 0.4448, 0.0099, 0.0576
Test number 2 for X 0.4448, 0.0099, 0.0576

using function to find max value in an array

Can someone please explain what I'm doing wrong. I need to use an array to find the max value of the percentages array and display that amount and the year in the corresponding years array.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int findHighNumber (double percentages[], int elements);
int main (void)
{
int index;
int elements;
int years[] = {2000, 2002, 2004, 2006, 2008, 2010, 2012};
double percentages[] = {6.7, 6.6, 8, 9, 11.3, 14.7, 14.6};
int sampleSizes[] = {187761, 444050, 172335, 308038, 337093, 1000, 346978};
int high = findHighNumber(percentages, elements);
printf ("%i had the highest percentage with autism at %.2lf%%.\n", years[high], percentages[high]);
return 0;
}
int findHighNumber (double percentages[], int elements)
{
int index, high;
high = percentages[0];
for (index = 1; index < elements; index++)
if (high < percentages[index])
{
high = percentages[index];
}
return high;
}
First, you have to declare the elements variable in main():
int elements = 7;
or even better:
int elements = sizeof(percentages) / sizeof(*percentages);
which computes the array size automatically.
Then, don't modify the elements variable in you loop.
If you do it, each time the current maximum is changed, you program your loop to stop after the next element, potentially missing the real maximum which can be located at the end of the array.
Then, like Bob said, you should return the index of the maximum, this way, you can retrieve the corresponding sampleSize, or year.
When you do years[high], you're using a percentage as an array index which can take any real value in [0,100], instead of an index which must stay in {0, 1, 2, 3, 4, 5, 6}.
What's more, you store high in an integer variable, resulting in a truncation of it's value. You may prefer to store it as a double variable.
So findHighNumber() can become:
int findHighNumber(double percentages[], int elements)
{
int index;
double high;
int high_index;
high_index = 0;
high = percentages[high_index];
for (index = 1; index < elements; index++)
if (high < percentages[index]) {
high = percentages[index];
high_index = index;
}
return high_index;
}
The main() function now can become something like:
int main (void)
{
int years[] = {2000, 2002, 2004, 2006, 2008, 2010, 2012};
double percentages[] = {6.7, 6.6, 8, 9, 11.3, 14.7, 14.6};
int sampleSizes[] = {187761, 444050, 172335, 308038, 337093, 1000,
46978};
int elements = sizeof(percentages) / sizeof(*percentages);
int high_index = findHighNumber(percentages, elements);
printf ("%i had the highest percentage with autism at %.2lf%% (sample"
"size was %d).\n", years[high_index], percentages[high_index],
sampleSizes[high_index]);
return 0;
}
Then, some small advices:
putting a prototype of findHighNumber() is not needed, just define the function above the places where it's needed. This way, when you really have to put a prototype for a function, it a hint saying that you were forced to do so, (for example for mutually recursive functions), plus it shortens the code.
you should define a, for example, struct autism_sample like that:
struct autism_sample {
int year;
int sample_size;
double percentage;
};
This way, you just have to define one array:
struct autism_sample autism_samples[] = {
{
.year = 2000,
.sample_size = 187761,
.percentage = 6.7,
},
{
.year = 2002,
.sample_size = 444050,
.percentage = 6.6,
},
...
};
This way, your data is organized in a more logical way, less error-prone to maintain and you gain the choice, in the implementation of findHighNumber(), to return either the index of the maximum or directly, a pointer to the element holding the maximum, the index becomes then useless.
What's more, it's easier to (un)serialize...
I'm not sure if this is a typo here, but it appears while calling
int high = findHighNumber(percentages, elements);
you don't have a variable elements defined there. That said, you have another syntax error (missing the closing }) near
if (high < percentages[index])
{
high = percentages[index]; ///after this.
Finally, inside findHighNumber (), elements is local to the function, so, the only usage as elements = index+1; is useless.
Given the way you are storing and using data, you should return the index where the higher element is, not its value.
Also you have to pass the right size of the array (and don't change it inside the function), while you are passing an uninitialized value.
You should send the index instead of the value.
int findIndexOfMax (double percentages[], int elements) {
int index = 0;
int highIndex = 0;
double high = 0.0;
high = percentages[highIndex];
for (index = 1; index < elements; index++)
{
if (high < percentages[index])
{
high = percentages[index];
highIndex = index;
}
}
return highIndex;
}
You are returning the wrong value .. you should not return what's the highest value but you should return the index of it.
or you you can simply print the result that you want in the function you're calling.
Also, I don't see that you have initialized the variable elements.

MQL4 array creating variables

I'm trying to make this function create X number of variables using an array. I know that this is technically wrong because I need a constant as my array's value (currently 'x'), but excluding that, what am I missing? Looked at so many code samples and can't figure it out, but I know it's got to be simple...
void variables()
{
int i;
int bars = 10;
int x = 1;
for (i = 1; i <= bars+1; i++)
{
int variables[bars] = { x };
x++;
if (i >= bars+1)
{
break;
}
}
void variables()
{
int bars = 10;
if(bars >= Bars) bars = Bars - 1;
// to be able to set array size based on variable,
// make a dynamically sized array
double highvalues[];
ArrayResize(highvalues, bars);
for (int i = 0 /*Note: Array index is zero-based, 0 is first*/; i <= bars; i++)
{
highvalues[i] = iHigh(NULL, 0, i);
// or
highvalues[i] = High[i];
}
}
It is hard to tell what do you want to achieve.
If you want to fill an array with a value ArrayFill() fill help you.

Initialize an "eye" (identity) matrix array in C

int eye[3][3] = {
{ 1,0,0 },
{ 0,1,0 },
{ 0,0,1 }
};
Is there a shorter way to initialize it? It's so regular that there must be a smarter way to initialize it, especially if it's more than 3x3, say 10x10 or more.
In c99 you can write:
int eye[][3] = { [0][0] = 1, [1][1] = 1, [2][2] = 1 };
all other elements are zeroed, moreover the compiler figures out the size of the array for you. Just don't skip the second size (3).
Btw. in your code you don't have to use the double braces, this would be fine too:
int eye[3][3] = {
1,0,0,
0,1,0,
1,0,1,
};
In c99 you can also leave the trailing comma, just for symmetry and future refactorings
Other solutions probably require you to write some code, which may indeed save you some time/space in file. But note that this way you're splitting declaration and "initialization", which in case of e.g. globals can make a difference.
You can use designated initializers:
int eye[3][3] = { [0][0]=1, [1][1]=1, [2][2]=1};
All the other elements will be initialized to 0 as per C standard's guarantee.
You may try the following:
#define SIZE 3
int eye[SIZE][SIZE] = {0};
for (int i = 0; i < SIZE ; ++i)
{
eye[i][i] = 1;
}
If you want to store {{ 1,0,0 }, { 0,1,0 }, ...} this style of values in square matrix means, you can write a simple logic as below.
#define SIZE 3
int eye[SIZE][SIZE] = {0};
int *p = (int *)eye;
for (i = 0; i < (SIZE * SIZE); i = i + (SIZE + 1))
{
p[i] = 1;
}
or
for (i = 0; i < SIZE; i++)
{
for (j = 0; j < SIZE; j++)
{
if (i == j)
{
eye[i][j] = 1;
}
else
{
eye[i][j] = 0;
}
}
}
Note : Above logic is only for the sample value you have given. So try to find similar logic if your values are having some relation. If not so, then no other way to initialize it directly even if size of matrix is 1000x1000.

Resources