Input array with recursively function without loops (.c) - c

I need to write a function, to input the size of array and allocate memory, and read (scanf) values to this array.
I wrote this function but it does not work:
void getss(int array[], int size)
{
int counter = 0;
if (size == 0)
return;
if (counter < size) {
scanf("%d", &array[i]);
counter++;
}
getss(array, size - 1);
}

It is not exactly clear what you are trying to achieve. But I would guess that your array parameter is not correct in the recursive call. Now all calls to getss get same array but different size. (Where does variable i come from? Variable counter does not have much use in posted code.)
I would assume that you need to update the array pointer to point to next element in array in the recursive call. In other words, pass address of second element in the array instead of the first element (current behaviour). That would be in line with the size-1 in the recursive call.
The implementation is trivial but is left as an exercise to the poster as this looks like homework to me.

You have unneeded variables. Is this what you are trying to accomplish:
The following will fill in the array so that the first value read with scanf() will be stored in the last element.
void getss(int array[], int size)
{
if (size == 0)
return;
scanf("%d", &array[size-1]);
getss(array, size - 1);
return;
}
The following will fill in the array so that the first value read with scanf() will be stored in the first element.
void getss(int array[], int size)
{
if (size == 0)
return;
scanf("%d", &array[0]);
getss(&array[1], size - 1);
return;
}

If you were to do this iteratively, how would you do it? I would assume something like this:
void getss(int array[], int size) {
int i;
for (i = 0; i < size; i++) {
scanf("%d", array[i]);
}
}
Our i there just serves to count our way through the array, so if we change our function slightly we can get rid of it:
void getss(int* array, int size) {
for (; size > 0; size--, array++) {
scanf("%d", array);
}
}
Now our "counter" is the size variable itself and instead of indexing in our array we just keep stepping forward our pointer to it.
Now this is in a perfect form to be turned into a recursive function. Instead of size-- and array++ we can pass the new values into another call to getss at the end of the function:
void getss(int* array, int size) {
if (size > 0) {
scanf("%d", array);
getss(array + 1, size - 1);
}
}
So our loop's terminating condition has moved into an if and instead of array++ and size-- we pass in array+1 and size-1 to our next call. It achieves the same result as looping but without an explicit loop construct.

Along with the other problems, what's the point of using counter? It is either 0 or 1 and never passed to the next call. Should it have been declared static?

#include <stdio.h>
#include <stdlib.h>
void getss(int* array, int size){
if (size == 0)
return;
scanf("%d", array);
getss(++array, size - 1);
}
int main(){
int *array;
int i, size;
printf("input array size:");
scanf("%d", &size);
array = (int*)malloc(sizeof(int)*size);
getss(array, size);
for(i=0;i<size;i++){
printf("array[%d]=%d\n", i, array[i]);
}
return 0;
}

#include<bits/stdc++.h>
using namespace std;
int a[100];
void input(int n)
{
if(n==0)
{
return;
}
input(--n);
cin>>a[n];
}
int main()
{
int n=4;
input(n);
for(int i=0;i<n;i++)
{
cout<<a[i]<<" ";
}
}

void getss(int array[], int size , int counter)
{
if (size == 0)
return;
if (counter < size) {
scanf("%d", &array[i]);
counter++;
}
getss(array, size - 1, counter);
}

Related

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

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.

Array pointers and functions

I have to write a C program to do the following:
Write a function that takes three arguments: a pointer to the first
element of a range in an array, a pointer to the element following
the end of a range in an array, and an int value. Have the function
set each element of the array to the int value.
My code is not working. Here is what I have so far. Any help is appreciated.
#include <stdio.h>
#include <iostream>
int listNumbers[3]{ 1,2,3 };
void Sorter(int *first, int * last, int *value);
int * first = &listNumbers[0];
int * last = &listNumbers[2];
int value;
int main() {
printf("your list numbers are:\n");
int i;
for (int i = 0; i < 3; ++i) {
printf("%d", listNumbers[i]);
}
printf("\n");
printf("enter an integer:\n");
scanf_s("%d", &value);
Sorter( first, last, &value);
printf("your new list numbers are:\n");
int j;
for (int j = 0; j < 3; ++j) {
printf("%d", listNumbers[j]);
}
printf("\n");
system("PAUSE");
return 0;
}
void Sorter(int *first, int * last, int *value) {
int i=0;
printf("value = %d\n", &value);
*first = value;
while (i <= *last) {
*(first + i) = value;
i++;
}
}
First, work out the different between the 2 pointers.
int count = last - first + 1;
The compiler will automatically divide by the size of an integer. We add 1 to make the range inclusive. Now just iterate through each element:
for (int i = 0; i < count; i++) {
first[i] = value;
}
Also, why are you passing the value as a pointer? This should just be a value.
void Sorter(int *first, int *last, int value) {
And when you call it...
Sorter(first, last, value);
Your Sorter function does not satisfy the problem criteria. The parameters are supposed to be two pointers into an array, and an int. Your function instead accepts three pointers.
You could nevertheless have made it implement at least the apparent spirit of the exercise, by using the value to which the third argument points as the fill value, but you don't do that. Instead you assign the pointer itself to each array element. That ought to at least elicit a warning from your compiler, and you ought not to be ignoring its warnings, especially when your code it not doing what you think it should.
Furthermore, the last pointer is expected to point to just past the last element to set, but you use it as if it points to an integer offset from the start pointer. This is almost the opposite of the previous problem: here, you need to use the pointer value itself, not the int to which it points.

Sorting an array with alternate smallest-largest values

Given an array I am required to sort it in such a way that the first element is the smallest value, the second element is the largest, the third element is the second smallest element and so on.
But my code just prints the original array and I am not able to figure out why. Any advice would be appreciated.
#include <stdio.h>
void swap(int m, int n);
int main()
{
int i,j,A[10],n;
printf ("enter the number of array elements\n");
scanf ("%d", &n);
for (i=0;i<n;i++){
scanf ("%d", &A[i]);
}
for (i=0;i<n;i++){
if (i%2 == 0){
for (j=i;j<n;j++){
if (A[j] < A[i]){
swap(A[i],A[j]);
}
}
}
else if (i%2 != 0){
for (j=i;j<n;j++){
if (A[j] > A[i]){
swap (A[i],A[j]);
}
}
}
}
for(i=0;i<n;i++){
printf ("%d\n", A[i]);
}
return 0;
}
void swap( int m, int n)
{
int temp;
temp = m;
m = n;
n = temp;
}
You need to pass by reference using pointers.
void swap( int *m, int *n)
{
int temp;
temp = *m;
*m = *n;
*n = temp;
}
and change your code to call it like this
swap (&A[i],&A[j]);
For a solution that doesn't use pointers you can use a MACRO like this;
#define swap(x,y) do{int t=(x);(x)=(y);(y)=t;}while(0);
swap(A[i],A[j]);
Just define this at the top of your file and remove the swap function and prototype. It's all about scope, because the MACRO is just a text replace it's in the correct scope to use A[i].
The first problem I notice in your program is your swap function. In your swap function, your parameters are primitive data types. Thus, the function creates copies of integers "m" and "n", and switches the values within the scope of the function swap. But as soon as the function returns, you haven't really swapped anything. To actually swap the values in the array that you created in main, you need to do a pass by reference(pass in pointers to the variable you are trying to swap). Modify your swap function like this:
void swap( int *m, int *n)
{
int temp;
temp = *m;
*m = *n;
*n = temp;
}
Then inside your main, pass in the address of that value in the array using the & operator(address of). Here is an example: swap (&A[i],&A[j]);
Other suggestions:
Format your code so there is space between your conditions in your for loops.
Add comments.

Passing an array to a sort function in C language

#include<stdio.h>
#include<conio.h>
float smallest(int arr[],int k,int n);
void sort(int arr[],int n);
void main()
{
int arr[20],i,n,j,k;
clrscr();
printf("\nEnter the number of elements in the array: ");
scanf("%d",&n);
printf("\nEnter the elements of the array");
for(i=0 ; i < n ; i++)
{
printf("\n arr[%d] = ",i);
scanf("%d",&arr[i]);
}
sort(arr,n);
printf("\nThe sorted array is: \n");
for(i=0 ; i < n ; i++)
printf("%d\t",arr[i]);
getch();
}
int smallest(int arr[],int k,int n)//smallest function
{
int pos=k,small=arr[k],i;
for(i=k+1;i<n;i++)
{
if(arr[i]<small)
{
small=arr[i];
pos=i;
}
}
return pos;
}
void sort(int arr[],int n)//sorting function
{
int k,pos,temp;
for(k=0 ; k < n ; k++)
{
pos=smallest(arr,k,n);
temp=arr[k];
arr[k]=arr[pos];
arr[pos]=temp;
}
}
In the above program the sort function is being called from main but the return type of sort is void and it still returns the sorted array. As after sorting the array the function should return the sorted array back to the calling function to print the sorted array but the program runs perfectly. How is that happening?
When you declare
int arr[20];
you can say "arr is an array of 20 integers". But arr is a pointer to an integer as well, pointing to the first integer in a row of 20. So de-referencing *arr is an integer, the same as arr[0] in fact.
This means when you pass arr to a function you only pass a pointer to that function. The function in this case works on the (copied) pointer. But this very pointer points exactly to the same memory as your original arr declared in main(). And that's the reason why manipulating arr in sort() is in fact manipulating arr in main().
When passing an array as a parameter, this
int smallest(int arr[],int k,int n)
means exactly the same as
int smallest(int *arr,int k,int n)
For example
#include<iostream>
void printArray(int data[])
{
for(int i = 0, length = sizeof(data); i < length; ++i)
{
std::cout << data[i] << ' ';
}
std::cout << std::endl;
}
int main()
{
int data[] = { 5, 7, 8, 9, 1, 2 };
printArray(data);
return 0;
}
You will see that only the first 4 elements of the array are printed. The sizeof(data) returns a value of 4! That happens to be the size of the pointer used to pass the array to printArray().
First the array does not get copied. The pointer to the first element of the array is copied
First, there is no connection between any function argument what is, or is not passed using a return statement with an expression according to the function's return type.
While it is true that all parameter passing in C is by value - copy the value to a "local parameter variable" - nothing is assumed about what is to happen at the memory location a pointer is referencing. So, a function can make any changes in the calling environment, even without returning a value.
As to parameters declared as being aType name[]. this is merely syntactic sugar for const aType* name.

Resources