How to declare two dimensional arrays using pointers? - c

Hello there I am having trouble declaring two dimensional arrays using pointers. I am new to C.
int main(){
int x = 0;
int y = 0;
int *xdim;
int *ydim;
printf("Enter x:\n");
scanf("%d", &x);
printf("Enter y:\n");
scanf("%d", &y);
xdim = &x;
ydim = &y;
char sq[xdim][ydim];
return 0;
}
I want the two dimentionial array char sq to hold the values inputed by the user. I get error non-integer type *int. I am also new to pointers.

Using VLAs (which are allowed in C99, or as an extension to many compilers), all you need to do is:
int xdim, ydim;
scanf("%d %d", &xdim, &ydim);
char vla_array[xdim][ydim];
As you can see, there is no need for pointers.
The 2nd option is to use "ordinary" arrays. You need to declare an array with big enough size, and use only a part of it:
#DEFINE X_MAX_DIM 100
#DEFINE Y_MAX_DIM 100
char vla_array[X_MAX_DIM][Y_MAX_DIM];
int xdim, ydim;
scanf("%d %d", &xdim, &ydim);
// check xdim and ydim are acceptable sizes
// from now on you use up to `xdim x ydim` of your array, even if
// it was declared as `100x100`
You can use this only when you know in advance the maximum allowed dimensions of your array.
The 3rd option is to use dynamic allocation. This is the only option if the array is very big. However this is an advanced topic, so you will not deal with this right now.

int** ptr = NULL;
ptr = new int*[val];
for(int i=0; i < val; i++)
{
ptr[i] = new int[val];
}
above code allocates 2d array of val*val

change char sq[xdim][ydim]; to char sq[*xdim][*ydim];, else you pass the location of the value rather than the value itself.
But it is unnecessary to use pointers in this case, you could just use x and y.

In the code you sowed the error occured because in this declaration
char sq[xdim][ydim];
there are used pointers xdim and ydim instead of integers. You could write
char sq[*xdim][*ydim];
Though there is no need to use pointers such a way.
If your compiler supports Variable Length Arrays then you can for example just write
int main( void )
{
size_t m = 0;
size_t n = 0;
printf("Enter x:\n");
scanf("%zu", &m);
printf("Enter y:\n");
scanf("%zu", &n);
if ( !m || !n ) return 1;
char sq[m][n];
//...
return 0;
}
Otherwise you have to allocate arrays dynamically. For example
#include <stdlib.h>
int main( void )
{
size_t m = 0;
size_t n = 0;
printf("Enter x:\n");
scanf("%zu", &m);
printf("Enter y:\n");
scanf("%zu", &n);
if ( !m || !n ) return 1;
char **sq = malloc( m * sizeof( char * ) );
for ( size_t i = 0; i < m; i++ ) sq[i] = malloc( n * sizeof( char ) );
//...
for ( size_t i = 0; i < m; i++ ) free( sq[i] );
free( sq );
return 0;
}

I believe if i understand what you're asking this should work.
Using a single pointer within a 2D array;
#include <stdio.h>
#include <stdlib.h>
int x = 0, y = 0;
char *arr = (char *)malloc(x * y * sizeof(int));

Related

Malloc and Realloc for Int Array [duplicate]

This question already has answers here:
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 3 months ago.
I've just started learning malloc() and realloc() and when testing them, I came across this issue with reallocating the size of an int array.
the program is supposed to make an array, initially of size two, but it's supposed to increase its size and add values to it ten times. However it doesn't increase its size and the output ends up being array = {0,1} when it should be array = {0,1,2,3,4,5,6,7,8,9}
#include <stdlib.h>
#include <stdio.h>
int main(void) {
int *array= malloc(sizeof(int)*2);
for (int x = 0; x < 10; x++) {
array = realloc(array, sizeof(int)*(2+x));
array[x] = x;
}
for (int i = 0; i<(sizeof(array)/sizeof(array[0])); i++) {
printf("%d\n",array[i]);
}
free(array);
}
could someone explain why it doesn't work?? I've tried looking for answers but none of this makes sense to me lol.
The expression
sizeof(array)/sizeof(array[0])
is equivalent to
sizeof( int * )/sizeof( int )
and yields either 2 or 1 depending on the used system.
Also the expression (2+x) in this statement
array = realloc(array, sizeof(int)*(2+x));
used in each iteration of the for loop does not make sense.
It seems you mean something like the following
enum { N = 10 };
size_t n = 2;
int *array = malloc( n * sizeof( int ) );
for ( int x = 0; x < N; x++ ) {
if ( n <= x )
{
n += 2;
array = realloc( array, n * sizeof( int ) );
}
array[x] = x;
}
for ( int i = 0; i < N; i++ ) {
printf("%d\n",array[i]);
}
free(array);
In general it is safer to use an intermediate pointer in the call pf realloc like for example
int *tmp = realloc( array, n * sizeof( int ) );
if ( tmp != NULL ) array = tmp;
Otherwise you can loose the allocated memory if the call of realloc will return a null pointer.
The problem is that sizeof(array) will just return the size of the pointer (8 bytes on a 64-bit system). You need to track the array size in another variable. For example...
#include <stdlib.h>
#include <stdio.h>
int main(void) {
int *array= malloc(sizeof(int));
int size;
for (size = 0; size < 10; size++) {
array = realloc(array, sizeof(int)*(1+size));
array[size] = size;
}
for (int i = 0; i<size; i++) {
printf("%d\n",array[i]);
}
printf("array size: %ld\n",size*sizeof(int));
free(array);
}

Problems in three dimension array in C

I defined the three dimensional array like this, but I it can't read any string in it? Where is the problem? Thanks!
int stuTotal, courseTotal,i,k;//a dynamic array
printf("Input the total number of students that you would like to import:");
scanf("%d", &stuTotal);
printf("Input the total number of courses that you would like to import:");
scanf("%d", &courseTotal);
char ***data = (char***)calloc(stuTotal,sizeof(char));//data
for(i = 0;i < stuTotal;i++){
data[i] = (char**)calloc(courseTotal,sizeof(char));
for (k = 0;k < courseTotal;k++){
data[i][k] = (char*)calloc(20,sizeof(char));
}
}
strcpy(data[0][0],"hello");
data[0][0] is shown to be empty.
Your arguments to sizeof are incorrect when you allocate the outer arrays - instead of
char ***data = (char***)calloc(stuTotal,sizeof(char));
it needs to be
char ***data = (char***)calloc(stuTotal,sizeof(char **)); // you're allocating N elements of type `char **`.
You can greatly simplify that call as follows:
char ***data = calloc( stuTotal, sizeof *data ); // sizeof *data == sizeof (char **)
and similarly
data[i] = calloc( courseTotal, sizeof *data[i] ); // sizeof *data[i] == sizeof (char *)
You should not need to cast the result of malloc and calloc unless you're working in C++ (in which case you should be using new or, better yet, some kind of container type) or an ancient C implementation (pre-1989).
You should be using sizeof(char**) for 3d "data" array as every element of this 3d array is char**.
int stuTotal, courseTotal,i,k;//a dynamic array
printf("Input the total number of students that you would like to import:");
scanf("%d", &stuTotal);
printf("Input the total number of courses that you would like to import:");
scanf("%d", &courseTotal);
char ***data = (char***)calloc(stuTotal,sizeof(char**));//data
for(i = 0;i < stuTotal;i++){
data[i] = (char**)calloc(courseTotal,sizeof(char*));
for (k = 0;k < courseTotal;k++){
data[i][k] = (char*)calloc(20,sizeof(char));
}
}
strcpy(data[0][0],"hello");
You specified invalid sizes of allocated objects.
You have to write
char ***data = (char***)calloc(stuTotal,sizeof(char **));//data
^^^^^^^
for(i = 0;i < stuTotal;i++){
data[i] = (char**)calloc(courseTotal,sizeof(char *));
^^^^^^
for (k = 0;k < courseTotal;k++){
data[i][k] = (char*)calloc(20,sizeof(char));
}
}
If your compiler supports variable length array then you can allocate the required array with calling malloc or calloc only once. For example
char ( *data )[courseTotal][20] =
malloc( sizeof( char[stuTotal][courseTotal][20] ) );
or
char ( *data )[courseTotal][courceName] =
calloc( 1, sizeof( char[stuTotal][courseTotal][courceName] ) );
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
size_t stuTotal = 5, courseTotal = 10, courceName = 20;
char ( *data )[courseTotal][courceName] =
calloc( 1, sizeof( char[stuTotal][courseTotal][courceName] ) );
strcpy(data[0][0],"hello");
puts( data[0][0] );
free( data );
return 0;
}
Its output is
hello
In this case to free all the allocated memory it is needed to call free only once.

Sorting array of strings with qsort

This program takes an integer value which then determines the amount of strings that can be inputted, once the user has entered the amount of strings that they specified they may input another integer and then input those amount of strings. Once done the program sorts the strings based on their lengths in descending order. However the qsort doesn't work, it ends up outputting how the order of when the strings were originally entered.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int sort(const void * a, const void * b){
size_t fa = strlen((const char *)a);
size_t fb = strlen((const char *)b);
return (fa < fb) - (fa > fb);
}
int main(void){
char pointer[100];
int n;
scanf("%d", &n);
char** strings = malloc(n * sizeof(char*));
int i;
for (i = 0; i < n; i++){
scanf("%s", pointer);
strings[i] = malloc(sizeof(char) * (strlen(pointer) + 1));
strcpy(strings[i], pointer);
}
int m;
scanf("%d", &m);
strings = realloc(strings, (n + m) * sizeof(char*));
for (i = n; i < m + n; i++){
scanf("%s", pointer);
strings[i] = malloc(sizeof(char) * (strlen(pointer) + 1));
strcpy(strings[i], pointer);
}
int a;
int g;
int k = m + n;
qsort(strings , a, 100, sort);
for (g = 0; g < k; g++){
printf("%s", strings[g]);
printf("\n");
}
}
You're not calling qsort correctly at all.
The 2nd parameter is the number of elements in the "array" that you are sorting. You're currently passing it a which as others have pointed out isn't set to anything. Compiling your code with the "-Wall" option will show you those kinds of errors.
The 3rd parameter is the size of one of the elements in the "array", but you've confused this with the size of an unrelated variable pointer? You could write it like sizeof(strings[0]).
The finished call should look like qsort(strings,k,sizeof(strings[0]),sort);.
But that still won't work because your sort() function is being passed two pointers to elements in your "array" (char **) and you're treating them as two elements of the "array" (char *). So you'd want something like
size_t fa = strlen(*(char **)a);
Well, this:
int a;
int g;
int k = m + n;
qsort(strings , a, 100, sort);
makes no sense at all, a has no value so this is undefined behavior.
Also sort() is broken, it should just be strcmp().

how to put numbers from interval to array? (C language)

I am looking for this for a while.
Can anyone tell me how can I create interval array?
Example:
interval = < 4;9 >
int array[9-4+1] = {4,5,6,7,8,9}
I would like to insert number from interval to array and than I can work with values in array.
#include <stdio.h>
#include <stdlib.h>
int main ()
{
int size_Of_Interval;
int a;
int b;
printf("Please specify the starting interval value: ");
scanf("%d", &a);
printf("Please specify the ending interval value: ");
scanf("%d", &b);
size_Of_Interval = (b-a+1);
printf("Interval from %d to %d. Interval has %d numbers\n", a, b, size_Of_Interval);
return 0;
}
If your compiler supports variable length arrays (VLAs) then you can just write
int arr[size_Of_Interval];
for ( int i = 0; i < size_Of_Interval; i++ )
{
arr[i] = a + i;
}
Otherwise you should dynamically allocate an array. For example
int *arr = malloc( size_Of_Interval * sizeof( int ) );
for ( int i = 0; i < size_Of_Interval; i++ )
{
arr[i] = a + i;
}
In this case you will need also to free the array when it will not be needed any more
free( arr );
Before to return from the main:
int *array = malloc(size_of_interval * sizeof(int));
This dynamically allocates the needed amount of memory, returning a pointer to the firts element of an array with size_of_interval length. Afterward you can go through a loop and fill that array:
for(int i = 0; i < size_Of_Interval; i++) {
array[i] = a + i;
}
When you end the job with your array, as commented above, you need to free the resource:
free(array);

C program for stddev/mean

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#define MAX 100
void calc(float**, int, float*, float*);
int main( int argc, char* argv[] )
{
float *array[MAX];
float *MEAN;
float *SD;
int array_size, i;
array_size = argc;
for( i = 0; i < argc ; ++i )
{
*array = (float *) malloc( argc*(sizeof(float)));
*array[i] = atof(argv[i]);
}
calc(array, array_size, MEAN, SD);
return 0;
}
void calc(float* arr[] , int arr_size, float* mean, float* stdev)
{
int sum, i;
for ( i = 0; i < arr_size ; ++i )
{
sum += *arr[i];
}
*mean = sum / arr_size;
printf("%.2f", *mean);
for ( i = 0; i < arr_size ; ++i )
{
sum += pow((*arr[i]-*mean), 2);
}
*stdev = sqrt((sum/arr_size));
printf("%.2f", *stdev);
}
The code is supposed to determine the mean and standard deviation of a number of user-inputted floats. I keep getting a segmentation fault when trying to compile it. I tried freeing malloc but it produced more problems for the code, so I just left it as is - although it's probably a problem with memory distribution.
Thank you
There are several problems:
float *array[MAX]; is a pointer to an array of floats. You should
use either an array of floats or a pointer. Since you are using
malloc, you can use a pointer like this: float *array;
Do not call malloc for each float, but call it once for the entire array
If you define MEAN and SD as pointers, you will have to use
malloc on them. It is better to declare them as float only and use
their addresses (via &MEAN and &SD).
You sum variable should be a float, and you should initialize it
to 0. You should also set it to 0 before calculating stdev.
Remember that argv[0] contains the name of your program, so
you should ignore it.
Also remember to call free on anything you allocate with malloc
when you are done with it.
A modified version of your code:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
void calc(float*, int, float*, float*);
int main( int argc, char* argv[] ) {
float *array;
float MEAN;
float SD;
int array_size, i;
array_size = argc-1;
array = (float *) malloc( array_size*sizeof(float));
for( i = 0; i < array_size ; ++i ) {
array[i] = atof(argv[i+1]);
}
calc(array, array_size, &MEAN, &SD);
free (array);
return 0;
}
void calc(float* arr , int arr_size, float* mean, float* stdev) {
float sum=0;
int i;
for ( i = 0; i < arr_size ; ++i ) {
sum += arr[i];
}
*mean = sum / arr_size;
printf("%.2f ", *mean);
sum=0;
for ( i = 0; i < arr_size ; ++i ) {
sum += pow((arr[i]-*mean), 2);
}
*stdev = sqrt((sum/arr_size));
printf("%.2f", *stdev);
}
You are allocating and accessing array wrongly. Should be like this:
for( i = 0; i < argc ; ++i )
{
array = malloc( argc * sizeof(*array));
array[i] = atof(argv[i]);
}
Also inside calc() function change *arr[i] to arr[i] everywhere.
This is definitely wrong :
*array = (float *) malloc( argc*(sizeof(float)));
You are allocating an array of floats after declaring the array. This does not make sense. Then you are dereferencing the values wrongly. In addition, in your code your are trying to transform the name of the program (argv[0]) to an int type.
This may be what you wanted to do :
float * array = NULL;
array = malloc( (argc-1)*(sizeof(float)));
for (i=1; i<argc; ++i)
array[i]=atof(argv[i]);
This code reserves a memory location in the heap of size (argc-1)*float, and initialises it with the values specified as command line parameters. A check should be inserted when argc is 1.
You have several problems,
check that you have at least one argument
you declared array as an array of pointers to float, either use array[], or *array
your array need only be allocated once
allocate an array of number of samples*sizeof(float), once, before loop
store values read into array[ndx] locations (atof is fine)
argv starts at program name, store into array[n] the value converted from argv[n+1]
MEAN and SD need space, you declared pointers, change to value, and pass address (&)
Here is the revised main(),
int main( int argc, char* argv[] )
{
//float array[MAX];
float *array;
float MEAN;
float SD;
int array_size, ndx;
if(!(argc>0)) { printf("please give 1 or more arguments\n"); exit(1); }
array_size = argc-1; //don't count the program name
array = (float*) malloc(array_size*(sizeof(float)));
for( ndx = 1; ndx<argc ; ++ndx )
{
array[ndx-1] = atof(argv[ndx]);
printf("[%d] %f\n",ndx-1,array[ndx-1]);
}
calc(array, array_size, &MEAN, &SD);
free(array); array=NULL; //always clean up after yourself
return 0;
}
Your statistics calculations need work, but this at least compiles and runs,
you need to link against libmath (see below),
your sum was not initialized, before either loop,
pow and sqrt return double - read about C math functions and passing double,
your array_size needs to be set carefully
Here,
void calc(float arr[] , int arr_size, float* _mean, float* _stdev)
{
double sum, mean, stddev;
int i;
sum=0.0;
for ( i = 0; i < arr_size ; ++i )
{
sum += arr[i];
//printf("[%d] %f\n",i,arr[i]);
}
printf("sum %f\n",sum);
*_mean = mean = sum / arr_size;
printf("mean %f\n",mean);
printf("%.2f\n", *_mean);
sum=0.0;
for ( i = 0; i < arr_size ; ++i )
{
sum += pow((arr[i]-mean), 2);
//printf("[%d] %f\n",i,arr[i]);
}
printf("sum^2 %f\n",sum);
*_stdev = stddev = sqrt((sum/arr_size));
printf("stddev %f\n",stddev);
printf("%.2f\n", *_stdev);
}
Oh, you want to link to libmath,
cc stddev.c -lm -o stddev
And when running it,
$ ./stddev 1 2 3 4 5
[0] 1.000000
[1] 2.000000
[2] 3.000000
[3] 4.000000
[4] 5.000000
sum 15.000000
mean 3.000000
3.00
sum^2 10.000000
stddev 1.414214
1.41
Also, you need to free the memory you malloc'ed (array). This is good habit, though not needed for this tiny program.

Resources