Initializing a Peg Solitaire Board in C [duplicate] - c

Im trying to initialize 2d array of chars with this ode
int x=4;
int y=4;
char plg[x][y]={{"o","o","o","o"},{"o","o","o","o"},{"o","o","o","o"},{"o","o","o","o"}};
but this piece of code throws error error: excess elements in char array initializer| i was searching for a while and everything says this is the rigth method how to do 2d char array. Why does it throw error?

In C you cannot use dynamic expressions as array sizes for global variables. It is possible for local variables since the C99 Standard, but these arrays known as VLA cannot be initialized.
For your purpose, you must specify the size directly with literal constants or constant expressions. You can use macros to increase readability, but it is a bad idea to #define x 4 as short identifiers like x may be used elsewhere in your program and will be substituted as well, leading to obscure bugs.
You cannot initialize the 2D array of char with a string for each individual char, you can either use character literals this way:
char plg[4][4] = {
{'o','o','o','o'},
{'o','o','o','o'},
{'o','o','o','o'},
{'o','o','o','o'}
};
Or you can use string literals to initialize the last level of the array:
char plg[4][4] = {"oooo", "oooo", "oooo", "oooo" };
Note that although you can elide the inner braces with char literal initializers this way:
char plg[4][4] = {'o','o','o','o','o','o','o','o','o','o','o','o','o','o','o','o' };
It is not possible to coalesce string initializers this way:
char plg[4][4] = { "oooooooooooooooo" }; // warning: initializer-string for char array is too long
The syntax above only initializes the first subarray with 'o's, leaving the remaining 3 initialized with '\0's
If you really need for the sizes to be dynamic, you will need to initialize the array some other way:
void myfunc(int x, int y) {
char plg[x][y];
int scores[x][y];
// you can initialize char arrays this way
memset(plg, 'o', sizeof(plg));
// you need a loop for other types
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
scores[i][j] = 1;
}
}
...
}
You still need to be careful with this feature: you must check user input a avoid allocating too much data in automatic storage (aka on the stack). Sufficiently large or possibly negative values of x or y will invoke undefined behavior. Only small values should be allowed, typically less than 256. For a more general solution, you will need to allocate plg from the heap.

"this is a string"
and
'o' /* this is a character */

#define N_ROWS 4
#define N_COLS 4
you have to replace " with ' (single) cause it's not string but chars:
char plg[N_ROWS][N_COLS]={{'o','o','o','o'},{'o','o','o','o'},{'o','o','o','o'},{'o','o','o','o'}};
moreover the initializers have to be definied during compile time not during runtime otherwise it would be a dynamic array for which you need to allocate memory manually.

Usually you need to define rows and cols when declaring a matrix, such as:
#define N_ROWS 4
#define N_COLS 4
char plg[N_ROWS][N_COLS]={{'o','o','o','o'},{'o','o','o','o'},{'o','o','o','o'},{'o','o','o','o'}};
Now if you need rows and cols as input variables, you need to dynamically allow the array. For example,
#include <stdlib.h>
#include <string.h>
int x = 4;
int y = 4;
char **plg = malloc(sizeof(char *) * x);
int i = 0;
for( i = 0; i < x; i++ )
{
plg[i] = malloc(sizeof(char) * (y + 1)); // +1 for NULL terminator
}
for( i = 0; i < x; i++ )
{
strcpy( plg[i], "oooo" );
printf( "%s \n", plg[i] );
}

Related

Can I assign an array to a dynamically created array (using pointers) the way you would normally initialize an array[]?

I tried this following code but it clearly didn't work:
void main3()
{
int n;
printf("Input the dimension of the array");
scanf("%d", &n);
int* testMatrix2 = malloc(sizeof(int) * n);
testMatrix2 = {512, 51, 642}; //is there a way to do this? "expected an expression" error
}
As the comment shows, is there a way to initialize an array as you would normally do without using arrays? I know it's a risky move, but it would make my life easier during testing.
The use of for cycles would not be feasible for me as I need a sort of randomness in the array.
As #EugeneSh. stated it is not possible for any size array. If the array has a fixed size you can wrap it into the structure:
typedef struct
{
int x[10];
}wrappedArray;
void foo(void)
{
wrappedArray *wa = malloc(sizeof(*wa));
*wa = (wrappedArray){1,2,3,4,5,6,7,8,9,10};
}
Arrays are "non-modifiable" L-values. Therefore they cannot be assigned with = operator.
However, you could memcpy from a compound literal.
memcpy(testMatrix2, (const int[]){512, 51, 642}, sizeof(int[3]));
Just ensure that n >= 3 before doing this to avoid Undefined Behavior.
As the other post already shown how to copy array to dynamically allocated space. Just in case if you don't need to access the array in some other function (or out of scope), then no need to allocate space dynamically. You can use compound literal:
#include <stdio.h>
int main (void) {
int* testMatrix2 = (int []){512, 51, 642};
for (int i = 0; i < 3; ++i) {
printf ("%d ", testMatrix2[i]);
}
printf ("\n");
return 0;
}
Output:
# ./a.out
512 51 642
Compound literals Constructs an unnamed object of specified type in-place.
In this statement of above program
int* testMatrix2 = (int []){512, 51, 642};
(int []){512, 51, 642} is a compound literal. It will create an unnamed automatic array of type int [3], initialise the array to the value 512, 51 and 642 and the pointer to first element of this array object will be assigned to testMatrix2.

initializing array of pointers to Integers

I was trying to initialize and print array of pointers to integers.
Is this method of initialization is correct or any other method is available to initialize when we declare it as array of pointers. We can also use traditional array of arrays ar1[][] anyway.
#include <stdio.h>
#include <stdlib.h>
#define NUM_COLS 4
#define NUM_ROWS 3
int main(void)
{
int rowCnt;
int colCnt;
int *ar2[NUM_ROWS]={
(int[]){11,12,13,14},
(int[]){21,22,23,24},
(int[]){31,32,33,34},
};
for(rowCnt=0;rowCnt<NUM_ROWS;rowCnt++)
{
for(colCnt=0;colCnt<NUM_COLS;colCnt++)
{
printf("%d\t",*(*(ar2+rowCnt)+colCnt));
}
printf("\n");
}
return(0);
}
This initialization is correct; compound literals have lifetime to match the block they are declared in. The literals have the same lifetime as ar2 in this case.
However I would recommend using a simple array as in dbush's answer unless you have some extra requirement (such as wanting rows of differing lengths).
Since you know the number of rows and colums, you can define a 2D array (formally an array of arrays) instead of an array of pointers:
int ar2[NUM_ROWS][NUM_COLS]={
{11,12,13,14},
{21,22,23,24},
{31,32,33,34},
};
This declaration below is incorrect.
int *ar2[NUM_COLS]={
(int[]){11,12,13,14},
(int[]){21,22,23,24},
(int[]){31,32,33,34},
};
This is an array of NUM_COLS of pointers to ints. The memory of these pointers to ints do not get properly allocated this way, and will result in undefined behavior.
If you wanted to allocate the entire array on the stack, you could do something like this:
int ar2[NUM_ROWS][NUM_COLS]= {
{11,12,13,14},
{21,22,23,24},
{31,32,33,34},
{0,0,0,0}
};
If you want the pointers to ints to be properly on the heap, you should use malloc/free respectively
int *ar2[NUM_ROWS];
for (int i = 0; i < NUM_ROWS; ++i)
{
ar2[i] = (int*)malloc(sizeof(int) * NUM_COLS);
}
///now you can set up your arrays
memcpy(ar2[0], (int []){11,12,13,14}, 4 * sizeof(int));
memcpy(ar2[1], (int []){21,22,23,24}, 4 * sizeof(int));
memcpy(ar2[2], (int []){31,32,33,34}, 4 * sizeof(int));
///Do what you want with the array
...
///Free array once you are done
for (int i = 0; i < NUM_ROWS; ++i)
{
free(ar2[i]);
}

Write a signature of function accepts all 2D arrays of type int as parameter regardless of the method the user chose?

An example to illustrate:
#include <stdlib.h>
#include<stdio.h>
void simple_function(int s , int array[][s]);
int main(void){
int x;
/*Static 2D Array*/
int array[2][2];
/*Many Methods to Dynamically Allocate 2D Array....for example*/
/* Using Array of pointers*/
int *array1[2];
for(x=0;x<2;x++){array1[x] = calloc (2, sizeof(int));}
/*Using pointer to a pointer */
int **array2 = calloc (2, sizeof(int*));
for(x=0;x<2;x++){array2[x] = calloc (2, sizeof(int));}
/*Using a single pointer*/
int *array3 = calloc (4 , sizeof(int));
/* Codes To Fill The Arrays*/
/*Passing the Arrays to the function, some of them won't work*/
simple_function(2, array); /*Case 1*/
simple_function(2, array1); /*Case 2*/
simple_function(2, array2); /*Case 3*/
simple_function(2, array3); /*Case 4*/
return 0;
}
void simple_function (int s, int array[][s]){
int x,y;
for(x=0;x<s;x++){
for(y=0;y<s; y++){
printf ("Content is %d\n", array[x][y]);
}
}
}
My Question:
Is there a way to write the signature of the simple_function to let it accepts all cases regardless of the method that the user chose? If not, what is the most preferable for the function if I want to make a library?
You've actually declared two different types of objects, as shown below
Your array and array3 are both stored in memory as 4 contiguous ints. There's no additional information, you've simply reserved space for 4 ints, and the C specification requires that they are contiguous.
However, array1 and array2 are actually pointer arrays. Your code reserves memory for an array of two pointers, and each pointer points to an array of two ints. The ints will be arranged in groups of two, but the groups can be scattered anywhere in memory.
From this, it should be clear that the compiler cannot use the same code to access both types of array. For example, let's say that you're trying to access the item at array[x][y]. With a contiguous array, the compiler computes the address of that item like this
address = array + (x * s + y) * sizeof(int)
With a scattered array, the compiler computes the address like this
pointer = the value at {array + x * sizeof(int *)}
address = pointer + y * sizeof(int)
So you need two functions to handle those two cases. For the contiguous array, the function looks like this
void showContiguousArray( int s, int array[][s] )
{
for ( int x=0; x<s; x++ )
for ( int y=0; y<s; y++ )
printf( "array[%d][%d] = %d\n", x, y, array[x][y] );
}
For the scattered array, the function is
void showScatteredArray( int s, int **array )
{
for ( int x=0; x<s; x++ )
for ( int y=0; y<s; y++ )
printf( "array[%d][%d] = %d\n", x, y, array[x][y] );
}
Notice that those functions are identical, except for one thing, the type of the array argument. The compiler needs to know the type in order to generate the correct code.
If the array is declared in the same scope where it's used, then all of these details are hidden, and it seems that you're using the exact same code to access different types of arrays. But that only works because the compiler knows the type of the array from the earlier declaration. But if you want to pass the array to a function, then the type information must be explicitly specified in the function declaration.
Is there a way to write the signature of the simple_function to let it accepts all cases regardless of the method that the user chose?
"All the cases" apparently describes the different declarations array, array1, array2, and array3, the latter three of which are described in code comments as "Methods to Dynamically Allocate 2D Array." But none of the four types are the same as any of the others, and none of the latter three in fact declare 2D arrays nor pointers to such. None of them are even compatible with each other. Of the dynamic ones, only array3 can even usefully be converted to something comparable to array.
A dynamically-allocated 2D array would be referenced via a pointer of this type:
int (*array4)[2];
array4 = calloc(2 * sizeof(*array4));
So, no.
If not, what is the most preferable for the function if I want to make a library?
It depends on your objectives. If your function must be compatible with static 2D arrays, then something of the general form you presented, plus or minus the variable dimension, is the only alternative. If you want to support the pointer-to-pointer form, then that's fine, and usable with declarations like array1's and array2's, but not with array, array3, or array4.
Assuming that you want this for 2D arrays, perhaps this can get you started ...
void simple_function(int s, int t , int* array) {
int i, j;
for (i=0; i<s; i++) {
for (j=0; j<t; j++) {
// accessing your array elements
printf(" %d", *(array + i*t + j));
}
printf("\n");
}
}
int main(void)
{
int array[2][3];
array[0][0] = 1;
array[0][1] = 2;
array[0][2] = 3;
array[1][0] = 11;
array[1][1] = 12;
array[1][2] = 13;
array[2][0] = 21;
array[2][1] = 22;
array[2][2] = 23;
simple_function(3, 3 , array);
return 0;
}
The expression int **array2 is not a 2D array by the way, it is a variable that holds the address of a pointer variable.

array of dynamically declared struct

Suppose we want to construct an array of structs, where the definition of the struct cannot be known at compile time.
Here is a SSCCE:
#include <stdlib.h>
int main(int argc, char *argv[]){
if (argc < 3) return 1;
int n = atoi(argv[1]);
int k = atoi(argv[2]);
if ((n < 1) || (k < 1)) return 2;
// define struct dynamically
typedef struct{
int a[n];
short b[k];
}data_point_t;
int m = 10;
// construct array of `m` elements
data_point_t *p = malloc(sizeof(data_point_t)*m);
// do something with the array
for(int i = 0; i < m; ++i) p[i].a[0] = p[i].b[0] = i;
free(p);
return 0;
}
This works fine with gcc (C99), however it doesn't with clang, which yields:
error: fields must have a constant size:
'variable length array in structure' extension will never be supported
So I'm obviously relying on a gcc extension. My question is, how to deal with this kind of problem in standard conform C99? (Bonus question: how to do this in C++11?)
Note: Performance matters, when iterating p there should be aligned memory access. Dereferencing pointers in the loop, yielding random memory access, is not an option.
I think your best bet is to drop the idea of wrapping the array in a structure, bite the bullet and allocate a 2D array yourself.
This will mean that you need to do explicit indexing, but that would have to happen under the hood anyway.
When it comes to alignment, if you're going to visit every n array elements in each of the m arrays, it probably doesn't matter, it's better to make them compact to maximize use of cache.
Something like:
int *array = malloc(m * n * sizeof *array);
Then to index, just do:
// do something with the array
for(int i = 0; i < m; ++i)
{
for(int j = 0; j < n; ++j)
array[i * n + j] = j;
}
If you're very worried about that multiplication, use a temporary pointer. After profiling it, of course.
Sometimes you see this done with a helper macro to do the indexing:
#define INDEX(a, n, i, j) (a)[(i) * (n) + (j)]
then you can write the final line as:
INDEX(array, n, i, j) = j;
it's a bit clumsy since the n needs to go in there all the time, of course.
First of all, it only makes sense to wrap the array inside a struct in the case there are other struct members present. If there are no other struct members, simply allocate an array.
If there are other struct members, then use a flexible array member to achieve what you want. Flexible array members are well-defined in the C standard and will work on every C99 compiler.
// define struct dynamically
typedef struct{
type_t the_reason_you_need_this_to_be_a_struct_and_not_an_array;
int a[]; // flexible array member
}data_point_t;
// construct array of `m` elements
int m = 10;
size_t obj_size = sizeof(data_point_t) + n*sizeof(int);
data_point_t *p = malloc(m * obj_size);
In C++ you can of course use pointers much like you do now, but for a "proper" C++ solution the only viable solution is to use std::vector:
struct data_point_t
{
explicit data_point_t(const size_t sz)
: a(sz) // Construct the vector `a` with `sz` entries,
// each element will be zero initialized (`int()`)
{}
std::vector<int> a;
};
int main(int argc, char *argv[]){
// Read `n`...
int n = 10; // Just example
// Read `m`...
int m = 10; // Just example
// Construct vector of `m` elements
std::vector<data_point_t> p(m, data_point_t(n));
// Here the vector `p` contains `m` elements, where each instance
// have been initialized with a vector `a` with `n` elements
// All fully allocated and initialized
// Do something with the array
// ...
}
This is valid C++03 code, so unless you use something ancient (like Turbo C++) any compiler today should support it.

Returning a two-dimensional array in C?

I recently started programming C just for fun. I'm a very skilled programmer in C# .NET and Java within the desktop realm, but this is turning out to be a bit too much of a challenge for me.
I am trying to do something as "simple" as returning a two-dimensional array from a function. I've tried researching on the web for this, but it was hard for me to find something that worked.
Here's what I have so far. It doesn't quite return the array, it just populates one. But even that won't compile (I am sure the reasons must be obvious to you, if you're a skilled C programmer).
void new_array (int x[n][n]) {
int i,o;
for (i=0; i<n; i++) {
for (o=0; o<n; o++) {
x[i][o]=(rand() % n)-n/2;
}
}
return x;
}
And usage:
int x[n][n];
new_array(x);
What am I doing wrong? It should be mentioned that n is a constant that has the value 3.
Edit: Here's a compiler error when trying to define the constant: http://i.imgur.com/sa4JkXs.png
C does not treat arrays like most languages; you'll need to understand the following concepts if you want to work with arrays in C.
Except when it is the operand of the sizeof or unary & operator, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array. This result is not an lvalue; it cannot be the target of an assignment, nor can it be an operand to the ++ or -- operators.
This is why you can't define a function to return an array type; the array expression will be converted to a pointer type as part of the return statement, and besides, there's no way to assign the result to another array expression anyway.
Believe it or not, there's a solid technical reason for this; when he was initially developing C, Dennis Ritchie borrowed a lot of concepts from the B programming language. B was a "typeless" language; everything was stored as an unsigned word, or "cell". Memory was seen as a linear array of "cells". When you declared an array as
auto arr[N];
B would set aside N "cells" for the array contents, along with an additional cell bound to arr to store the offset to the first element (basically a pointer, but without any type semantics). Array accesses were defined as *(arr+i); you offset i cells from the address stored in a and dereferenced the result. This worked great for C, until Ritchie started adding struct types to the language. He wanted the contents of the struct to not only describe the data in abstract terms, but to physically represent the bits. The example he used was something like
struct {
int node;
char name[14];
};
He wanted to set aside 2 bytes for the node, immediately followed by 14 bytes for the name element. And he wanted an array of such structures to be laid out such that you had 2 bytes followed by 14 bytes followed by 2 bytes followed by 14 bytes, etc. He couldn't figure out a good way to deal with the array pointer, so he got rid of it entirely. Rather than setting aside storage for the pointer, C simply calculates it from the array expression itself. This is why you can't assign anything to an array expression; there's nothing to assign the value to.
So, how do you return a 2D array from a function?
You don't. You can return a pointer to a 2D array, such as:
T (*func1(int rows))[N]
{
T (*ap)[N] = malloc( sizeof *ap * rows );
return ap;
}
The downside to this approach is that N must be known at compile time.
If you're using a C99 compiler or a C2011 compiler that supports variable-length arrays, you could do something like the following:
void func2( size_t rows, size_t cols, int (**app)[cols] )
{
*app = malloc( sizeof **app * rows );
(*app)[i][j] = ...; // the parens are necessary
...
}
If you don't have variable-length arrays available, then at least the column dimension must be a compile-time constant:
#define COLS ...
...
void func3( size_t rows, int (**app)[COLS] )
{
*app = malloc( sizeof **app * rows );
(*app)[i][j] = ...;
}
You can allocate memory piecemeal into something that acts like a 2D array, but the rows won't necessarily be contiguous:
int **func4( size_t rows, size_t cols )
{
int **p = malloc( sizeof *p * rows );
if ( p )
{
for ( size_t i = 0; i < rows; i++ )
{
p[i] = malloc( sizeof *p[i] * cols );
}
}
return p;
}
p is not an array; it points to a series of pointers to int. For all practical purposes, you can use this as though it were a 2D array:
int **arr = foo( rows, cols );
...
arr[i][j] = ...;
printf( "value = %d\n", arr[k][l] );
Note that C doesn't have any garbage collection; you're responsible for cleaning up your own messes. In the first three cases, it's simple:
int (*arr1)[N] = func(rows);
// use arr[i][j];
...
free( arr1 );
int (*arr2)[cols];
func2( rows, cols, &arr2 );
...
free( arr2 );
int (*arr3)[N];
func3( rows, &arr3 );
...
free( arr3 );
In the last case, since you did a two-step allocation, you need to do a two-step deallocation:
int **arr4 = func4( rows, cols );
...
for (i = 0; i < rows; i++ )
free( arr4[i] )
free( arr4)
Your function return void, so the return x; line is superfluous. Aside from that, your code looks fine. That is, assuming you have #define n 3 someplace and not something like const int n = 3;.
You can't return an array in C, multidimensional or otherwise.
The main reason for this is that the language says you can't. Another reason would be that generally local arrays are allocated on the stack, and consequently deallocated when the function returns, so it wouldn't make sense to return them.
Passing a pointer to the array in and modifying it is generally the way to go.
To return (a pointer to) a newly-created array of dimensions known at compile time, you can do this:
#define n 10 // Or other size.
int (*new_array(void))[n]
{
int (*x)[n] = malloc(n * sizeof *x);
if (!result)
HandleErrorHere;
for (int i = 0; i < n; ++i)
for (int o = 0; i < n; ++o)
x[i][o] = InitialValues;
return x;
}
…
// In the calling function:
int (*x)[n] = new_array();
…
// When done with the array:
free(x);
If the size is not known at compile time, you cannot even return a pointer to an array. C does support variable-length arrays but not in the return types of functions. You could instead return a pointer to a variable-length array through a parameter. That requires using a parameter that is a pointer to a pointer to an array of variable length, so it gets somewhat messy.
Also, the preferred choices between allocating an array in the caller dynamically, allocating an array in the caller automatically, allocating an array in the called function dynamically and using variable-lengths arrays or fixed-length arrays or even one-dimensional arrays with manual indexing depend on context, including what how large the array might be, how long it will live, and what operations you intend to use it for. So you would need to provide additional guidance before a specific recommendation could be made.
In C there's only pass/return by value (no pass by reference). Thus the only way of passing the array (by value) is to pass its address to the function, so that it can manipulate it through a pointer.
However, returning by value an array's address isn't possible, since by the time control reaches the caller, the function goes out of scope and its automatic variables go down with it too. Hence if you really have to, you can dynamically allocate the array, populate and return it, but the preferred method is passing the array and leaving the onus of maintaining the array to the caller.
As for the error, the only warning I get in GCC for this is warning: 'return' with a value, in function returning void which is simply meaning that you shouldn't return anything from a void function.
void new_array (int x[n][n]); what you're really doing here is taking a pointer to an array of n integers; the decayed type is int (*x)[n]. This happens because arrays decay into pointers generally. If you know n at compile time, perhaps the best way to pass is:
#define n 3
void new_array (int (*x)[n][n]) {
int i,o;
for (i=0; i<n; i++) {
for (o=0; o<n; o++) {
x[i][o]=(rand() % n)-n/2;
}
}
}
And call it as
int arr[n][n];
new_array(&arr);
You can pass around arbitrarily dimensions arrays like any another variable if you wrap them up in a struct:
#include <stdio.h>
#define n 3
struct S {
int a[n][n];
};
static struct S make_s(void)
{
struct S s;
int i, j;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++)
s.a[i][j] = i + j;
}
return s;
}
static void print_s(struct S s)
{
int i, j;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++)
printf(" %d", s.a[i][j]);
printf("\n");
}
}
int main(void) {
struct S s;
s = make_s();
print_s(s);
return 0;
}
You are probably declaring n as a constant integer:
const int n = 3;
Instead, you should define n as a preprocessor definition:
#define n 3

Resources