Input of integers' array of unknown size - c

I'm trying to create an array of integers of an unknown size.
Every time I input a positive element I use realloc to increase the size of the array and store that element
The thing is that when I run this code, I get a run-time error after 2 iterations of the while of the function create1DArray, so it's probably due to a realloc failure.
Can anybody tell me what I did wrong and how to fix it?
Thanks in advance,
#include <stdio.h>
#include <stdlib.h>
void create1DArray(int** perArray, int* size);
int main()
{
int *perArray, size=0, i;
create1DArray(&perArray, &size );
for(i=0; i<size; i++)
printf("%d ",perArray[i]);
free(perArray);
return 0;
}
void create1DArray(int** perArray, int* size)
{
int flag=0, i=0, x;
*perArray=(int*)malloc(sizeof(int) );
if(*perArray==NULL)
{
printf("Allocation failed!");
exit(1);
}
while(!flag)
{
if( scanf("%d", &x)<1 || (x<0) )
{
printf("Invalid input!");
free(perArray);
exit(1);
}
if(!x)
{
if( !(*size) )
{
printf("The first element of the array must not be 0");
free(perArray);
exit(1);
}
flag++;
}
else
{
*perArray=(int*)realloc(*perArray, (++(*size))*sizeof(int) );
if(*perArray==NULL)
{
printf("Reallocation failed!");
free(perArray);
exit(1);
}
*perArray[i++]=x;
}
}
}

I think I see two problems (and M Oehm spotted one more):
1) Your handling of size is wrong (or at least strange). Normally you'll do something like:
*perArray=(int*)malloc(sizeof(int) );
*size = 1;
Perhaps even better - you should drop the malloc and just initialize the pointer in main to NULL. realloc works like malloc when called with NULL.
This would also allow you to call the function several times - something you current code doesn't allow.
2) There is a problem with your realloc
*perArray=(int*)realloc(perArray, (++(*size))*sizeof(int) );
^^^^
Should be *perArray
3) You need to dereference the pointer before indexing (noticed by M Oehm - thanks).
*perArray[i++]=x; ---> (*perArray)[i++]=x;

May not be exactly what you want, but take a look at how it can be done concisely (although doing realloc at each iteration is inefficient). It should be compiled with the flag std=c11.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int main()
{
int size = 0;
int input = 0;
int * perArray = NULL;
while(scanf("%d", &input) && input > 0)
{
++size;
perArray = (int *) realloc(perArray, sizeof(int) * (long unsigned) size);
assert(perArray);
perArray[size - 1] = input;
}
if(perArray)
{
for(int i = 0; i < size; ++i) printf("%d ", perArray[i]);
printf("\n");
free(perArray);
}
return 0;
}

Related

I made a function which covert decimal to binary. but it does not work

#include <stdio.h>
void DectoBin(int *n);
int *p;
int position;
int main()
{
int num;
printf("Input number : ");
scanf("%d", &num);
DectoBin(&num);
for (int i = position - 1; i >= 0; i--)
{
printf("%d", p[i]);
}
}
when launch this code, this code compile well...
but I have a error message 'zsh : segmentation fault'
void DectoBin(int *n)
{
int binary[20] = { 0, };
p = binary;
while (1)
{
binary[position++] = *n % 2;
*n = *n / 2;
if (n == 0)
break;
}
return;
}
so, What parts should be corrected to solve the problem??
I think the minimum change to make it seem to work is this:
// you use *n as an integer, but test "n"
// (which is its address, and will never be zero).
// So the while loop goes on indefinitely, eventually overflowing the buffer.
if (*n == 0)
break;
A more serious problem is that the buffer is allocated backwards: you have the pointer outside the function and the buffer is allocated on the stack inside the function. So, as soon as the function exits, the buffer is no longer "legal". The data is probably still there (on my system, it is) and you might even be able to use it as if nothing was amiss. On a short program, and depending on your system, you might not notice that the code has become a time bomb.
You ought to estimate how much of a buffer you need (how many binary digits), then allocate memory on the heap, using malloc(), check it worked, and pass that memory to the function - which will allocate nothing - together with the allocated size, so it can ensure it doesn't overflow the buffer.
The function would then return how many digits to actually print.
#include <stdio.h>
#include <malloc.h>
size_t DectoBin(size_t maxdigits, int *digits, int number);
int main() {
int num;
int *buffer;
size_t maxdigits, position;
printf("Input number : ");
scanf("%d", &num);
// Always check your inputs.
if (num < 0) {
printf("Negative numbers are not supported yet\n");
return 1;
}
maxdigits = 1;
{
// Calculate how many digits are required. Could use ceiling of base-2 logarithm of num.
int tmp = num;
while (tmp > 0) {
maxdigits ++;
tmp /= 2;
}
}
buffer = malloc(maxdigits * sizeof(int));
if (NULL == buffer) {
fprintf(stderr, "Out of memory\n");
return 2;
}
position = DectoBin(maxdigits, buffer, num);
for (size_t i = position; i > 0; i--) {
printf("%d", buffer[i-1]);
}
printf("\n");
return 0;
}
size_t DectoBin(size_t maxdigits, int *digits, int number) {
size_t pos = 0;
do {
digits[pos++] = number % 2;
number /= 2;
} while (number && pos < maxdigits);
return pos;
}
For starters there is a typo
if (n == 0)
It seems you mean
if (*n == 0)
Though there is no any sense to accept a number indirectly through a pointer to it.
You are using the local array binary with automatic storage duration within the function DectoBin
void DectoBin(int *n)
{
int binary[20] = {
0,
};
//...
that will not be alive after exiting the function. So the pointer p will have an invalid value.
Also it is unclear why you are using the magic number 20 in the array declaration. At least you should use the value of the expression sizeof( int ) * CHAR_BIT.
Also it is a bad idea to use global variables.
At Least you could declare the array within the function with the storage-class specifier static and return a pointer to the array from the function.
Pay attention to that for negative numbers you can get an incorrect result.
For example the function can be implemented the following way as shown in the demonstration program below.
#include <stdio.h>
#include <limits.h>
#include <string.h>
const char * DecToBin( int n )
{
static char binary[CHAR_BIT * sizeof( int ) + 1 ];
memset( binary, 0, sizeof( binary ) );
unsigned int un = n;
char *p = binary + sizeof( binary ) - 1;
do
{
*--p = '0' + ( un & 1 );
} while ( un >>= 1 );
return p;
}
int main( void )
{
printf( "%d -> %s\n", 123, DecToBin( 123 ) );
printf( "%d -> %s\n", -123, DecToBin( -123 ) );
}
The program output is
123 -> 1111011
-123 -> 11111111111111111111111110000101

Is there anyway to decide the amount of array while running your code?

I'm trying to write a beginner c code when you get unknown amount of integers from user and process them. Since it's is not valid to initialize a array of integers without deciding the size, i wonder if i could do some trick to make my code more efficient. Currently I'm initializing an array with size of 999 and ask user not to go beyond this border.
example code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a[999];
printf("After entering numbers enter -1 to stop: \n");
for(int i=0;i<999;i++)
{
printf("Enter number(%d): ",i+1);
scanf("%d",&a[i]);
if(a[i]==-1) break;
if(i==998)
{
printf("Max limit reached.");
break;
}
}
//some code for processing the numbers
}
2 options: a) ask the user how many items and use a Variable Length Array (added to Standard C in C99; made optional in C11) ... or b) use dynamic memory and keep growing the array.
option a)
printf("enter number of items: ");
fflush(stdout);
char input[100];
fgets(input, sizeof input, stdin); // error checking ommited
size_t n = strtol(input, 0, 10); // error checking ommited
int array[n]; // VLA
// use array
option b)
size_t reserved = 5; used = 0;
int *array = malloc(reserved * sizeof *array); // start with space for 5 items
for (;;) {
if (used == reserved) {
// grow array
reserved *= 2;
int *tmp = realloc(array, reserved * sizeof *tmp);
if (!tmp) exit(EXIT_FAILURE); // not enough memory
array = tmp;
}
array[used++] = getint(); // get integer from user/file/network/...
// find way to leave for loop
}
// optionaly shrink the array
if (used < reserved) {
int *tmp = realloc(array, used * sizeof *tmp);
if (!tmp) exit(EXIT_FAILURE);
array = tmp;
}
// use array
free(array);
Option b) is preferred if the number of items can be large so as to not cause a stack overflow.
One sensible option is to forget about scanf and use command-line arguments instead. Faster, potentially safer (if you add an upper-bounds check), less memory consumed.
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char* argv[])
{
if(argc < 2) // or if(argc < 2 || argc > SOME_UPPER_LIMIT)
return 0;
size_t size = argc-1;
int input [size];
for(size_t i=0; i<size; i++)
{
input[i] = strtol(argv[i+1],NULL,10);
printf("%d ", input[i]);
}
}
Execute as for example: myprog 12 34 56 78 -> Output 12 34 56 78.
you can use this also :
#define MAXSIZE 999
void getNums(int nums[]){
int i = 0, temp;
char c;
while(((c=getchar())!='\n') && (i < MAXSIZE-1)){
temp = c - '0';
nums[i] = temp;
i++;
}
nums[i] = '\0';
}
int main(){
int nums[MAXSIZE];
getNums(nums);
return 0;
}

C function stops after few iterations

The program should do this: write a doubleArray() function, which takes in input an array of int and its size (as a pointer to int). In the main(): ask the user to input an integer n between 1 and 4, then dynamically create an array of size n. Then start filling the array with 2048 randomly generated int: each time the array is full, call the doubleArray function; each time the function doubleArray is called, print the content of the array.
My code works until the size of array n reach a number around 250, then stops inside the for loop.
#include<stdlib.h>
#include<stdio.h>
#include<time.h>
void doubleArray(int vect[], int *dim)
{
int n = *dim *2;
*dim = n;
vect = (int*)realloc(vect, n*sizeof(int));
}
void stampaArray(int vect[], int dim)
{
for (int i=0;i<dim;i++)
{
printf("%d ",vect[i]);
}
printf("\n");
}
int main()
{
printf("Insert a number between 1 and 4: ");
int n;
scanf("%d",&n);
if ((n<1)||(n>4))
{
printf("Number not valid, try again: '");
scanf("%d",&n);
}
int *arr = (int*) malloc (n*sizeof(int));
srand(time(NULL));
int num;
for (int i=0;i<220;i++)
{
num = rand();
if (i==n)
{
doubleArray(arr, &n);
stampaArray(arr, n);
}
arr[i]=num;
}
stampaArray(arr,n);
return 0;
}
Firstly, Change this
if ((n<1)||(n>4)) { } /* use && instead of || to scan if n if both condition are true*/
to
//scanf("%d",&n); /*remove this, use only once, in below loop */
while(1) {
scanf("%d",&n);
if ((n>=1) && (n<=4)) {
break;
}
else {
printf("Number not valid, try again: '");
}
}
And allocate memory equal to n bytes. for e.g
int *arr = malloc (n * sizeof(*arr)); /* typecasting is not required */
Also here
for (int i=0;i<220;i++) { /* some code */ }
what is the rationale behind rotating loop 220 times, doesn't it should be n times ?
As you were said in comment, your main error is that realloc is allowed to change the pointer value. If it happens, the new value is only assigned to the local copy inside the doubleArray function, but the caller still keeps the previous value which is now a dangling pointer (pointing to non allocated memory). Using it invokes Undefined Behaviour (and crashes are to be expected...)
The correct way is to return the new pointer value:
int * doubleArray(int vect[], int *dim)
{
int n = *dim *2;
*dim = n;
return realloc(vect, n*sizeof(int));
}
That is not all. best practices recommend to test allocation. In a stressed environment, the system could be unable to allocate enough memory and realloc could return NULL. Proceeding would then also involve Undefined Behaviour.
Let us go on. Controlling input is nice, but a user can type twice an error, so you should loop until you get a correct value:
int n;
for (;;) {
printf("Insert a number between 1 and 4: ");
scanf("%d",&n);
if ((n >= 1) && (n <= 4)) break;
printf("Number not valid, try again: '");
}
And please, please do not cast malloc in C language. It is useless and can hide hard to find indirection level errors.
Finally, I cannot understand why you have a loop up to 220... From your requirements it should be up to 2048.
Last point (but this one is only my opinion, not a problem): I would only display the initialized content of the array, so up to i instead of n. That way you would see the array grow while always keeping the same (initialized) values:
int *arr = malloc (n*sizeof(int));
srand(time(NULL));
int num;
for (int i=0;i<2048;i++)
{
num = rand();
if (i==n)
{
arr = doubleArray(arr, &n);
if (arr == NULL) {
perror("allocation error");
return 1;
}
stampaArray(arr, i);
printf("\n");
}
arr[i]=num;
}
stampaArray(arr,2048);
free(arr); // not required immediately before a return but good practice

Trying to script a matrix multiplication experiment

So I am tasked with scripting a program that multiplies random matrices between size 50 and 3000, and I have hit a snag. I am unsure of the best way to change the size while the script is running. I could manually do it but that would take hours of sitting in front of the computer, and I feel like there is a simple way that I am missing. I am aware that if I define these matrices within main, anything over about 800 will cause the proverbial stack overflow, which is why I have placed them outside of main. Unfortunately, now I cannot simply pass N as argv[1]. My question is this: is it possible to be able to script something along these lines:
./matrix 50
./matrix 150
./matrix 200
et cetera
and if so, how?
#include <foo>
#define N 1000
int A[N][N];
int B[N][N];
int result[N][N];
int main(int argc, char *argv[]){
//so on
thank you in advance to all who reply.
If the dimension n is passed to the program as an argument, the
malloc/calloc is a good option. I'd do something like this:
int **matrix_create(size_t dim)
{
int **matrix = calloc(dim, sizeof *matrix);
if(matrix == NULL)
return NULL;
for(size_t i = 0; i < dim; ++i)
{
matrix[i] = calloc(dim, sizeof *matrix[i]);
if(matrix[i] == NULL)
{
matrix_free(matrix, dim);
return NULL;
}
}
return matrix;
}
void matrix_free(int **matrix, size_t dim)
{
if(matrix == NULL)
return;
for(size_t i = 0; i < dim; ++i)
free(matrix[i]);
free(matrix);
}
Then you can create the matrix from main like this:
int main(int argc, char **argv)
{
if(argc < 2)
{
fprintf(stderr, "usage: %s dim\n", argv[0]);
return 1;
}
// just an example of how to convert,
// you could also use strtol
size_t dim = atoi(argv[i]);
int **matrix_a = matrix_create(dim);
if(matrix_a == NULL)
return 1;
int **matrix_b = matrix_create(dim);
if(matrix_b == NULL)
{
matrix_free(matrix_a);
return 1;
}
do_something_with(matrix_a, matrix_b, dim);
matrix_free(matrix_a);
matrix_free(matrix_b);
return 0;
}
Note that I used calloc instead of malloc, because calloc has the benefit
to set 0 to the allocated memory. It's great for initializing and error
handling, because free(NULL) is allowed, so as you see when allocating memory
for the matrix[i] rows, if something goes wrong, I can safely use
matrix_free on the whole matrix.

How to return int array in C using this Collatz Conjecture function?

I have a function for the Collatz Conjecture that returns an int Array but I keep getting a segmentation fault error and am not sure why.
int n=1;
int* col fuction(int x){
int *totalList;
totalList[0]=x;
while (x != 1){
if (x%2==0){
x=x/2;
}else{
x= 3* x + 1;
}
totalList[n]= x;
n++;
}
totalList[n+1]=1;
return totalList;
}
It is suppose to return the integers in a row with commas in between each number. I call it as shown below:
int *colAns;
colAns= col(num);
for (int k =0; k< n; k++){
printf("%d", colAns[k]);
if(colAns[k] != 1){
printf(",");
}
}
printf("\n");
Your issue lies within the first few lines of col_function().
int* col_fuction(int x){
int *totalList;
totalList[0]=x;
// ...
}
When the int* called totalList gets created on the stack, it takes whatever value was previously there. There's a slim chance that the pointer value will be anything even owned by the process, let alone something valid/usable.
What you need is a dynamically-allocated value that can grow as values are added to it. For this, we use malloc to allocate a pre-determined amount of memory. Because the collatz function is recursive and the number of elements cannot be determined by merely looking at it, we cannot presume to know exactly how much memory it will take, so it should grow as numbers are added to it. For this, we use realloc. What's nice about realloc is that, if the first parameter is NULL, it is guaranteed by the standard to work like malloc.
The only other thing you really need is a couple of size_t values inside of a struct in order to keep track of the current index as well as the allocated space. Something like this should be sufficient:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define CHUNK_SIZE 100
typedef struct dynarray
{
int *values;
size_t allocated, used;
} dynarray;
int dynarray_init(dynarray *d)
{
memset(d, 0, sizeof(dynarray));
return 0;
}
int dynarray_deinit(dynarray *d)
{
free(d->values);
memset(d, 0, sizeof(dynarray));
return 0;
}
int dynarray_append(dynarray *d, int val)
{
int *tmp = NULL;
size_t i;
if(d->used + 1 >= d->allocated)
{
if((tmp = (int*)realloc(d->values, (d->allocated + CHUNK_SIZE)*sizeof(int))) == NULL)
{
perror("realloc() failure");
return 1;
}
else
{
d->values = tmp;
d->allocated += CHUNK_SIZE;
}
}
d->values[d->used++] = val;
}
Use dynarray_append() to add values to the list after it's been initialized.

Resources