Changing size of 2d array on iteration - c

Im new to C coding. In order to learn the language i want to do following little "program".
I want to scan inputs , and put them into 2d array - but i do now know how many elements i want to scan / input = i want to dynamicly create 2d array. And here is the problem. I know how i can dynamicly create 1d array e.g
int MAX;
int *arr;
scanf("%d",&MAX);
arr=(int*)malloc( Max * sizeof ( int ) )
i found how to allocate 2d array e.g
int X;
int Y;
int **arr;
scanf("%d%d",&X,&Y);
arr=(int*) malloc ( X * Y * sizeof ( int* ) )
But i havent found the thing i need the most = create 2d array and increase its " memory or size " every time new item is being added.
For example - what i would like to achieve.
int **arr;
int index=1;
int X;
int Y;
arr=(int *) malloc ( index * sizeof ( int ) );
while (! feof ){
scanf("%d%d",&X,&Y);
if ( index > 1 ){
index ++;
arr=realoc( arr*, index * sizeof ( arr* ) )
arr[iX][0]=X;
arr[iX][1]=Y;
} else{
arr[iX][0]=X;
arr[iX][1]=Y;
index++;
}
}
this was my attempt and i failed horribly.. how can dynamicly change size of 2d array on every input (or every iteration of loop )
i am aware of this solution but all answer are used with predefined y-osis of array. e.g arr[][25]

First you need a field of pointers, each pointer in the field of pointers points to the first element of a row/column of your matrix. Each time you want to add a value to your row/column you have to increase your row/column with realloc. Each time you want to add a new row/column you have to add one pointer to your field of pointers. Thus you need two conditions of truncation, one for the row/column and one for the field of pointers.
The following code shows an example how that can be realized. However be aware that the program may terminate due to allocation errors.
#include <stdio.h>
#include <stdlib.h>
main(){
//numberofrows points to the pointers used for the columns countrows tells us how many pointers we have
char **numberofrows;
int countrows=0;
//countcolumns tells us how much memory has to be allocated for the current column
int countcolumns=0;
numberofrows=malloc(sizeof(char*));
//t is needed for the first run of the loop otherwise the program will likely terminate
int t=0;
//truncation condition: e signals the end of the usersinput
while(t==0||numberofrows[countrows-1][countcolumns-1]!='e'){
countcolumns=0;
countrows++;
t=0;
//allocation of new array and reallocation of pointer array
numberofrows[countrows-1]=malloc(sizeof(char));
*numberofrows=realloc(*numberofrows,sizeof(char*)* countrows);
//truncation condition \n: end of current column, condition e: end of input for 2d array
while(t==0||(numberofrows[countrows-1][countcolumns-1]!='\n'&&numberofrows[countrows-1][countcolumns-1]!='e')){
countcolumns++;
//change for t to activate truncation conditions
t=1;
// info for what postion new value is needed realloc to make place for additional value and setting of new value
printf("row: %d, column: %d\n",countrows,countcolumns);
numberofrows[countrows-1]=realloc(numberofrows[countrows-1],sizeof(char)*countcolumns);
numberofrows[countrows-1][countcolumns-1]=getchar();
//clears input buffer
if(numberofrows[countrows-1][countcolumns-1]!='\n')
while(getchar()!='\n'){}
}
}
//prints transposed 2d array
int tc=0,k=0;
while(tc<countrows){
k=0;
while(numberofrows[tc][k]!='\n'&& numberofrows[tc][k]!='e'){
printf("%c ",numberofrows[tc][k]);
k++;
}
printf("\n");
tc++;
}
}

Related

Infinite array index without any pointer in C

I want to get a variable from user and set it for my array size. But in C I cannot use variable for array size. Also I cannot use pointers and * signs for my project because i'm learning C and my teacher said it's forbidden.
Can someone tell me a way to take array size from user?
At last, I want to do this two projects:
1- Take n from user and get int numbers from user then reverse print entries.
2- Take n from user and get float numbers from user and calculate average.
The lone way is using array with variable size.
<3
EDIT (ANSWER THIS):
Let me tell full of story.
First Question of my teacher is:
Get entries (int) from user until user entered '-1', then type entry numbers from last to first. ( Teacher asked me to solve this project with recursive functions and with NO any array )
Second Question is:
Get n entries (float) from user and calculate their average. ( For this I must use arrays and functions or simple codes with NO any pointer )
Modern C has variable size arrays, as follows:
void example(int size)
{
int myArray[size];
//...
}
The size shouldn't be too large because the aray is allocated on the stack. If it is too large, the stack will overflow. Also, this aray only exists in the function (here: funtion example) and you cannot return it to a caller.
I think your task is to come up with a solution that does not use arrays.
For task 2 that is pretty simple. Just accumulate the input and divide by the number of inputs before printing. Like:
#include <stdio.h>
#include <stdlib.h>
int main()
{
float result = 0;
float f;
int n = 0;
printf("How many numbers?\n");
if (scanf("%d", &n) != 1) exit(1);
for (int i=0; i < n; ++i)
{
if (scanf("%f", &f) != 1) exit(1);
result += f;
}
result /= n;
printf("average is %f\n", result);
return 0;
}
The first task is a bit more complicated but can be solved using recursion. Here is an algorithm in pseudo code.
void foo(int n) // where n is the number of inputs remaining
{
if (n == 0) return; // no input remaining so just return
int input = getInput; // get next user input
foo(n - 1); // call recursive
print input; // print the input received above
}
and call it like
foo(5); // To get 5 inputs and print them in reverse order
I'll leave for OP to turn this pseudo code into real code.
You can actually use variable sized arrays. They are allowed when compiling with -std=c99
Otherwise, you can over-allocate the array with an arbitrary size (like an upper bound of your actual size) then use it the actual n provided by the user.
I don't know if this helps you, if not please provide more info and possibly what you have already achieved.

C array elements change value

I define three arrays. Once the first one is allocated, I print out its first element which is as expected. Then, a second array ('problematic') is allocated. When I reprint the first array's first element, it has magically changed to the value I allocated the array 'problematic' with. It gets even weirder. Had I chosen not to allocate the array 'problematic' but 'working' between the two print statements, everything works fine.
What's going on?
#include<stdio.h>
int problem(double variable);
int main(){
problem(1.0);
return 0;
}
int problem(double variable){
int limit1 = 10;
int limit2 = 10;
double bin_bounds[limit1];
double problematic[limit2];
double working[limit2];
// Allocate first array
for (int bin=0; bin<limit1; bin++){
bin_bounds[bin] = variable/limit1 * (bin+1);
}
printf("%f\n\n",bin_bounds[0]); // prints 0.2 as excpected
for (int el=0;el<=limit2;el++){problematic[el]=2.;}
printf("%f\n\n",bin_bounds[0]); // prints 2.0
return 0;
}
It's array out of bound, you are allocating 10 elements with index 0 to 9 but you're accessing index 10. Your loop should only be
for (int el=0;el<limit2;el++){problematic[el]=2.;}
The big_bounds is probably allocated right after the problematic in this case. So problematic[10] is at the same memory address as big_bounds[0]
Run with valgrind and check whether you are accesing invalid memory.During declaring array init it with 0.

dynamically storing prime numbers in a 1d array

I am making a program which stores prime numbers in a given range into an 1-d array dynamically. I have read about dynamic memory allocation in c,but i don't know what's wrong with my code.
Initially I define an "isprime" function which checks whether a number is prime or not and if the number is prime it returns 1.
After that I use a for loop which helps in storing of prime numbers in an array.
In the for loop I use an if statement which checks whether the number in the range input by the user is prime or not,and if it is prime it is stored in an array p for which memory is allocated dynamically using malloc.
But in the array p no prime numbers are stored and instead garbage values are stored,I don't know why prime numbers are not getting stored in my array?
#include<stdio.h>
#include<math.h>
int isprime(int n)
{
int i;
for(i=2;i<sqrt(n);i++)
{
if(n%i==0)
{
return 0;
}
}
return 1;
}
main()
{
int *p,i,n,j=1;
scanf("%d",&n);
for(i=0;i<n;i++)
{
if(isprime(i)&&i!=0&&i!=1)
{
p=malloc(j*sizeof(int));//Memory allocation for p should increase as more prime no.s are stored
p[j-1]=i;
j++;
}
}
printf("%d\n",p[1]);//garbage value is printed instead of any prime no.
}
malloc will return a new memory region each time in your loop, losing your previous data.
You need realloc instead
int *p = NULL; // initialize to NULL
and in the loop:
p=realloc(p,j*sizeof(int));
so either p address is kept and memory increased, either previous data from p is copied and a new p is issued. Either way it's transparent for you.
(First time, as p is NULL, it acts like malloc)
Note that it's rather inefficient to realloc at each iteration. It would be better to resize less often, and keep record of capacity and actual data length. For instance like this:
Init:
int growth = 100;
int capacity = 0;
int *p = NULL;
and in the loop:
if (j>=capacity)
{
capacity += growth;
p = realloc(p,capacity*sizeof(int));
}
Aside: as comments noted, for the answer to full work, don't omit last value when checking for primes or you'll detect perfect squares as primes.

Adding an element to an array in C without a loop

This is my first time asking so please be gentle lol.
So I am trying to better understand arrays in C. Is there a way I can add an element to an array without using a for loop? The problem is I want to add a new element to the end of the array, but without knowing the size of the array.
So I already have this:
#include <stdlib.h> //not sure if needed but put it just in case
int main(void):
float real[20];
real[]={1,2,3,4,5};
I want to add the number 6 to the array, but I don't want to use real[5]=6. Is there another way to add an element to the end of the array without a loop checking if each element in the array until the element is null? Thanks for your help in advance!
C arrays don't know about their length. If you need arrays that can grow and shrink, you have to keep extra information on how long your active array is. An array that is created on the stack like so:
real array[20] = {1, 2, 3};
will contain twenty elements, the first three initialised with concrete values, the rest initialised to zero. If you want to consider this array as an array of initially three values that can hold up to 20 values, you have to keep the actual array length as an extra variable:
real array[20] = {1, 2, 3};
int narray = 3;
You can then append a value. Take care not to overflow that maximum storage of 20 elements:
if (narray < 20) array[narray++] = 9;
You can read the last value and remove it from the array:
if (narray) printf("%g\n", array[--narry]);
Here, you have to take care not to underflow the array. (Also, don't decrement narray more than once in the same expression, which will lead to undefined behaviour.)
If you write a function that operates on the array, pass both array and length:
void array_print(float array[], int n)
{
int i;
for (i = 0; i < n; i++) {
if (i) printf(", ");
printf("%g", array[i]);
}
printf("\n");
}
and call it like so:
array_print(array, narray);
Another approach is to keep a sentinel value like 0.0. This can be useful in some cases, but it has the disadvantage that you have to traverse the whole array to find out the length. It also removes the sentinel from the range of valid values that your array can hold.
The advantage here is, of course, that the array is "self-contained", i.e. you don't have to pass array and length to a function; just the array is enough. When appending you still have to take care not to overflow the maximum storage, which makes this approach cumbersome.
The only way is to keep a pointer to the next free position in the array. For example
#include <stdio.h>
float * copy( const float *src, size_t n, float *dst )
{
while ( n-- ) *dst++ = *src++;
return dst;
}
int main(void)
{
float real[20];
float *p = real;
p = copy( ( float [] ){ 1, 2, 3, 4, 5 }, 5, p );
p = copy( ( float [] ){ 6, 7 }, 2, p );
for ( float *q = real; q != p; ++q ) printf( "%1.1f ", *q );
printf( "\n" );
return 0;
}
The output is
1.0 2.0 3.0 4.0 5.0 6.0 7.0
You always can check whether p points within the array using condition
p < real + 20
The other approach is to use a structure that contains an array. For example
struct Array
{
enum { N = 20 };
float real[N];
size_t n; /* current number of filled elements */
};
With a little help of the preprocessor, you can use a compound literal to get the size:
int main(void)
{
#define REAL_VALUES 1, 2, 3, 4, 5
float real[20] = {REAL_VALUES};
real[sizeof((float[]){REAL_VALUES}) / sizeof(float)] = 6;
return 0;
}
In C you can get the length of an array with the expression sizeof (array) / sizeof (array)[0], or even better, by defining a macro:
#define LEN(array) \
((int) (sizeof (array) / sizeof (array)[0]))
What you describe is not adding an element to the end of the array but rather adding an element after the last element inserted. For that you need a variable that keeps track of the element count:
int count = 0;
float x;
...
if (count < LEN(real)) {
real[count] = x;
count++;
}
Observe, however, that once you have passed the array to a function its length is gone, so you need to pass the array length to the function as well:
void foo(float a[], int len);
...
foo(real, LEN(real));
You can use memset() to make space for your element in your array and then insert your element at specific position.
Here is sample code below.
/*Make space for number to insert.*/
memmove(&arr[pos+1],&arr[pos],(ARR_SIZE+1-pos)*sizeof(int));
arr[pos] = num;/*insert the number.*/
Full code snipet could be found here InsertElement

How to correctly compare and print out matching elements in this array in C?

I have this simple problem to which I am trying to write a solution, in C.
If an array arr contains n elements, then write a program to check
if arr[0] = arr[n-1], arr[1] = arr[n-2] and so on.
And my code looks like this-
#include<stdio.h>
int main()
{
int arr[10],i=0,j;
int k=0;
printf("\n Enter 10 positive integers: \n");
for(k=0;k<=9;k++)
scanf("%d",&arr[k]);
while(i<=9)
{
for(j=9;j>=0;j--)
{
if(arr[i]==arr[j])
{
printf("\n The array element %d is equal to array element %d\n", arr[i],arr[j]);
}
i++;
continue;
}
}
return 0;
}
On entering this input-
Enter 10 positive integers:
10
20
30
40
50
60
40
80
20
90
The output I get is-
The array element 20 is equal to array element 20
The array element 40 is equal to array element 40
The array element 40 is equal to array element 40
The array element 20 is equal to array element 20
Now, there are two problems with this code-
As you can see, the program prints out matching array elements twice. This is because, the way I've structured the program, once the variable i loops through the array from the first to last element, and then j loops through from the last to first element. So each prints out the matching array element once, leading to two sets of values.
My second question is- In my code, I've hard-coded the length of the array in the for loops(0 to 9 for an array of 10 elements). What change can be done so that the length of the array, as entered by the user, can directly be used in the for loops?
I've read that, in C, array dimensions(when declaring) cannot be a variable. So, a declaration like this(which was my first thought) wouldn't work-
int n; // n is no. of elements entered by the user
int arr[n];
I'm a newbie to programming, so my apologies if the question sounds/is too simple, low-quality.
Thank You.
1)You can traverse the array for half times for getting the prints only once. Instead of for(j=9;j>=0;j--) you can use for(j=9;j>=9/2;j--).
2)
int n;
int arr[n].
Recent Compilers support this statement. If you don't like to use this, you can go for dynamic memory allocation for the array.
My second question is- In my code, I've hard-coded the length of the array in the for loops(0 to 9 for an array of 10 elements). What change can be done so that the length of the array, as entered by the user, can directly be used in the for loops?
Use dynamic memory allocation. Use malloc().
So code will be
{
int num_elements;
int* arr;
printf("Enter number of elements\n");
scanf("%d", &num_elements);
arr = (int *) malloc(num_elements * sizeof(int)); // Use this 'arr' for holding input data from user
// Your remaining code comes here
free(arr); // Free the pointer in the end of program
}
the variable length creation works for me:
#include<stdio.h>
int main(){
int a, i;
scanf("%i", &a);
int blah[a];
for (i = 0; i < a; i++){
printf("/n%i", blah[a]);
}
}
The other way would be to create the maximum length array and than simply use first n elements.
As the previous answer states it is up to you to make sure you are checking each element only once therefore stopping at the element n/2. It is probably important that n/2 is rounded to the closest smaller integer, so at first glance odd numbers of arguments may be differently handled. But as it is omitting only the middle element it is identical to itself.
For your first query
for(i=0;i<n/2;i++)
{
if(a[i]==a[n-(i+1)])
{
printf("\n The array element %d is equal to array element %d\n",a[i],a[n-(i+1)]);
}
}
For your second query you can use condition i<(n/2) (which runs the loop (n/2)-1 times) For your case where n = 10 it will run from 0 to 4.
If you want to loop from 0 to 9 you can use
for(i=0;i<n;i++)
For making array of n elements where n is a variable either make an array of elements that is always greater than n or do it by making a dynamic array.
http://www.cs.swarthmore.edu/~newhall/unixhelp/C_arrays.html
corrected:
#include<stdio.h>
int main()
{
int i=0, size; // size of array
int k=0; // counter
printf("enter size of array\n");
scanf("%d", &size); // ask user for desired size
int *arr = malloc(size * sizeof(int)); // allocate memory for array
printf("\n Enter 10 positive integers: \n"); // fill your array of size size
for(k=0;k<size;k++)
scanf("%d",&arr[k]);
k = 0; // reset this counter
for(i=0; i<size/2; i++) // check only for half of it
{
if(arr[i] == arr[size-i-1]) // try it with paper and pincil
{
printf("match arr[%d]=arr[%d]=%d\n", i,size-i-1, arr[i]);
k++;
}
}
if(k==0) printf("No matching");
return 0;
}

Resources