Passing a multidimensional array of variable size - c

I'm trying to understand what "best practice" (or really any practice) is for passing a multidimensional array to a function in c is. Certainly this depends on the application, so lets consider writing a function to print a 2D array of variable size. In particular, I'm interested in how one would write the function printArry(__, int a, int b) in the following code. I have omitted the first parameter as I'm not exactly sure what that should be.
void printArry(_____, int a, int b){
/* what goes here? */
}
int main(int argc, char** argv){
int a1=5;
int b1=6;
int a2=7;
int a2=8;
int arry1[a1][b1];
int arry2[a2][b2];
/* set values in arrays */
printArry(arry1, a1, b1);
printArry(arry2, a2, b2);
}

The easiest way is (for C99 and later)
void printArry(int a, int b, int arr[a][b]){
/* what goes here? */
}
But, there are other ways around
void printArry(int a, int b, int arr[][b]){
/* what goes here? */
}
or
void printArry(int a, int b, int (*arr)[b]){
/* what goes here? */
}
Compiler will adjust the first two to the third syntax. So, semantically all three are identical.
And a little bit confusing which will work only as function prototype:
void printArry(int a, int b, int arr[*][*]);

This is not really an answer, but extended comment to the OP's comment question, "well you can pass the array without knowing the number of rows with this, but then how will you know when to stop printing rows?"
Answer: generally, you can't, without passing the array size too. Look at this 1-D example, which breaks the array size.
#include <stdio.h>
int procarr(int array[16], int index)
{
return array[index];
}
int main (void)
{
int arr[16] = {0};
printf("%d\n", procarr(arr, 100));
return 0;
}
Program output (although all elements initialised to 0):
768
That was undefined behaviour and there was no compiler warning. C does not provide any array overrun protection, except for array definition initialisers (although such initialisers can define the array length). You have to pass the array size too, as in
#include <stdio.h>
int procarr(int array[16], size_t index, size_t size)
{
if (index < size)
return array[index];
return -1; // or other action / flag
}
int main (void)
{
int arr[16] = {0};
printf("%d\n", procarr(arr, 100, sizeof arr / sizeof arr[0]));
return 0;
}
Program output:
-1

Related

How to pass the user value for the size of an array into a function implemented in another code file?

I have no idea what to do. Whenever I try to insert read_num[size] it does not work. My debugger shows the value as 0. I want to take a value for the size of the array from the user. Then I want to use the value in another file.
So what I want to do is, I will do a printf to ask the user to give a value so that I can pass it as the size of the array. I did and it didn't work. Then I decided to write a direct value [36]. But I want user to insert 36.
This is what I have tried:
main.c
int main(void)
{
int numbers[ARR_SIZE] = { 0 };
int size = 36; // I am doing directly but I want to take the value from the user but it just does not work.
double mean = 0;
double stddev = 0;
read_array(size);
}
file.c
int read_array(int a[36]) //placing 36 directly, I want it to be placed by the user
{
int num_read[36]; int i = 0; // I have no clue whats i am doing. I just want to pass the value from the user.
while (i < a)
{
printf("Enter number");
scanf_s("%d", &num_read[i]);
++i;
}
}
header file
#include <stdio.h>
#include <math.h>
#define ARR_SIZE 100
int read_array(int arr[ARR_SIZE]);
double calc_mean(int arr[], int size);
double calc_stddev(int arr[], int size);
void print_array(int arr[], int size);
In you main.c file you want to decide the value of size and use that value in a call to the function read_array().
You do so by calling read_array(size);, which makes sense to me.
Sadly your shown code lacks the details of whether or not you include your header file (and others). I assume that it does.
However, if what you are doing inside main() is actually what you want to do (I assume so), then the header file and the implementation of read_array() does not match that intention.
This int read_array(int arr[ARR_SIZE]), in your header and your implementation, means
"Dear compiler, this function takes an array (or a pointer to 100 consecutive ints)."
That does not match your plan of "I will give a single int as the parameter to the function."
To match that plan, use a prototype of int read_array(int a);.
The implementation code as shown should then work.
If you want the local array to actually be of the size given by the user and arriving via the parameter a, then change
int num_read[36]; to int num_read[a];.
However, I suspect that you then intend to return the array which you filled with input from the user.
That is neither possible with a prototype of int read_array(int a); nor with one of int read_array(int arr[ARR_SIZE]);. Both mean "This function will return a single int.".
I assume you will need help with that, but you need to ask a separate question on how to return a new array from a C function - or better first search StackOverflow for a duplicate.
To pass the size of the array to the function (it does not matter if it is defined in the same or another compilation units) you need to have an additional parameter to the function. There is no other way of doing it in C language
int *doSomethingWithArray(int *array, size_t size)
{
/* ... */
}
But I want user to insert 36.
The user can only enter something using I/O functions and has no access to the C code.
int *initArray(int *array, const size_t size)
{
for(size_t index = 0; index < size; index ++)
array[index] = rand();
return array;
}
int *printArray(int *array, const size_t size)
{
for(size_t index = 0; index < size; index ++)
printf("array[%3zu] = %d\n", index, array[index]);
return array;
}
int main(void)
{
size_t array_size;
srand(time(NULL));
if(scanf("%zu", &array_size) == 1) // user enters the size of the array
{
int array[array_size];
initArray(array, array_size);
printArray(array, array_size);
}
}
https://godbolt.org/z/xjh9qGcrz

Pass a 2D char array to a function in C

I'm a beginning programmer who is confused with passing a two dimensional array to a function. I think it may just be a simple syntax problem. I've looked for an answer, but nothing I've found seems to help, or is too far above my level for me to understand.
I identify the array and the function in the main function as, and after initializing it, attempt to call it:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int const ROWS = 8;
int const COLS = 8;
int main(int argc, char** argv) {
char board[ROWS][COLS];
bool canReach(char board[][], int i, int j);
//initialize array
//values of i and j given in a for loop
canReach(board, i, j);
return (EXIT_SUCCESS);
}
While writing the function outside the main function, I defined it exactly the same as I did in the main function.
bool canReach(char board[][], int i, int j){
//Functions purpose
}
When I attempt to build the program, I'm given this error twice and the program does not build:
error: array has incomplete element type 'char[][]'
bool canReach(char board[][], int i, int j)
^
Please note that I'm trying to pass the entire array to the function, and not just a single value. What can I do to fix this problem? I would appreciate it if it didn't have to use pointers, as I find them quite confusing. Also, I've tried to leave out things that I thought weren't important, but I may have missed something I needed, or kept in things I didn't. Thank you for your time in helping out this starting programmer!
You can just pass arrays as function arguments with definition of their size.
bool canReach(char board[ROWS][COLS], int i, int j);
When the size is unknown, pointers are the way.
bool canReach(char* board, int i, int j);
You should know, that arrays != pointers but pointers can storage the address of an array.
Here is a demonstrative program
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
bool canReach( int n, int m, char board[][m] )
{
for ( int i = 0; i < n; i++ )
{
for ( int j = 0; j < m; j++ )
{
board[i][j] = 0;
}
}
return printf( "Hello SaarthakSaxena" );
}
int main( void )
{
const int ROWS = 8;
const int COLS = 8;
char board[ROWS][COLS];
canReach( ROWS, COLS, board );
return EXIT_SUCCESS;
}
Its output is
Hello SaarthakSaxena
Defining a function inside another function (here: main) is not allowed in C. That is an extension of some compilers (e.g. gcc), but should not be used.
You have to specify the dimension of the array. C arrays do not have implicit size information as in HLL.
It also is not a good idea to use const variables for array dimensions in C. Instead
#define ROWS 8
#define COLS 8
Assuming i and j are the indexes of an element in the array, you can use the signature:
bool canReach(size_t rows, size_t cols, char board[rows][cols],
size_t i, size_t j);
This allows to pass arrays of (run-time) variable size to the function. If the dimensions are guaranteed fixed at run-time:
bool canReach(char board[ROWS][COLS], size_t i, size_t j);
But only if using the macros above. It does not work with the const variables.
Both versions tell the compiler which dimension the array has, so it can calculate the address of each element. The first dimension might be omitted, but there is nothing gained and it would imhibit optional bounds checking (C11 option). Note the 1D-case char ca[] is just a special version of this general requirement you can always omit the left(/outer)most dimension.
Note I changed the types to the (unsigned) size_t as that is the appropriate type for array-indexing and will generate a conversion warning if properly enabled (strongly recommended). However, you can use int, but have to ensure no value becomes negative.
Hint: If you intend to store non-character integers in the array or do arithmetic on the elements, you should specify the signed-ness of the char types. char as such can be either unsigned or signed, depending on implementation. So use unsigned char or signed char, depending what you want.

Segmentation fault (core dumped) in the following code. What's wrong?

I am relatively new to C. I have encountered quite a few segmentation faults but I was able to find the error within a few minutes. However this one's got me confused. Here's a new function I was trying to write. This basically is the C equivalent of the python code
r=t[M:N]
Here's my C code with a test case
#include <stdio.h>
char* subarraym(char* a, int M, int N)
{
char* s;
int i;
for (i=M; i<N; i++){ s[i-M]=a[i]; }
return s;
}
main()
{
char* t="Aldehydes and Ketones";
char* r=subarraym(t,2,10);
printf("%c\n",r[4]);
return 0;
}
The expected answer was 'd'. However I got a segmentation fault.
Extra Info: I was using GCC
Your code will not work because your sub-array pointer is never initialized. You could copy the sub-array, but then you will have to manage the memory, and that's overkilling for your problem.
In C, arrays are usually passed around as pairs of pointer and number of elements. For example:
void do_something(char *p, int np);
If you follow this idiom, then getting a sub-array is trivial, assuming no overflow:
void do_something_sub(char *p, int np, int m, int n)
{
do_array(p + m, n);
}
Checking and managing overflow is also easy, but it is left as an exercise to the reader.
Note 1: Generally, you will not write a function such as do_something_sub(), just call do_something() directly with the proper arguments.
Note 2: Some people prefer to use size_t instead of int for array sizes. size_t is an unsigned type, so you will never have negative values.
Note 3: In C, strings are just like char arrays, but the length is determined by ending them with a NUL char, instead of passing around the length. So to get a NUL-terminated substring, you have to either copy the substring to another char array or modify the original string and overwrite the next-to-last char with the NUL.
From
...,10);
you expect to receive 10 char (+1 0-terminator), so provide it to the function somehow.
Not doing so, but writing to invalid memory by
char * s; /* note, that s is NOT initialised, so it points "nowhere". */
...
s[i-M] = ...
provokes undefined behaviour.
Possible solution to provide memory for such a case can be found in this answer: https://stackoverflow.com/a/25230722/694576
You need to secure the necessary memory.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* subarraym(char *a, int M, int N){
if(N < 0){
N += strlen(a);
if(N < 0)
N = 0;
}
int len = N - M;
char *s =calloc(len+1, sizeof(char));//memory allocate for substring
return memcpy(s, &a[M], len);
}
int main(){
char *t="Aldehydes and Ketones";
char *r=subarraym(t,2,10);
printf("%c\n",r[4]);
free(r);
return 0;
}

How pass(to function) by value variable size array?

First of all I know that array A degrades to pointer when we call function f(int a[]) and f(int *p) is same.
BUT:
1.I really need sending by value all array.
2.I really need that sending size is non const in function (but const size in plase we calling function)
I write some example:
http://ideone.com/ZbW0wT
#include <stdio.h>
#define SZ 15
typedef struct {int a[SZ];} rec;
int main(){
void pa(rec);
int value[SZ] ={9,8,7,6,5,4,3,2,1,0};
pa(*(rec*)value);
printf("%u %u\n",sizeof(rec),sizeof(value));
return 0;
}
void
pa(rec b){
int z;
for(z=0;z<SZ;z++){
printf("array[%2d] is %d\n",z,b.a[z]);
}
}
This code work for const size , but how change so pa would get by value some rec which size depend on passed array?
Update: it must by value sended , but not const sized as in Pascal etc , but in true C way , all pass by value not by pointer on 0 element
and function need universal so user can write func(variablesizeArrayOfT) where arg passed by value.
if possible need standard way (C11 or better C99 or better C89 or better K&R), if cant then gcc
UPD2: http://ideone.com/H4XGqC
#include
typedef struct{
int len;
int a[];
} av;
void f(av a){
while(a.len--){
printf("array[%2d] is %d\n",a.len,a.a[a.len]);
}
}
int main(){
int b[]={3,1,2,3};
int c[]={7,1,2,3,4,5,6,7};
f(*(av*)b);
f(*(av*)c);
return 0;
}
all good by probably bug in alignment so size(3 and 7) is right but value of a[] is not
UPD3 see throw gcc -g -c 2ndSRC.c &&objdump -d -M intel -S 2ndSRC.o
it just send only size (b[0] and c[0]) but not all array
An idiomatic way to have arrays containing data of variable length in C is to use a buffer with a maximum size which is known at compile time, is that what you wanted?
#include <stdio.h>
#define MAX_SIZE 15
typedef struct {
int arr[MAX_SIZE];
size_t arr_len;
} rec_t;
void pa(rec_t rec){
for(int z=0; z<rec.arr_len; z++){
printf("array[%2d] is %d\n", z, rec.arr[z]);
}
}
int main(void){
rec_t rec ={
.arr = {9,8,7,6,5,4,3,2,1,0},
.arr_len = 10
};
pa(rec);
}

c standard library sort function from programming pearls

#include <algorithm>
#include <stdio.h>
#include <iostream>
int intcomp(int *x,int *y) { return *x-*y;};
int a[10000];
int main(void){
int i; int n=0;
while (scanf("%d",&a[n])!=EOF)
n++;
qsort(a,n,sizeof(int),intcomp);
for (int i=0;i<n;i++)
printf("%d\n",a[i]);
return 0;
}
it is just copy of code i have two question it show me that intcomp is incompatible in this code
and also what does intcomp function?
and also what is in windows 7 EOF? how tell program that it reached EOF?
the qsort() function requires a pointer with a particular signature.
Your function has the wrong signature so it is complaining.
Your function has the signature:
int intcomp(int *x,int *y)
While qsort requires the signature:
int intcomp(void const* xp,void const* yp)
Please note the difference in the parameter types.
A corrected version of the function is:
int intcomp(void const* xp,void const* yp)
{
// Modified for C as the tag on the question changed:
// int x = *static_cast<int const*>(xp);
// int y = *static_cast<int const*>(yp);
int x = *((int const*)(xp));
int y = *((int const*)(yp));
return x-y;
}
The function qsort() is passed a function pointer as the third parameter.
This function pointer (in your case intcomp()) is used to compare values in the array passed. Each call provides pointers into the array. The result of the function should be:
Less than 0: if x is smaller than y
0: If x is equal to y
Greater than 0: If x is larger than y
First of all: the question is labeled C++ and you #include <algorithm> and <iostream>, but your code is 100% C.
Martin York already gave the answer how to correct the signature of the function you pass to qsort().
However, the "true"(TM) C++ solution would be to use std::sort<> instead of qsort!
#include <algorithm>
#include <stdio.h>
bool intcomp(int a, int b) { return a<b; }
int a[10000];
int main(void){
int n=0;
while (scanf("%d",&a[n])!=EOF)
n++;
std::sort(&a[0], &a[n], intcomp);
for (int i=0;i<n;i++)
printf("%d\n",a[i]);
return 0;
}
Note that incomp() takes ints and not int pointers, and returns a bool. Just like operator<() would.
Also note that in this case, you could forget the intcomp and just use std::sort(&a[0], &a[n]), which will use std::less<>, which will use operator<(int, int).
intcomp is an "Int Compare" function. It is passed a pointer to 2 ints and returns 0 if they are the same, a positive value is x > y and a negative value is x < y.
qsort is passed a pointer to this function and calls it each time it wants to know how to sort a pair of values.
The docs for qsort should give you some more details.
eg http://www.cppreference.com/wiki/c/other/qsort
qsort is in stdlib.h, so include that file at the beginning. Note that algorithm and iostream aren't needed.
#include <stdlib.h>
As Martin York mentioned, qsort needs a function which it will use to compare the values:
void qsort( void *buf, size_t num, size_t size, int (*compare)(const void*, const void *) );
Here is a good example on how to use qsort: http://www.cppreference.com/wiki/c/other/qsort
Edit: Ri was faster....

Resources