I have some problem with removing an element from a sorted array (all instances of an element must be removed). When I run my program, I get a segmentation fault. I have no idea why that happens, because the function remElem(int*, int*, int) where 1st arg is an array, 2nd arg is a length of an array (which changes when elements are removed) and 3rd arg is an element to be removed -- worked properly before I expanded the program with switch statement and onther functions like shuffle(int*, int) (for shuffling elements of an array) and insElem(int*, int*, int) (for inserting an element into a sorted array. I have no idea what went wrong, please help. I will provide the code with comments. There are also some other minor questions provided with the comments. Thank you in advance :)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_LEN 1000
void initArray(int*, int);
void printArray(int*, int);
void swap(int*, int*);
void insSort(int*, int);
void insElem(int*, int*, int);
void remElem(int*, int*, int);
void shuffle(int*, int);
int main() {
int array[MAX_LEN];
int len, elem, comm;
srandom(time(NULL));
printf("Number of elements? >> ");
scanf("%d", &len);
initArray(array, len);
do {
printf("Command? (6 for help) >> ");
scanf("%d", &comm);
switch (comm) {
case 1:
printArray(array, len);
break;
case 2:
shuffle(array, len);
break;
case 3:
insSort(array, len);
break;
case 4:
printf("Insert element? >> ");
scanf("%d", &elem);
insElem(array, &len, elem);
break;
case 5:
printf("Remove element? >> ");
scanf("%d", &elem);
remElem(array, &len, elem);
break;
case 6:
printf("Help:\n");
printf("1 - Print\n");
printf("2 - Shuffle\n");
printf("3 - Sort\n");
printf("4 - Insert element\n");
printf("5 - Remove element\n");
printf("6 - Help (this screen)\n");
printf("0 - Quit\n");
break;
case 0:
break;
default :
printf("Wrong input! Repeat!\n");
}
} while (comm);
return EXIT_SUCCESS;
}
/*Initializes array with n random numbers from 0 to 9 (including)*/
void initArray(int a[], int n) {
int i;
for (i = 0; i < n; i++)
a[i] = random() % 10;
}
/*Prints n elements of an array*/
void printArray(int a[], int n) {
int i;
for (i = 0; i < n; i++)
printf("%d ", a[i]);
putchar('\n');
}
/*Swaps the values of two variables*/
void swap(int *i, int *j) {
*i = *i + *j;
*j = *i - *j;
*i = *i - *j;
/*I saved up some memory yaaaaaaay :3 */
/*I spent some processing time nooooo :| */
/*Which is better... with or without tmp variable???*/
/*I suppose it depends on application... clearly, this
method doesnt work with structures, for example*/
}
/*Sorts the elements of an array using insertion sort algorythm*/
void insSort(int a[], int n) {
int i, j;
for (i = 1; i < n; i ++)
for (j = i; j > 0 && a[j] < a[j-1]; j--)
swap(&a[j], &a[j-1]);
}
/*Inserts an element into a sorted array*/
/*Wassn meant to be working with unsorted arrays
in that case unpreddictable results*/
void insElem(int a[], int *n, int e) {
int i, j;
(*n)++;
for (i = 0; a[i] < e && a[i+1] < e; i++);
for (j = *n; j > i + 1; j--)
a[j] = a[j-1];
a[i+1] = e;
}
/*Removes an element from a sorted array*/
/*Wassn meant to be working with unsorted arrays
in that case unpreddictable results*/
void remElem(int a[], int *n, int e) {
int i, j;
for (i = 0; i < *n; i++) {
while (a[i] == e) {
for (j = i; j < *n; j++)
a[j] = a[j+1];
(*n)--;
}
}
}
/*Shuffles the elements of an array*/
/*I just did this on the fly...
are there any known algorythms for doing this*/
void shuffle(int a[], int n) {
int i;
for (i = 0; i < n; i++)
swap(&a[rand()%n], &a[rand()%n]);
}
The following can result in out-of-bounds access, leading to undefined behaviour:
for (j = i; j < *n; j++)
a[j] = a[j+1];
Consider what happens to a[j+1] when j == (*n)-1.
As to the swap() function, your clever-looking implementation is at risk of integer overflow and consequently undefined behaviour. Just use a temporary variable and let the compiler worry about efficiency.
In this cycle:
for (j = i; j < *n; j++)
a[j] = a[j+1];
When j = *n - 1, you will access memory that is outside of the array's bounds. This invokes undefined behavior and the result may be anything and so I believe it explains your crash. As for way the program did not crash before - well as this can do anything it may also have no negative effect.
Related
The program should eliminate any repeating digits and sort the remaining ones in ascending order. I know how to print unique digits but I donĀ“t know how to create a new vector from them that i can later sort.
#include <stdio.h>
void unique(double arr[], int n) {
int i, j, k;
int ctr = 0;
for (i = 0; i < n; i++) {
printf("element - %d : ",i);
scanf("%lf", &arr[i]);
}
for (i = 0; i < n; i++) {
ctr = 0;
for (j = 0, k = n; j < k + 1; j++) {
if (i != j) {
if (arr[i] == arr[j]) {
ctr++;
}
}
}
if (ctr == 0) {
printf("%f ",arr[i]);
}
}
}
int main() {
double arr[100];
int n;
printf("Input the number of elements to be stored in the array: ");
scanf("%d", &n);
unique(arr, n);
}
You can always break a larger problem down into smaller parts.
First create a function that checks if a value already exists in an array.
Then create a function that fills your array with values. Check if the value is in the array before adding it. If it is, you skip it.
Then create a function that sorts an array. Alternatively, qsort is a library function commonly used to sort arrays.
This is far from efficient, but should be fairly easy to understand:
#include <stdio.h>
#include <stdlib.h>
#define MAX_NUMS 256
int find(double *arr, size_t length, double val)
{
for (size_t i = 0; i < length; i++)
if (val == arr[i])
return 1;
return 0;
}
size_t fill_with_uniques(double *arr, size_t limit)
{
size_t n = 0;
size_t len = 0;
while (n < limit) {
double value;
printf("Enter value #%zu: ", n + 1);
if (1 != scanf("%lf", &value))
exit(EXIT_FAILURE);
/* if value is not already in the array, add it */
if (!find(arr, len, value))
arr[len++] = value;
n++;
}
return len;
}
int compare(const void *va, const void *vb)
{
double a = *(const double *) va;
double b = *(const double *) vb;
return (a > b) - (a < b);
}
int main(void)
{
double array[MAX_NUMS];
size_t count;
printf("Input the number of elements to be stored in the array: ");
if (1 != scanf("%zu", &count))
exit(EXIT_FAILURE);
if (count > MAX_NUMS)
count = MAX_NUMS;
size_t length = fill_with_uniques(array, count);
/* sort the array */
qsort(array, length, sizeof *array, compare);
/* print the array */
printf("[ ");
for (size_t i = 0; i < length; i++)
printf("%.1f ", array[i]);
printf("]\n");
}
Above we read values from stdin. Alternatively, fill_with_uniques could take two arrays, a source and a destination, and copy values from the former into the latter, only when they would be unique.
Remember to never ignore the return value of scanf, which is the number of successful conversions that occurred (in other words, variables assigned values). Otherwise, if the user enters something unexpected, your program may operate on indeterminate values.
So I'm very new to programming and the C language, and I would like to find the simplest, fastest, and most efficient way to count all the distinct elements of a 1D array. This was actually for a school assignment, but I've been stuck on this problem for days, since my program was apparently too slow for the online judge and it got a TLE. I've used regular arrays and dynamically allocated arrays using malloc, but neither worked.
Anyways, here's the latest code of it(using malloc):
#include <stdio.h>
#include <stdlib.h>
int distinct(int *arr, int N){
int j, k, count = 1;
for(j = 1; j < N; j++){
for(k = 0; k < j; k++){
if(arr[j] == arr[k]){
break;
}
}
if(j == k){
count++;
}
}
return count;
}
int main(){
int T, N, i = 0;
scanf("%d", &T);
do{
scanf("%d", &N);
int *arr;
arr = (int*)malloc(N * sizeof(int));
for(int j = 0; j < N; j++){
scanf("%d", &arr[j]);
}
int count = distinct(arr, N);
printf("Case #%d: %d\n", i + 1, count);
i++;
}while(i < T);
return 0;
}
The most efficient way depends on too many unknown factors. One way is to sort the array and then to count distinct elements in there, skipping the duplicates as you go. If you have sorted the array and gotten this:
1 1 1 1 2 2 2 2 3 3
^ ^ ^
+-skip--+-skip--+-- end
... you can easily see that there are 3 distinct values in there.
If you don't have a favourite sorting algorithm handy, you could use the built-in qsort function:
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
Example:
#include <stdio.h>
#include <stdlib.h>
int compar(const void *l, const void *r) {
const int* lhs = l;
const int* rhs = r;
if(*lhs < *rhs) return -1; // left side is less than right side: -1
if(*lhs > *rhs) return 1; // left side is greater than right side: 1
return 0; // they are equal: 0
}
int distinct(int arr[], int N){
// sort the numbers
qsort(arr, N, sizeof *arr, compar);
int count = 0;
for(int i=0; i < N; ++count) {
int curr = arr[i];
// skip all numbers equal to curr as shown in the graph above:
for(++i; i < N; ++i) {
if(arr[i] != curr) break;
}
}
return count;
}
int main() {
int T, N, i = 0;
if(scanf("%d", &T) != 1) return 1; // check for errors
while(T-- > 0) {
if(scanf("%d", &N) != 1) return 1;
int *arr = malloc(N * sizeof *arr);
if(arr == NULL) return 1; // check for errors
for(int j = 0; j < N; j++){
if(scanf("%d", &arr[j]) != 1) return 1;
}
int count = distinct(arr, N);
free(arr); // free after use
printf("Case #%d: %d\n", ++i, count);
}
}
I am creating a program which uses a pointer to function to allow the user to select from 2 options to perform on an array of integers: reverse or randomise. However, the program yield no output when executed. Where did I go wrong?
void reverseArray(int arraySize, int a[]);
void randomiseArray(int arraySize, int a[]);
void printArray(int arraySize, int a[], void (*arrayFunction)(int arraySize, int a[]));
int main ()
{
srand(time(NULL));
int selection;
int myArray[] = {2,4,6,8,10,12,14,16,18,20};
printf("Enter 0 for reverse, 1 for randomise.\n");
scanf("%d",&selection);
if (selection == 0)
printArray(sizeof(myArray)/sizeof(myArray[0]),myArray,reverseArray);
else if (selection == 1)
printArray(sizeof(myArray)/sizeof(myArray[0]),myArray,randomiseArray);
else
printf("Please make a valid selection\n");
return 0;
}
void reverseArray(int arraySize, int a[])
{
int i,j=arraySize,swap=0;
for (i=0;i<arraySize/2;i++)
{
swap = a[i];
a[i] = a[j];
a[j] = swap;
--j;
}
}
void randomiseArray(int arraySize, int a[])
{
int i,j,swap;
for (i=0;i<arraySize;i++)
{
j = rand()%(i+1);
if (j!=i)
{
swap = a[i];
a[i] = a[j];
a[i] = swap;
}
}
}
void printArray(int arraySize, int a[], void (*arrayFunction)(int arraySize, int a[]))
{
arrayFunction(arraySize, a);
for (int i = 0; i < arraySize; i++)
{
printf("%d ", a[i]);
}
printf("\n");
}
The user selects when function they want to perform by typing either 0 for reverse or 1 for randomise. Based on the decision, a printArray function is called with the respective choice.
reverseArray is just a generic swap function, and randomiseArray uses a Fisher-Yates shuffling algorithm.
I am assuming that the source of my error lies in the printArray fucntion, yet I cannot correct it.
Two errors
in reverseArray, j should start at arraysize - 1 or you will be writing one element past the end of the array
void reverseArray(int arraySize, int a[])
{
int i, j = arraySize - 1, swap = 0;
for (i = 0; i<arraySize / 2; i++)
{
swap = a[i];
a[i] = a[j];
a[j] = swap;
--j;
}
}
And in randomizearray(), you assign to a[i] twice, instead of using a[j] for the final assignment.
void randomiseArray(int arraySize, int a[])
{
int i, j, swap;
for (i = 0; i<arraySize; i++)
{
j = rand() % (i + 1);
printf("%d %d\n", i, j);
if (j != i)
{
swap = a[i];
a[i] = a[j];
a[j] = swap;
}
}
}
The first error causes undefined behavior when reversing, the second causes the array to stay the same. Other than that, the function pointers are setup fine and work correctly.
In reverseArray() your index j is out of range, it should he j=arraySize-1
Other than that it works for me.
You are accessing outside the bounds of your array, causing UB and in this case "no output":
In reverseArray, you must initialize j=arraySize-1. Without the -1 you go out of bounds.
Hi i was wondering why i can't manage to change the value of the variable "cinter" in this:
int nbobject=7, cinter, i, *inter;
printf("\nHow many elements in array :");
scanf("%d", &cinter);
inter=malloc(nbObject*sizeof(int));
printf("\nEnter the elements :");
for(i=0;i<cinter;i++){
scanf("%d",&inter[i]);
}
qsort(inter, cinter, sizeof *inter, compare);
noDuplicate(inter, cinter);
cinter=noDuplicate(inter,cinter);
for(i=0;i<cinter;i++){
printf("%d", inter[i]);
}
printf("\nNumber of elements in array : ");
printf("%d", cinter);
printf("\nArray elements : ");
for (i=0;i<cinter;i++){
printf("%d ", inter[i]);
}
int noDuplicate( int arr[],int size ){
int i=0, j=0;
for (i = 1; i < size; i++){
if (arr[i] != arr[j]){
j++;
arr[j] = arr[i]; // Move it to the front
}
}
// The new array size..
size = (j + 1);
return size;
}
So what i did is simply sort the array and remove the duplicate. I'd like for the variable "cinter" that's number of elements in the array to be reduced by the number of removed elements so that i can use it later on to know how many relevant elements are in the array but no matter what i always end up with the same number in the end.
Output :
How many elements in array : 6
Enter the elements : 2 1 2 3 5 1
Number of elements in array : 6
Array elements : 1 2 3 5 3 5
EDIT : #Arash here's a code you can run, all i need is to be able to change the value of cinter while i delete duplicates so i can use it later to know exactly how many relevant items are in my array.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
static int compare (void const *a, void const *b){
int const *pa = a;
int const *pb = b;
return *pa - *pb;
}
void main(){
int nbObjets=7, *inter;
size_t cinter;
size_t i, j;
printf("\nHow many elements in the array :");
scanf("%d", &cinter);
inter=malloc(nbObjets*sizeof(int));
printf("\nEnter the elements :");
for(i=0;i<cinter;i++){
scanf("%d",&inter[i]);
}
qsort(inter, cinter, sizeof *inter, compare);
noDuplicate(inter, cinter);
cinter=noDuplicate(inter, cinter);
printf("\nNumber of elements in the array (cinter) : ");
printf("%d", cinter);
printf("\nArray elements : ");
for (i=0;i<cinter;i++){
printf("%d ", inter[i]);
}
}
int noDuplicate( int arr[], size_t size ){
size_t i=0, j=0;
for (i = 1; i < size; i++){
if (arr[i] != arr[j]){
j++;
arr[j] = arr[i]; // Move it to the front
}
}
// The new array size..
size = (j + 1);
return size;
}
EDIT : I got it to work by making the changes that Arash told me to do, thanks for the help guys !
You can use pass by address to fix the problem:
void noDuplicate( int arr[],size_t *size ){
size_t i=0, j=0;
for (i = 1; i < *size; i++){
if (arr[i] != arr[j]) {
j++;
arr[j] = arr[i]; // Move it to the front
}
}
// The new array size..
*size = (j + 1);
}
Then you call it this way:
noDuplicate(inter, &cinter);
You try to return the new size at the end in a void function. And the compiler doesn't complain? Make it int (and, btw, not size_t).
int noDuplicate( int arr[],size_t size )
{
(BTW: Throwing such an unformatted code in a Q is not very helpful.)
Of course in your main() you should assign the return value to cinter or whatever.
cinter = noDuplicate(inter, cinter);
#include <stdio.h>
int main(){
void sorting(){
int a[4];
a[0]=1;
a[1]=6;
a[2]=15;
a[3]=3;
a[4]=19;
int size = 4;
int t =1;
if (size ==0) return; // ie if you reach to the end stop
int i;
for (i=0;i<size-1;i++){
if(a[i+1] >a[i]) { //if the +1 element is bigger than before it do the swap
int j;
j= a[i+1];
a[i+1]=a[i]; //swap
a[i] = j; //swap
}
}
sorting(*a,size - 1);//recursion
void print_int() {
int i; // Loop counter
for (i = 0; i < 4; i++) {
printf("%d\n", a[i]);
}}
}
It compiles ok but when I try to run the file nothing appears? My intentions were to create an array sort them then display them.
Also, the code where the recursion happened "sorting(*a,size - 1);//"
if I tried to replace *a with a[] an error will happen. Why is that?
the error is "error expected expression before ']' token"!
thank you.
int a[4];
But you access a[4]=19; index 4 that is out of bound. You can access highest index 3.
I think function void sorting() should be defined outside main .Nested functions are GNU extensions in GCC.
Your code has to many problems. Here is a working Array sort:
#include <stdio.h>
void bubble_sort(int *array, int length){
int i,j, k, temp;
for (i = 0 ; i < length-1; i++){
for (k = 0 ; k < length-i-1; k++){
if (array[k] > array[k+1]){
temp = array[k];
array[k] = array[k+1];
array[k+1] = temp;
}
}
}
printf("The sorted Array List:\n\n");
for ( j = 0 ; j < length ; j++ ){
printf("%d ", array[j]);
}
}
int main(void){
int array[] = {1,6,15,3,19};
int length = sizeof array / sizeof array[0];
bubble_sort(array, length);
printf("\n");
return 0;
}
You should read about functions declarations and definitions.
About arrays you should know that if you declare:
int array[4];
Your working array is from 0 to 3 and not from 0 to 4.
Take a look at the following:
int main(void){
int array[] = {1,6,15,3,19};
int size = 5;
int i;
for(i=0;i<size;i++){
printf("%d ",array[i]);
}
return 0;
}
I have size=5 and not size=4- like you tried. You should be careful about number of Array elements.
Aside from all the problems spotted by others, you must repeatedly execute the for loop until no more exchanges are made, which is the standad way of bubbling. As you use recursion, it is of course nonsense to declare the array to be sorted (and its size) inside the function called recursively.