May you help me with this exercise please?
Write a C program that reads 6 integers from the keyboard and assigns the first 5 values at the first 5 positions of an array; store the sixth value in a variable N. Write a function that, given input the array initialized with the first 5 values from the keyboard and the integer N, returns the array resized to contain 5 + N elements, such that each one of the new N elements corresponds to the sum of the numbers before it in the array.
In main, print the content of the array returned by the function.
It's OK also all in the main function.
I have the problem when I have to use the function realloc to increment the array from size = 5 to 5 + N.
This is my code:
int N, a, i;
int *ptr;
int arr[6];
for (i = 0; i < 5; i++) {
printf("Insert number in array, position(%d): ", i);
scanf("%d", &arr[i]);
}
N = arr[4];
a = 5 + N;
ptr = (int *)realloc(arr, sizeof(int) * a);
for (i = 4; i < a; i++) {
ptr + i = N * N; //<--- **problem!!**
}
for (i = 0; i < a; i++) {
printf("%d\n", ptr[i]);
}
free(ptr);
You cannot reallocate an array defined locally in a function nor defined globally. You can only call realloc on an object previously allocated with malloc(), calloc() or realloc() or with a NULL pointer. So you must allocate the initial array with 5 elements in main() and reallocate it in the function.
#include <stdio.h>
#include <stdlib.h>
int *extend_array(int *arr, int N) {
int a = 5 + N;
arr = realloc(arr, a * sizeof(int));
if (arr != NULL) {
int sum = 0;
for (int i = 0; i < 5; i++) {
sum += arr[i];
}
for (int i = 5; i < a; i++) {
arr[i] = sum;
sum += sum;
}
}
return arr;
}
int main() {
int N;
int *arr = malloc(5 * sizeof(int));
if (arr == NULL) {
printf("allocation failed\n");
return 1;
}
for (int i = 0; i < 5; i++) {
printf("Insert number in array, position(%d): ", i);
if (scanf("%d", &arr[i]) != 1) {
printf("invalid input\n");
return 1;
}
}
printf("Insert the value of N: ");
if (scanf("%d", &N) != 1) {
printf("invalid input\n");
return 1;
}
int *ptr = extend_array(arr, N);
if (ptr == NULL) {
printf("reallocation failed\n");
} else {
arr = ptr;
for (int i = 0; i < 5 + N; i++) {
printf("%d\n", arr[i]);
}
}
free(arr);
return 0;
}
The assignment specifies that the function should take the array and the number N as arguments, but it would be better to make the initial size a variable and pass that to the function as well to make the code more generic, easier to extend, and less error prone as the constant 5 appears in many places.
If you need to reallocate an array then it initially must be allocated dynamically.
So this code
int arr[6];
//...
ptr = (int *)realloc(arr, sizeof(int) * a);
is invalid.
Pay attention to that according to the assignment you need to write a function that reallocates the array.
Bear in mind that it is a very bad style of programming to use "magic numbers" like 5. Instead use named constants or assign such numbers to variables and use them.
The program can look the following way.
#include <stdio.h>
#include <stdlib.h>
int * resize( int *a, size_t n, size_t m )
{
int *tmp = realloc( a, ( n + m ) * sizeof( int ) );
if ( tmp != NULL )
{
int sum = 0;
size_t i = 0;
while ( i < n ) sum += tmp[i++];
while ( i < n + m )
{
tmp[i] = sum;
sum += tmp[i++];
}
}
return tmp;
}
int main(void)
{
size_t n = 5;
int *a = malloc( n * sizeof( int ) );
size_t m = 0;
printf( "Enter %zu numbers. The last number shall be greater than 0: ", n + 1 );
for ( size_t i = 0; i < n; i++ )
{
scanf( "%d", a + i );
}
scanf( "%zu", &m );
int *tmp = resize( a, n, m );
if ( tmp != NULL )
{
a = tmp;
}
else
{
m = 0;
}
for ( size_t i = 0; i < n + m; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
free( a );
return 0;
}
The program output might look like
Enter 6 numbers. The last number shall be greater than 0: 1 2 3 4 5 6
1 2 3 4 5 15 30 60 120 240 480 960 1920 3840 7680
Related
This is the task I have got:
I need to write a function (not recursive) which has two parameters.
An array of integers.
An integer representing the size of the array.
The function will move the duplicates to an end of the array.
And will give the size of the different digits.
Example:
5 , 2 , 4 , 5 , 6 , 7 , 2, n = 7
we will get back 5 , 2 , 4 , 6 , 7 , 5 , 2 and 5
We must keep the original sort as it is (which means like in example 5 must)
It does not matter how we sort the duplicates ones but just keep the sort for the original array as it is)
The function has to print the number of different digits (like in example 5)
The the input range of numbers in array [-n,n]
I can only use 1 additional array for help.
It has to be O(n)
I tried it so many times and feel like am missing something. Would appreciate any advice/suggestions.
int moveDup(int* arr, int n)
{
int* C = (int*)calloc(n * 2 + 1, sizeof(int));
assert(C);
/*int* count = C + n;*/
int *D = arr[0];
int value = 0, count = 0;
for (int i = 0; i < n; i++)
{
value = arr[i];
if (C[value + n] == 0)
{
*D = arr[i];
D++;
count++;
}
C[value + n] = C[value + n] + 1;
}
while (1 < C[value + n])
{
*D = i;
D++;
C[value + n]--;
}
free(C);
return count;
}
This algorithm will produce the required results in O(n) arithmetic complexity:
Input is an array A with n elements indexed from A0 to An−1 inclusive. For each Ai, −n ≤ Ai ≤ n.
Create an array C that can be indexed from C−n to C+n, inclusive. Initialize C to all zeros.
Define a pointer D. Initialize D to point to A0.
For 0 ≤ i < n:
If CAi=0, copy Ai to where D points and advance D one element.
Increment CAi.
Set r to the number of elements D has been advanced from A0.
For −n ≤ i ≤ +n:
While 1 < CAi:
Copy i to where D points and advance D one element.
Decrement CAi.
Release C.
Return r. A contains the required values.
A sample implementation is:
#include <stdio.h>
#include <stdlib.h>
#define NumberOf(a) (sizeof (a) / sizeof *(a))
int moveDuplicates(int Array[], int n)
{
int *memory = calloc(2*n+1, sizeof *Array);
if (!memory)
{
fprintf(stderr, "Error, unable to allocate memory.\n");
exit(EXIT_FAILURE);
}
int *count = memory + n;
int *destination = Array;
for (int i = 0; i < n; ++i)
// Count each element. If it is unique, move it to the front.
if (!count[Array[i]]++)
*destination++ = Array[i];
// Record how many unique elements were found.
int result = destination - Array;
// Append duplicates to back.
for (int i = -n; i <= n; ++i)
while (0 < --count[i])
*destination++ = i;
free(memory);
return result;
}
int main(void)
{
int Array[] = { 5, 2, 4, 5, 6, 7, 2 };
printf("There are %d different numbers.\n",
moveDuplicates(Array, NumberOf(Array)));
for (int i = 0; i < NumberOf(Array); ++i)
printf(" %d", Array[i]);
printf("\n");
}
here is the right answer, figured it out by myself.
int moveDup(int* arr, int n)
{
int* seen_before = (int*)calloc(n * 2 + 1, sizeof(int));
assert(seen_before);
int val = 0, count = 0, flag = 1;
int j = 0;
for (int i = 0; i < n; i++)
{
val = arr[i];
if (seen_before[arr[i] + n] == 0)
{
seen_before[arr[i] + n]++;
count++;
continue;
}
else if (flag)
{
j = i + 1;
flag = 0;
}
while (j < n)
{
if (seen_before[arr[j] + n] == 0)
{
count++;
seen_before[arr[j] + n]++;
swap(&arr[i], &arr[j]);
j++;
if (j == n)
{
free(seen_before);
return count;
}
break;
}
/*break;*/
j++;
if (j == n)
{
free(seen_before);
return count;
}
}
}
}
second right answer
int* mem = (int*)calloc(2 * n + 1, sizeof * arr);
assert(mem);
int* count = mem + n;
int* dest = arr;
for (i = 0; i < n; ++i)
{
if (count[arr[i]]++ == 0)
{
*dest = arr[i];
*dest++;
}
}
res = dest - arr;
for (i = -n; i <= n; ++i)
{
while (0 < --count[i])
{
*dest++ = i;
}
}
free(mem);
return res;
here is my code and it always output -1 and I didn't know why. any help?
Input
The first line contains an integer t (1≤t≤104) — the number of test cases.
The first line of each test case contains an integer n (1≤n≤2⋅105) — the length of the array.
The second line of each test case contains n integers a1,a2,…,an (1≤ai≤n) — the elements of the array.
It is guaranteed that the sum of n over all test cases does not exceed 2⋅105.
Output
For each test case, print any value that appears at least three times or print -1 if there is no such value.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n, size,*arr, *frr,count,*ptr,g,s;
scanf("%d", &n);
ptr = (int*)malloc(n * sizeof(int));
for (int i = 0;i < n; i++)
{
scanf("%d",&size);
arr = (int*)malloc(size * sizeof(int));
frr = (int*)malloc(size * sizeof(int));
for(int j = 0; j < size; j++)
{
scanf("%d",arr+j);
*(frr + j) = -1;
}
if(size >= 3)
{
for (g = 0; g < size ; g++)
{
count=1;
for(s = g + 1; s < size;s++)
{
if(*(arr + g) == *(arr + s))
{
count++;
*(frr+s) = 0;
}
}
if(*(frr+g) != 0 )
{
*(frr+g) = count;
}
if(*(frr+g) >= 3)
{
*(ptr+i) = *(arr + g);
}else
{
*(ptr+i) = -1;
}
}
}else
{
*(ptr+i) = -1;
}
free(arr);
free(frr);
}
for(int j = 0;j<n;j++)
{
printf("%d\n",*(ptr+j));
}
}
The problem is that you set *(ptr+i) to -1 for each element of the array. This means that a later element of the array that is not repeated three times will reset *(ptr+i) to -1.
Change this
if(*(frr+g) >= 3)
{
*(ptr+i) = *(arr + g);
}
else
{
*(ptr+i) = -1;
}
to this
if(*(ptr+i) == -1 && *(frr+g) >= 3)
{
*(ptr+i) = *(arr + g);
}
and at the beginning add this
ptr = (int*)malloc(n * sizeof(int));
for (int i = 0;i < n; i++)
{
*(ptr + i) = -1;
But as has already been said in the comments you do not need either the ptr array or the frr array. You only run one test at a time so there is no need to keep all the test results before you print any of them out. And you only need to save the frequency of the current element you are testing, so you don't need an array for that either.
And make your code readable, change *(arr + g) to arr[g]. They both work exactly the same.
For starters this array allocation
ptr = (int*)malloc(n * sizeof(int));
does not make a sense. For each given sequence of numbers you can at once output whether the sequence contains three equal elements or not without storing this information in the allocated array.
Also allocating this auxiliary array
frr = (int*)malloc(size * sizeof(int));
makes the code unsafe and inefficient.
It does not make a sense to travers the array if an element that occurs already three times is found.
Otherwise this code snippet
if(*(frr+g) >= 3)
{
*(ptr+i) = *(arr + g);
}else
{
*(ptr+i) = -1;
}
for elements that are present in the tail of the array arr can incorrectly
set the value ptr[i] to -1 though early there was already found a preceding element that occurs three times.
Without the redundant arrays pointed to by the pointers ptr and frr the program can look the following way
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
size_t t = 0;
scanf( "%zu", &t );
while (t--)
{
size_t n = 0;
scanf( "%zu", &n );
int result = -1;
if (n)
{
int *a = malloc( n * sizeof( int ) );
for (size_t i = 0; i < n; i++)
{
scanf( "%d", a + i );
}
for (size_t i = 2; result == -1 && i < n; i++)
{
int count = 1;
for (size_t j = i; count != 3 && j-- != 0; )
{
if (a[j] == a[i]) ++count;
}
if (count == 3) result = a[i];
}
free( a );
}
printf( "%d\n", result );
}
}
I would approach the problem altogether differently. Since the range of the elements is not explicitly bounded, it is a bit tricksome to manage a frequency table. But the maximum number of elements in each test array is pretty small, so it is feasible to
declare an array large enough to hold all the elements of any test case
for each test case,
read all the elements into the (one) array
sort the array (qsort(), or roll your own insertion or selection sort)
scan the sorted array to easily detect and report values that appear at least thrice
I'm a beginner in programing so please be understanding with my code.. I'm working on a problem set where I have to implement a selection sort using recursion. I feel like it should work but I get an error message and i can't figure out why.
the problem set consists in that I use a recursive function where i have to look for the largest number in an array, store it in the last position and sort the entire array using this method.
int array[n];
printf ("enter numbers: ");
for (i = 0; i < n; i++)
{
scanf ("%i", &array[i]);
}
selection_sort(n, array);
printf ("sorted numbers: ");
for (i = 0; i < n; i++)
{
printf ("%i", array[i]);
}
return 0;
here is the recursive function that i'd like to implement.
i used curpos to store the position of the largest number,
lastpos to store the location of the last element in the array,
and a tmp variable to store the largest number.
and this is the error message that i get.
.c:67:34: error: incompatible integer to pointer conversion passing 'int' to parameter of type 'int *'; take the address with & [-Werror,-Wint-conversion]
return selection_sort(n, array[n-1]);
^~~~~~~~~~
&
if (n <= 0)
{
return 1;
}
else
{
for (i = 0; i < n; i++)
{
if (tmp <= array[i]) //look for the largest number and update it into tmp
{
tmp = array[i];
curpos = array[i]; //remember the location of the current largestnumber
}
}
lastpos = array[n-1]; // save the last element into a variable before swap
array[n-1] = tmp; // put the largest number into the last element
curpos = lastpos; // put the last element before swap into the changed location.
return selection_sort(n, array[n-1]);
}
}
I hope you can give me a hand to understand the recursion better. thank you so much in advance.
The return value is a red herring. You don't use it so your function may as well be void.
if (n <= 0)
{
return 1;
}
The second thing to notice is that you can't pass an array to a function. You are passing a pointer to the beginning of the array. This is good, because otherwise you wouldn't be able to sort it.
else
{
for (i = 0; i < n; i++)
{
Right here is an issue. You haven't initialised tmp and curpos. You need to do that before the loop.
if (tmp <= array[i]) //look for the largest number and update it into tmp
{
tmp = array[i];
curpos = array[i]; //remember the location of the current largestnumber
}
}
lastpos = array[n-1]; // save the last element into a variable before swap
array[n-1] = tmp; // put the largest number into the last element
curpos = lastpos; // put the last element before swap into the changed location.
Finally, right here you have the right idea, but the wrong notation. You want to pass the same array, but 1 less element
return selection_sort(n, array[n-1]);
Should be:
return selection_sort(n-1, array);
}
The error message means that in this call
return selection_sort(n, array[n-1]);
you are passing an element of the array of the type int with the index n-1. But the function expects a pointer of the type int *.
Moreover the value of the first parameter is always the same and equal to n.
Also the return type of the function does not make a sense. The function should be declared with the return type void.
Also you need to swap two elements if within the array there is found an element that is greater than the last element.
The function can be declared and defined the following way
void selection_sort( int a[], size_t n )
{
if (!( n < 2 ))
{
size_t i = --n;
for (size_t j = n; j-- != 0; )
{
if (a[i] < a[j]) i = j;
}
if (i != n)
{
int tmp = a[i];
a[i] = a[n];
a[n] = tmp;
}
selection_sort( a, n );
}
}
Here is a demonstration program.
#include <stdio.h>
void selection_sort( int a[], size_t n )
{
if (!( n < 2 ))
{
size_t i = --n;
for (size_t j = n; j-- != 0; )
{
if (a[i] < a[j]) i = j;
}
if (i != n)
{
int tmp = a[i];
a[i] = a[n];
a[n] = tmp;
}
selection_sort( a, n );
}
}
int main( void )
{
int a[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
const size_t N = sizeof( a ) / sizeof( *a );
for (size_t i = 0; i < N; i++)
{
printf( "%d ", a[i] );
}
putchar( '\n' );
selection_sort( a, N );
for (size_t i = 0; i < N; i++)
{
printf( "%d ", a[i] );
}
putchar( '\n' );
}
The program output is
9 8 7 6 5 4 3 2 1 0
0 1 2 3 4 5 6 7 8 9
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNING
#endif
#include <stdio.h>
#include <stdlib.h>
void bubbleSort(int matrix[9], int n);
int main(void) {
int matrix[9];
int n = 9;
printf("enter 10 values to the matirx \n");
for (int i = 0; i < 10; i++) {
printf("now %dth componet\n ", i+1);
scanf("%d", &matrix[i]);
}
bubbleSort(matrix[9], n);
return 0;
}
void bubbleSort(int matrix [9], int n) {
//bubble sort the given matrix
int temp = 0;
for (int i=n-1; i > 0; i--) {
// compare two values at j and j+1 and move left when j+1 is smaller than j
for (int j = 0; j < i; j++) {
if (matrix[j] > matrix[j + 1]) {
temp = matrix[j];
matrix[j] = matrix[j + 1];
matrix[j + 1] = temp;
}
}
printf("Check the matrix \n");
for (int i = 0; i < 9; i++) {
printf("%d ", matrix[i]);
}
printf("\n");
}
}
Hi, I am getting a read access violation error at
if (matrix[j] > matrix[j + 1]) {
**temp = matrix[j];**
matrix[j] = matrix[j + 1];
matrix[j + 1] = temp;
}
This part of the code. The code builds right, but when I run the program I get an error. Can anyone help me out to figure out the issue? I searched up a little bit and based on that I assume it has something to do with the pointer but I do not know why there would be an issue with a pointer since I never used it in my code.
For starters you declared an array that contains only 9 elements.
int matrix[9];
On the other hand, you are trying to enter 10 elements.
printf("enter 10 values to the matirx \n");
for (int i = 0; i < 10; i++) {
printf("now %dth componet\n ", i+1);
scanf("%d", &matrix[i]);
}
So the program already has undefined behavior.
In this function declaration
void bubbleSort(int matrix[9], int n);
the magic number 9 used in the declaration of the first parameter does not make a great sense. Just write
void bubbleSort(int matrix[], int n);
or
void bubbleSort(int *matrix, int n);
In this call
bubbleSort(matrix[9], n);
instead of passing the array matrix like
bubbleSort(matrix, n);
you are passing the non-existent element of the array matrix[9]. The compiler should issue a message that you are trying to convert an integer to a pointer.
Within the function you are using the magic number 9 instead of the parameter n in this loop
for (int i = 0; i < 9; i++) {
Pay attention to that it looks strange when a one-dimensional array is named matrix.
Using your approach the program can look the following way.
#include <stdio.h>
void bubbleSort( int matrix[], size_t n )
{
if ( n )
{
for ( size_t i = n - 1; i != 0; i-- )
{
// compare two values at j and j+1 and move left when j+1 is smaller than j
for ( size_t j = 0; j < i; j++ )
{
if ( matrix[j + 1] < matrix[j] )
{
int temp = matrix[j];
matrix[j] = matrix[j + 1];
matrix[j + 1] = temp;
}
}
}
}
}
int main(void)
{
enum { N = 9 };
int matrix[N];
printf( "enter %d values to the matirx \n", N );
for ( int i = 0; i < N; i++ )
{
printf( "now %dth componet\n", i+1 );
scanf( "%d", matrix + i );
}
bubbleSort( matrix, N );
for ( int i = 0; i < N; i++ )
{
printf( "%d", matrix[i] );
}
putchar( '\n' );
return 0;
}
The program output might look
enter 9 values to the matirx
now 1th componet
9
now 2th componet
8
now 3th componet
7
now 4th componet
6
now 5th componet
5
now 6th componet
4
now 7th componet
3
now 8th componet
2
now 9th componet
1
1 2 3 4 5 6 7 8 9
bubbleSort(matrix[9], n);
This passes just the final element of the list (coerced into an address) rather than the actual address of the list, which is what you probably intended.
That won't end well :-)
You should just pass in matrix.
A decent compiler should warn you of this, such as with gcc:
prog.c: In function ‘main’:
prog.c:21:22: warning: passing argument 1 of ‘bubbleSort’
makes pointer from integer without a cast
[-Wint-conversion]
21 | bubbleSort(matrix[9], n);
| ~~~~~~^~~
| |
| int
prog.c:7:21: note: expected ‘int *’ but argument is of
type ‘int’
7 | void bubbleSort(int matrix[9], int n);
| ~~~~^~~~~~~~~
#include <stdio.h>
#include <malloc.h>
int insertAt(int *Arr, int len, int num) {
for (int i = 0; i < len; ++i) {
if (num <= Arr[0])
return 0;
else if (num >= Arr[len])
return len + 1;
else if (num >= Arr[i - 1] && num <= Arr[i])
return i;
}
}
int * sortedArrayInsertNumber(int *Arr, int len, int num){
int *output = (int *)malloc((len + 1)*sizeof(int));
if (len <= 0)
return NULL;
for (int i = 0, j = 0; j <= len+1; ++i, ++j) {
if (i == insertAt(Arr, len, num) && j==i) {
output[j] = num;
--i;
}
else if(insertAt(Arr,len,num)==len+1) {
output[j] = num;
}
else {
output[j] = Arr[i];
}
}
return output;
}
int main() {
int input[5] = {2,4,6,8,10};
int *out = (int*)malloc(6*sizeof(int));
out = sortedArrayInsertNumber(input, 5, 12);
for(int i=0;i<6;++i) {
printf("%d\n", out[i]);
}
}
When I try out this test case, it gives me a runtime error sometimes. Other times, it outputs:
2
4
6
8
10
12
Which makes no sense?
Also, is there a way to make my code better?
The question requires me to insert a value num at its appropriate index.
In the function insertAt there is at least two attempts to access memory beyond the array. The first one is in the statement
else if (num >= Arr[len])
^^^^
And the second one is in the statement
else if (num >= Arr[i - 1] && num <= Arr[i])
^^^^^^
when the variable i is equal to 0.
The function sortedArrayInsertNumber starts with a potential memory leak when the variable len is equal at least 0 because at first a memory is allocated and then there is exit from the function with A NULL pointer.
int * sortedArrayInsertNumber(int *Arr, int len, int num){
int *output = (int *)malloc((len + 1)*sizeof(int));
if (len <= 0)
return NULL;
// ...
Also it is a bad idea when the length of an array has type int instead of type size_t.
To call several times the function insertAt in the function sortedArrayInsertNumber does not make sense and breaks the loop.
In the main there is again a memory leak
int *out = (int*)malloc(6*sizeof(int));
out = sortedArrayInsertNumber(input, 5, 12);
The program can look the following way.
#include <stdio.h>
#include<stdlib.h>
size_t insertAt( const int *a, size_t n, int num )
{
size_t i = 0;
while ( i < n && !( num < a[i] ) ) i++;
return i;
}
int * sortedArrayInsertNumber( const int *a, size_t n, int num )
{
int *b = malloc( ( n + 1 ) * sizeof( int ) );
if ( b )
{
size_t pos = insertAt( a, n, num );
size_t i = 0;
for ( ; i < pos; i++ ) b[i] = a[i];
b[i] = num;
for ( ; i < n; i++ ) b[i+1] = a[i];
}
return b;
}
int main(void)
{
int input[] = { 2, 4, 6, 8, 10 };
const size_t N = sizeof( input ) / sizeof( *input );
int *out = sortedArrayInsertNumber( input, N, 12 );
if ( out )
{
for ( size_t i = 0; i < N + 1; i++ )
{
printf( "%d ", out[i] );
}
putchar( '\n' );
}
free( out );
return 0;
}
Its output is
2 4 6 8 10 12
Instead of the loops in the function sortedArrayInsertNumber you can use standard C function memcpy declared in header <string.h>.