Incrementing a struct name for new entries - c - c

So i'm trying to use i in the name of my struct entries so I can increment it everytime I make a new entry. However, it says I must use a constant value.
But obviously if I use #define i (2) for example, I wouldn't be able to increment it since it's constant.
struct order {
char orderName[15];
int orderQuantity;
int orderUnderTen;
int orderUnderSixteen;
int orderStudent;
int orderOverSixty;
int orderNA;
double orderTotal;
};
int i;
struct order s[i] = { "John", 5, 0, 0, 0, 0, 5, 25.00 };
Am I going about this in the wrong way?
Is there a better way to increment so I can store new entries?
Thank you.

Value i has an unknown, potentially random value, because you have not set it yet!
Is this line trying to set the first element of the array, or the 10th element?
struct order s[i] = { "John", 5, 0, 0, 0, 0, 5, 25.00 };
With no valid value for i, it could be anything!
You must first decide how big you want your array to be.
int i = 0;
struct order s[10] = { { "John", 5, 0, 0, 0, 0, 5, 25.00 },
{ "Mark", 6, 0, 0, 0, 0, 6, 30.00 },
{ "Luke", 7, 0, 0, 0, 0, 7, 35.00 } };
s[3] = (struct order){ "Matt", 8, 0, 0, 0, 0, 8, 40.00 };
i = 4;
s[i] = (struct order){ "Mike", 9, 0, 0, 0, 0, 9, 45.00 };
i++;

So you want an array. If you are defining everything up front in your program code, you can let it create an array with automatic size, like this:
#include <stdlib.h>
struct data {
int id;
char name[256];
};
struct data data[] = {
{1, "Jon"},
{2, "Fred"},
};
const size_t data_len = sizeof(data) / sizeof(data[0]);
Now you can add more lines to "data" and it automatically figures out how big to make the array when it compiles the code.
In a realistic program you would load these from a data file or database and you would need to use malloc and realloc to allocate and grow a dynamic array.

You can perform an assignment to an entire structure if you use a compound literal:
struct order s[i] = (struct order){ "John", 5, 0, 0, 0, 0, 5, 25.00 };

Related

Pointers and typedef structs, what to do when you call a function in C

I have a program that has to use ShowMe (int *p) and from the main function when it is called it needs to pull the values out of typedef Pyramid A.
this is the typedef struct declaration
typedef struct _Pyramid
{
double element [N][N];
} Pyramid;
I have gotten incompatible errors, I understand they're not the same type. I have tried casting and have been told I can't do that.
I have tried every-way I'm currently aware of to get this to work. So how would I call the function ShowMe (int *p) in main and pass it the values of Pyramid A?
I will post the code if asked. But I'm tired of being told what I'm doing wrong (which I mostly had already figured out from the errors) without any direction on what to do right. I will emphasize again. I'm new to C and I'm very tired and have worked on something for more than a couple of days before I post.
#include <stdio.h>
#include <stdlib.h>
#define N 8
typedef struct _Pyramid{
double stone [N][N];
} Pyramid;
int data[N*N];
Pyramid ShowMe(int *p) // pass in data and return Pyramid
{
int i;
int j;
for (i=0; i<N; i++)
{
for (j=0; j<N; j++)
{
printf("%g ", a.stone[i][j]);
}//Inner for
printf("\n");
}//Outer For
}//IZZ
int main(int argc, char **argv)
{
// special case that allows us to initialize this way
Pyramid A = {10, 4, 2, 5, 1, 0, 0, 0,
3, 9, 1, 2, 1, 0, 0, 0,
-7, -5, 1, -2, -1, 0, 0, 0,
-3, -5, 0, -1, 0, 0, 0, 0,
-2, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0};
ShowMe(int *A);
}//main
Your stumbling block is more about handling the struct as a parameter. A struct is simply a data type in C. It is passed as a parameter just as any other data type (int, long, char, etc...) and follows the same rules.
The convenience of a typedef allows you to specify the parameter as Pyramid var rather than having to use the full struct Pyramid var as you would without it. In fact, you don't even need the _Pyramid name for the struct when using a typedef, e.g.
typedef struct { /* you can simply typedef a struct */
double stone [N][N];
} pyramid_t;
Above, the typedef simply aliases an unnamed struct containing an array of doubles to the pyramid_t name, which you can use in declaring instances of the struct, e.g.
/* explicit way to initilize 2D array as 1st member of struct */
pyramid_t a = {{{10, 4, 2, 5, 1, 0, 0, 0},
{ 3, 9, 1, 2, 1, 0, 0, 0},
{-7, -5, 1, -2, -1, 0, 0, 0},
{-3, -5, 0, -1, 0, 0, 0, 0},
{-2, 1, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0}}};
Whether you include _Pyramid or not is up to you. (without it, you simply lose the ability to refer to struct _Pyramid as a declared type).
Your declaration of int data[N*N]; is a red-herring, a distraction of no consequence that isn't relevant to what you are attempting to do. You initialize an instance of your struct in main(). You simply need to pass the struct (or better, a pointer to your struct) to your showme[1] function in order to have the values available for printing there.
For example, including the typedef to specify you are passing the struct as a parameter (where the function receives a copy of the struct) you output the values using the dot '.' operator as you have in your function, e.g.
/* function type is void if it returns no value */
void showme (pyramid_t p)
{
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++)
printf("%3g ", p.stone[i][j]);
putchar('\n'); /* use putchar() to output single char */
}
}
You would then call your function in main() as:
showme (a); /* passing a copy of the struct to showme() */
(note: the function receives a copy of the struct -- so try changing some of the array values and then print the contents again back in main() ... any changes made are lost)
A more efficient way of passing the struct would be to pass a pointer to the struct, so that all that is being passed is the address of where the structure is stored in memory. Not only does that avoid making a copy of the struct, but by passing the address, any changes you make to the structure values are then preserved (because you are directly changing the values of the original struct in memory -- not simply making changes to a copy). When you pass a pointer to a struct (or anytime you are accessing values of a struct through a pointer), you use the arrow operator (->) to access the struct members. For example, you could have just as easily have declared showme() to take a pointer to pyramid_t instead of a struct, e.g.
/* function type is void if it returns no value */
void showme (pyramid_t *p)
{
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++)
printf("%3g ", p->stone[i][j]);
putchar('\n'); /* use putchar() to output single char */
}
}
To pass a pointer to your struct in main(), you simply use the unary '&' operator (address of) to pass the address of a, e.g.
showme (&a); /* pass pointer to prevent duplicating struct */
Now if you made changes to the array values in the function, the changes would be visible back in main() because you changed the values where they were stored in memory rather than operating on a copy passed to the function.
Look at both examples and understand the differences both in declaring the showme() function and how it is called in main(). The first example passing a copy of the struct and using the dot-operator to access the member would be:
#include <stdio.h>
#include <stdlib.h>
#define N 8 /* good job - if you need a constant, #define one (or more) */
typedef struct { /* you can simply typedef a struct */
double stone [N][N];
} pyramid_t;
/* function type is void if it returns no value */
void showme (pyramid_t p)
{
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++)
printf("%3g ", p.stone[i][j]);
putchar('\n'); /* use putchar() to output single char */
}
}
int main (void) { /* unless using argc, argv, use void */
/* explicit way to initilize 2D array as 1st member of struct */
pyramid_t a = {{{10, 4, 2, 5, 1, 0, 0, 0},
{ 3, 9, 1, 2, 1, 0, 0, 0},
{-7, -5, 1, -2, -1, 0, 0, 0},
{-3, -5, 0, -1, 0, 0, 0, 0},
{-2, 1, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0}}};
showme (a); /* passing a copy of the struct to showme() */
return 0; /* main() is type 'int' and returns a value */
}
To pass a pointer containing the address of the original struct, you would simply change the declaration of showme() and the operator used to access the struct members:
/* function type is void if it returns no value */
void showme (pyramid_t *p)
{
...
printf("%3g ", p->stone[i][j]);
...
}
And, as explained above, you would simply call showme() with the address of a, e.g.
showme (&a); /* pass pointer to prevent duplicating struct */
In either case the output would be the same, e.g.
Example Use/Output
> bin\pyramid-struct.exe
10 4 2 5 1 0 0 0
3 9 1 2 1 0 0 0
-7 -5 1 -2 -1 0 0 0
-3 -5 0 -1 0 0 0 0
-2 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
Look things over and understand the differences, and let me know if you have further questions.
footnotes:
[1] While not an error, C style generally avoids the use of MixedCase or camelCase variables and the use of all-uppercase names (reserving all uppercase names for constants or macros), instead using variables names of all lowercase. While this is an issue of style, and completely up to you, it can lead to the wrong first-impressions in some settings.
Casting the type Pyramid* as an int* will violate the strict aliasing rule and could cause some undefined behaviors. Passing a char* instead of an int* for ShowMe() is a possible workaround, since char pointers are an exception to the strict aliasing rule. For more information and workarounds, check this post.

Pointer to 2D array as parameter in function in c

I'm writing a Sudoku solving program and I'm a bit confused on using pointers with 2D arrays. Currently I am defining a puzzle like so:
int puzzle[9][9] = {
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0}
};
and then I have a function called backtrack which will solve this recursively using backtracking. I need to pass puzzle to backtrack so I can modify it inside the function. Currently backtrack looks like
int backtrack(int (*p)[9][9]){
int puzzle[9][9] = *p;
//actual logic is here
return 0;
}
but gcc gives an error saying that int puzzle[9][9] = *p; is an invalid initializer
I am under the impression that int (*p)[9][9] is a pointer to a 9 x 9 int array, so I should be able to turn this into a int puzzle[9][9] by dereferencing p, but this doesn't seem to work.
It is not possible to assign to all elements of an array at once using an assignment expression, it is possible to initialize some or all elements of an array when the array is defined.
A 1D array decays to a pointer. However, a 2D array does not decay to a pointer to a pointer.
If you declare backtrack like this:
int backtrack(int arr[][9]);
or even better
int backtrack(int r, int c, int arr[][c]);
and call like:
int backtrack(puzzle);
int backtrack(9,9, puzzle);
any modifications to the arr[x][y] element modify the original array puzzle.
arr, the argument in backtrack, is of type int (*)[c].
Edit:
The explicit use of pointers in the calling function is of course possible as shown:
#include <stdio.h>
#include <stdlib.h>
#define NR_OF_ROWS 9
void backtrack1(int nr_of_columns, int *array){
// access to
// array[i][j] =
// *(array + i*nr_of_columns + j)
}
void backtrack2(int nr_of_columns, int array[][nr_of_columns]){
//...
}
int main(void)
{
int nr_of_columns = 9; // number of columns
int *ptr1; // (to show how to init a pointer to puzzle1)
int (*ptr2)[nr_of_columns]; // (to show how to init a pointer to puzzle2)
int puzzle1[NR_OF_ROWS][nr_of_columns]; // declare puzzle1
int puzzle2[NR_OF_ROWS][nr_of_columns]; // declare puzzle2
ptr1 = &puzzle1[0][0]; // pointer `ptr1` points to first element in the puzzle1
ptr2 = puzzle2; // pointer `ptr2` points to first element in the puzzle2
// 1a. call `backtrack1` function
backtrack1(nr_of_columns, ptr1); // or `backtrack1(nr_of_columns, &table1[0][0]);`
// 2a. call `backtrack2` function
backtrack2(nr_of_columns, ptr2); // or simply `backtrack2(nr_of_columns, table2);
return 0;
}
Though the parameter declaration is correct but it seems you mean the following
int backtrack(int (*p)[9]){
and the function is called like
backtrack( puzzle );
When an array is used as an argument it is implicitly converted to pointer to its first element. In case of the array puzzle the first element of the array is the first "row" that is a one-dimensional array of the type int[9].
The syntax to access an element of the array is look like
p[i][j]
where i and j are some indices.
Take into account that when the parameter is declared like
int backtrack(int p[9][9]){
nevertheless the compiler adjusts it in any case like
int backtrack(int (*p)[9]){
You could declare the parameter like
int backtrack(int (*p)[9][9] ){
but in this case the function is called like
backtrack( &puzzle );
and the body of the function would be too complicated. For example the syntax to access an element of the original array will look like
( *p )[i][j]
Also this statement in the function
int puzzle[9][9] = *p;
does not make sense. You may not initialize an array such a way. I think this statement is redundant in implementation of the function. You already have the poinetr p that points to the first "row" of the array. And you can change the original array or traverse its elements using this pointer. In fact all elements of the array are passed by reference through the pointer p.

Modify a 2D array using passing by reference in C

I've been working on a simple C checkers game.
I want the function cargar_partida (load game) to read a text file which contains a list of numbers (64 in total) that represent every position in the game.
1 represents a blank space that can be occupied, 0 a blank space that can't be occupied, 2 the white pieces and 3 the black ones.
FIL and COL value is 8.
Here's the function:
int cargar_partida(int *turno, int *tablanueva[FIL][COL]) {
int i, j;
FILE * archivo;
archivo = fopen("partida.txt", "r");
if (archivo == NULL) {
printf("Error al abrir el archivo.\n");
exit(0);
}
fscanf(archivo, "%d", turno);
for (i = 0; i < FIL; i++) {
for (j = 0; j < COL; j++) {
fscanf(archivo, "%d", tablanueva[i][j]);
}
}
}
The variable turno (turn in english) is loaded correctly, but the 2D array tablanueva (new array) isn't.
NOTE: In the file partida.txt the variable turno is the first one to apear, the other values apear each one in a different row.
This is the initial array, which has to be changed when cargar_partida is called. The problem is that the function doesn't change it. The array's declaration is located in the main function.
int tabla[FIL][COL] = {
{0, N, 0, N, 0, N, 0, N},
{N, 0, N, 0, N, 0, N, 0},
{0, N, 0, N, 0, N, 0, N},
{VAL, 0, VAL, 0, VAL, 0, VAL, 0},
{0, VAL, 0, VAL, 0, VAL, 0, VAL},
{B, 0, B, 0, B, 0, B, 0},
{0, B, 0, B, 0, B, 0, B},
{B, 0, B, 0, B, 0, B, 0},
};
This is how the function is called.
cargar_partida(&opcion, tabla);
You are passing a double pointer (tabla) as a parameter in
cargar_partida(&opcion, tabla);
The function expects a pointer to a 2D array (a triple pointer). Thus, you have to change the type of the second parameter in your function.
This should work
int cargar_partida(int *turno, int tablanueva[FIL][COL])
if it does not work, let us know.

Initialize a 2d array inside a struct

I am trying to initialize a 2d array of ints inside a struct.
In the beginning of my program (global access) I have created a struct, and an array of this struct:
struct block {
int theblock[3][3];
};
struct block blockArray[6];
Then I am trying to initialize the array of structs in a function:
void afunction() {
int block1[3][3] = {
{0, 1, 0},
{0, 1, 0},
{0, 1, 0}
};
blockArray[0].theblock = block1;
}
Compiler error:
error: incompatible types when assigning to type 'int[3][3]' from type 'int[*][3]'
Could anyone please explain what I have done wrong here, I know this is pretty basic stuff but I have really tried to read up and solve this on my own. I am coming from Java and trying to learn C.
Create a temporary struct and assign it to your element of the array of structs:
struct block temp = { { {0, 1, 0}, {0, 1, 0}, {0, 1, 0} } } ;
blockArray[0] = temp ;
or just use your array and copy it:
int temp[3][3] = { {0, 1, 0}, {0, 1, 0}, {0, 1, 0} } ;
assert( sizeof( temp ) == sizeof( blockArray[0].theblock ) ) ;
memcpy( blockArray[0].theblock , temp , sizeof( temp ) ) ;
You can not copy an array this way in C. For that matter, I didn't think you could do it in Java either.
You can copy the pointers around, for instance
blockArray[0].theblock = block1;
But all this will do is to have blockArray[0].theblock point at the same address as &block1[0]. It does not copy any content, it's a shallow copy.
You'll have to copy the members over with memcpy() or in loop(s):
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
blockarray[0].theblock[i][j] = block1[i][j];

Calling variables with pointers in a typedef

Hello i know a bit about pointers in C but the problem I am running into is how to access variables in an this typedef enum.
The structure is defined as:
typedef enum {
ZERO = (uint8_t) 0, ONE = (uint8_t) 1
} BIT;
typedef BIT lc3_word_t[16];
and the method that is calling it is:
word_not(lc3_word_t *R, lc3_word_t *A) {
/*int i;
for (i=0;i<16;i++){
printf("Current i is: '%d' and the value is: '%d' \n", i, *A[i]);
//lc3_word_t a_value = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1}; // 13
}
*/
}
The commented out section is what I have been trying along with some other variations that were introduced in this post: Understanding C: Pointers and Structs
If anyone could help me get this it would be greatly appreciated.
THanks
You want to use (*A)[i], not *A[i].

Resources