Comparing arrays in a function - c

My function countCopies doesn't work even though it gets the right inputs. All it should do is taking an array of integers as an input and then searching through this array for duplicates of the second input x.
int main() {
char intArray[100]; //The integer array can only hold 100 integers
int i, x, j;
printf("Please enter a couple of integers and when you're done enter end. ");
i = 0;
while (scanf("%d", &intArray[i++]) == 1)
/*empty loop*/;
scanf("%*s");
printf("Enter x:");
scanf("%d", &x);
printf("Copies = %d\n", countCopies(intArray, i, x));
}
int countCopies(int a[], int n, int x) {
int count = 0;
int j = 0;
for (j = 0; j < n - 1; j++) {
if (a[j] == x) {
count++;
}
}
return count;
}

The for loop is incorrect: you should change the test to j < n.
The idiomatic for loop in C: for (j = 0; j < n; j++) ... iterates exactly n times, j taking values 0 to n-1 inclusively, which are correspond to exactly all valid positions in an array of n elements.
Note that the array has the wrong element type: it should be int, not char. You should also check for array bounds in the first loop and for conversion success of the last scanf.
Here is a corrected version:
#include <stdio.h>
int countCopies(int a[], int n, int x);
int main(void) {
int intArray[100]; //The integer array can only hold 100 integers
int i, x;
printf("Please enter a series of integers, end the list with the word end.\n");
for (i = 0; i < sizeof(intArray) / sizeof(*intArray); i++) {
if (scanf("%d", &intArray[i]) != 1)
break;
}
if (scanf("%d", &x) == 1) {
printf("too many numbers\n");
return 1;
}
scanf("%*s"); /* skip the end word. Note that any word is OK */
printf("Enter x:");
if (scanf("%d", &x) == 1) {
printf("Copies = %d\n", countCopies(intArray, i, x));
}
return 0;
}
int countCopies(int a[], int n, int x) {
int j, count = 0;
for (j = 0; j < n; j++) {
if (a[j] == x) {
count++;
}
}
return count;
}

To expand on chqrlie's answer,
The code for (i = 0; i < n; i++) {/* do stuff */} executes in the following order:
The variable i is set to zero.
The conditional i < n is tested. If true, the code in /* do stuff */ is executed, otherwise, the loop is exited.
The increment i++ is applied.
Go back to 2.
That means that on the loop iteration when i gets incremented to n, the for loop breaks before the code inside the loop gets executed, so if you're accessing an array with n elements, the last element that gets accessed has the index n - 1. Hence the C loop paradigm that chqrlie mentioned.

Related

Facing Runtime error while Solving finding and counting duplicates in c

Can someone please help me i am facing runtime error while solving this problem.
I have first defined the integers and then used scanf to take the input.
Then i check whether the 2 consecutive elements of array are equal are not.
if they are equal i equate j variable to i+1 and so that it can traverse and find if same duplicate elements are side by side (eg- 15 15 15).
I increment the j element till a[j] is equal to a[i].
Then using i try to print the number with the number of occurences of it which is j-i and then assign i with vakue of j-1.
#include <stdio.h>
int main()
{
int n,j=0,i;
scanf("%d",&n);
int a[n];
for (i = 0; i < n; ++i) {
scanf("%d",&a[i]);
}
for (i = 0; i < n - 1; ++i)
{
if(a[i]==a[i+1])
{
j=i+1;
while(j<n && a[i]==a[j])
{
j++;
}
printf("%d is appearing %d times\n",a[i],j-i);
}
i=j-1;
}
return 0;
}
The input array needs to be sorted first to count duplicated, the loop logic needs to be fixed to reassign the index i.
A fixed code might like this:
#include <stdio.h>
#include <stdlib.h>
static int cmp_intp(const void *p1, const void *p2) {
return *(const int *)p1 > *(const int *)p2;
}
int main() {
int n, j = 0, i;
scanf("%d", &n);
int a[n];
for (i = 0; i < n; ++i) {
scanf("%d", &a[i]);
}
qsort(a, n, sizeof(a[0]), cmp_intp);
for (i = 0; i < n;) {
if (i < n - 1 && a[i] == a[i + 1]) {
j = i + 1;
while (j < n && a[i] == a[j]) {
j++;
}
printf("%d is appearing %d times\n", a[i], j - i);
i = j;
} else {
++i;
}
}
return 0;
}
The problem is created by the line,
i=j-1;
in the case when two consecutive elements are not equal.
move it within the if condition.

Frequency of an Element Accruing In an Array

I am new to programming, I am trying to write a program that lets the user input numbers ranging from 0 to 1000, and the maximum number the user can input is 100. The numbers in the array don't have to be in order, and the program ends when the user inputs a negative number. After that, the program should determine which number occurs the most and the frequency of that occurrence.
I have written a similar code but not for this type of problem the code below showcases what I mean by similar code and any help would be appreciated
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
char again;
do {
srand(time(0));
int myNumbers[10];
int i, n, findnum, time, num;
n = 10;
for (i = 0; i < n; i++) {
myNumbers[i] = rand() % 10 + 1;
}
for (i = 0; i < n; i++) {
printf("elements %d\n", myNumbers[i]);
}
printf("Enter number to find Occurrence: ");
scanf("%d", &findnum);
time = 0;
for (i = 0; i < n; i++) {
if (myNumbers[i]==findnum)
time++;
}
if (findnum>0) {
printf("Occurrence of %d is: %d times\n",findnum,time);
} else {
printf("The number %d is not present in the array\n",num);
}
do {
printf("Shall we play again (y/n)?: ");
while(getchar()!='\n');
scanf("%c", &again);
}
while(again !='y' && again !='n');
}
while(again =='y');
}
You will need a second array to count the frequencies. Worst case, the user entered unique numbers, so the second array should be as large as myNumbers. The array will hold two values: the number, and its count:
int myNumbers[10];
int myCount [10][2] = {0};
int n= 10;
You remember the first entry of myCount that is available:
int m= 0;
You cycle over all numbers:
for (i = 0; i < n; i++){
For each number, you check if it is already in the myCount and if yes, increment the count and then exit the loop:
for (j = 0; j < m; j++){
if (myCount[j][0] == myNumbers[i]){
myCount[j][1]++;
break;
}
}
If the number was not found, you add it:
if (j == m) {
myCount[m][0] = myNumbers[i];
myCount[m][1] = 1;
m++;
}
}
Now you can search the array for the number with the highest count.
Integrated the code is:
int myNumbers[10];
int myCount [10][2] = {0};
int n= 10;
int m= 0;
/* now fist read the input */
for (i = 0; i < n; i++){
for (j = 0; j < m; j++){
if (myCount[j][0] == myNumbers[i]){
myCount[j][1]++;
break;
}
}
if (j == m) {
myCount[m][0] = myNumbers[i];
myCount[m][1] = 1;
m++;
}
}
To do: search the array for the number with the highest count.

I want to print the number of times an element is repeated in an array of random numbers in C

Hi wanted to display repeated elements of a Random array whose size can be specified by the user. The problem I am getting in the output is , the function is printing a repeated number as many times as it has been repeated but I want to print it only once.
Here is my code and output following the former:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int array_size = 0;
int *my_array;
int i = 0;
printf("Enter the size of the array:\n");
scanf("%d",&array_size);
my_array = malloc(array_size * sizeof my_array[0]);
if(NULL == my_array) {
fprintf(stderr,"MEMORY ALLOLCATION FAILED \n");
return EXIT_FAILURE;
}
for(i=0;i<array_size;i++){
my_array[i] = rand()%array_size;
}
printf("What's in the array:\n");
for(i = 0;i<array_size;i++){
printf("%d ",my_array[i]);
}
printf("\n");
display_repeats(my_array, array_size);
free(my_array);
return EXIT_SUCCESS;
}
void display_repeats(int *a,int n){
int *repeats;
repeats = malloc(n * sizeof repeats[0]);
int i=0;
int j=0;
int count = 0;
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(a[i] == a[j]){
count++;
}
}
if(count>1){
repeats[i] = count;
printf("%d occurs %d times\n",a[i],repeats[i]);
}
count = 0;
}
free(repeats);
}
Here is the output I am getting
Enter the size of the array:
5
What's in the array:
3 1 2 0 3
3 occurs 2 times
3 occurs 2 times
I want "3 occurs 2 times" to print once.
Please help!
What's happening is that your code realizes 3 is repeated twice, in this block:
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(a[i] == a[j]){
count++;
}
}
if(count>1){
repeats[i] = count;
printf("%d occurs %d times\n",a[i],repeats[i]);
}
}
When i is equal to 0, it will look at the array and realize that 3 is repeated, so count>1 will be true. Then, when i is equal to 4, count>1 will be true again, and you get the double print.
In order to fix this, I would create an array that stores the numbers that have already been verified as repeated and check against that.
Since in your case, value of elements < size_array, so can take this approach.
memset(repeats, 0, n*sizeof(repeats[0]));
for(i=0;i<n;i++){
for(j=0;j<n;j++){
count = repeats[a[i]];
if(count>0)
break;
if(a[i] == a[j]){
count++;
}
}
repeats[a[i]] = count;
The idea is to store the count for each value and check before starting search for each new value to check if it has already been counted.
Try it:
for(i=0;i<n-1;i++)
{
for(j=1;j<n;j++)
{
So, don't compare the same one element with itself.
Thanks guys I got it working with the above ideas!
here is what I got..
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int array_size = 0;
int *my_array;
int i = 0;
printf("Enter the size of the array:\n");
scanf("%d",&array_size);
my_array = malloc(array_size * sizeof my_array[0]);
if(NULL == my_array) {
fprintf(stderr,"MEMORY ALLOLCATION FAILED \n");
return EXIT_FAILURE;
}
for(i=0;i<array_size;i++){
my_array[i] = rand()%array_size;
}
printf("What's in the array:\n");
for(i = 0;i<array_size;i++){
printf("%d ",my_array[i]);
}
printf("\n");
display_repeats(my_array, array_size);
free(my_array);
return EXIT_SUCCESS;
}
void display_repeats(int *a,int n){
int *freq;
freq = malloc(n * sizeof freq[0]);
int i=0;
int j=0;
int count = 0;
for(i=0;i<n;i++){
freq[i] = -1;
}
for(i=0;i<n;i++){
count = 1;
for(j=i+1;j<n;j++){
if(a[i]==a[j]){
count++;
freq[j] = 0;
}
}
if(freq[i]!=0){
freq[i] = count;
}
}
for(i=0;i<n;i++){
if(freq[i]!=1 && freq[i]!=0){
printf("%d occurs %d times\n",a[i],freq[i]);
}
}
free(freq);
}
In display_repeats(), you may simply update 2 lines and add 3 lines to make your program have the correct behaviour. And we will see it later: we can optimize the final code using C99 syntax and the comma C operator, to write far less lines than your original code (9 lines instead of 20 lines!).
So, in this answer, you will find how to get the final code that has the correct behaviour and is very short, shorter than your initial code:
void display_repeats(int *a, int n) {
for (int i = 0; i < n; i++) {
if (a[i] == -1) continue;
int count = 1;
for (int j = i + 1; j < n; j++)
if (a[i] == a[j]) count++, a[j] = -1;
if (count > 1) printf("%d occurs %d times\n", a[i], count);
}
}
The idea is to set to -1 each array value that has matched a previous one, just after the count increment. Because you do not want to count this value again.
So simply do the following:
In the two lines where you write count = 0, replace 0 by 1, because you are sure that each number in the list must be counted at least one time.
This way, you can avoid checking the case where i equals j in the inner loop: it is already taken into account in count. So add if (i == j) continue; at the beginning of the inner loop.
With the previous updates, you are now sure that when you increment count, in the inner loop, j is not equal to i. Therefore, you can change the value of a[j] without changing a[i], in the array.
So, add a[j] = -1; just after having increased count. This way, when i will be incremented to check for a new count of a new value, it is impossible that the new counted value has already been counted.
Finally, you do not want to count how many times -1 is in the array. But you have replaced some values with -1. So simply add if (a[i] == -1) continue; at the beginning of the outer loop to avoid counting how -1 there are in the array.
This intermediate code is:
void display_repeats(int *a,int n) {
int *repeats;
repeats = malloc(n * sizeof repeats[0]);
int i=0;
int j=0;
int count = 1;
for(i=0; i<n; i++) {
if (a[i] == -1) continue;
for(j=0; j<n; j++) {
if (i == j) continue;
if(a[i] == a[j]) {
count++;
a[j] = -1;
}
}
if(count > 1) {
repeats[i] = count;
printf("%d occurs %d times\n",a[i],repeats[i]);
}
count = 1;
}
free(repeats);
}
Now, we can optimize this code.
First, we can avoid testing a[i] == a[j] when j <= i: if such a case happens, we know that we have previously displayed the count for a[j] (the number of times a[j] appears in the array). Therefore we can replace for (j=0; j < n; j++) { by for (j=i+1; j<n; j++) {.
With this last update, we know that the first line of the inner loop will never match: i can not be equal to j. So we can remove this line (if (i == j) continue;).
Note that the values stored in the repeats array are only used to get the value of count in the printf() call. So we can remove every reference to the repeats array and simply use count in the printf() call.
Now, you can see that we set count to 1, two times. We can do it only one time, if we do not set it to 1 at the end of the main loop, to prepare a new loop, but at the beginning.
Now, note that i, j and count have the same type, so only one line may be used to define them: int i = 0, j = 0, count = 1;. More over, i and j are defined later in the for loops, so no need to define their initial value here. So we can simply write int i, j, count = 1;. But count is now defined at the beginning of the outer loop, so we do not need to define it previously. So we only need to define i, j and count without an initial value: int i, j, count;.
The new intermediate code is:
void display_repeats(int *a, int n) {
int i, j, count;
for (i = 0; i < n; i++) {
if (a[i] == -1) continue;
count = 1;
for(j = i + 1; j < n; j++) {
if (a[i] == a[j]) {
count++;
a[j] = -1;
}
}
if (count > 1) printf("%d occurs %d times\n", a[i], count);
}
}
Using C99 syntax
But we can do more, using the C99 specification: we can define a variable with the for instruction: we can write for (int i = ...). No more need to define it previously. So we can avoid having to write int i, j, count;, we will define them at first use:
void display_repeats(int *a, int n) {
for (int i = 0; i < n; i++) {
if (a[i] == -1) continue;
int count = 1;
for(int j = i + 1; j < n; j++) {
if (a[i] == a[j]) {
count++;
a[j] = -1;
}
}
if (count > 1) printf("%d occurs %d times\n", a[i], count);
}
}
Using the comma C operator
Again, we can do much better! We can use the comma operator (,): it is a binary operator that evaluates its first operand, discards the result, evaluates the second operand and returns its value. Using the comma operator, we can transform count++; a[j] = -1; to a single instruction: a[j] = (count++, -1). But we can avoid the parenthesis writing count++, a[i] = -1. Now, we do not need a block for the if statement, since there is only one instruction. Therefore, we can remove a lot of parenthesis.
The final code is:
void display_repeats(int *a, int n) {
for (int i = 0; i < n; i++) {
if (a[i] == -1) continue;
int count = 1;
for (int j = i + 1; j < n; j++)
if (a[i] == a[j]) count++, a[j] = -1;
if (count > 1) printf("%d occurs %d times\n", a[i], count);
}
}

Copying elements from an array to another one and counting the number of a character in C

I'm new to C, so I apologize for asking silly questions.
I need to copy certain elements from an array to another one, but I can't make it work and get random numbers instead. In this case I need all the elements after the smallest one from the first array to be copied to the second one.
The other thing I can't figure out is a function that counts how many times a certain symbol is used. I need to find the number of times I've used the biggest odd digit in an array.
Here's the code, I've made so far. I hope you understand most of it:
#include <stdio.h>
#define DIM 100
int enter (int x[]);
int min (int x[], int y[], int n);
int sort (int x[], int n);
void print (int x[], int n);
//=============================================
int main () {
int a[DIM], b[DIM], n, i;
n = enter (a);
printf("The smallest element in the first array: %d.\n The smallest element in the second array: %d.\n", min (a, b, n));
printf("%d\n", sort (b, n));
for (i = 0; i < n; i++)
printf ("%d ", b[i]);
printf ("\n");
system("pause");
return 0;
}
//===========================================================
int enter (int x[]) {
int i, n;
do {
printf ("Enter number of elements in array: ");
scanf ("%d", &n);
}
while (n < 1 || n > DIM);
printf ("Enter %d elements:\n", n);
for (i = 0; i < n; i++)
scanf ("%d", &x[i]);
return x[i], n;
}
int min (int x[], int y[], int n) {
int minimum, i, j=0, p;
minimum = x[0];
for ( i = 1 ; i < n ; i++ ) {
if ( x[i] < minimum ) {
minimum = x[i];
p = i+1;
}
}
for (i = p+1; i<n; i++ && j++) {
x[i] = y[j];
}
return minimum;
}
int sort (int x[], int n) {
int i, j, a;
for (i = 0; i < n; ++i) {
for (j = i + 1; j < n; ++j) {
if (x[i] > x[j]){
a = x[i];
x[i] = x[j];
x[j] = a;
}
}
}
printf("Elements from array in ascending order: \n");
for (i = 0; i < n; ++i)
printf("%d\n", x[i]);
return x[i];
}
I need to find the number of times I've used the biggest odd digit in
an array.
Fist sort your array start at the end and find the biggest odd number. You can find a odd number by number%2==1. Finally count equal numbers:
// sort the array
sort(b, n); // sort function from your questions code
// find the biggest odd number
int i = n-1;
while ( i >= 0 && b[i]%2 == 0 )
{
i --;
}
// count the biggest odd number
count = 0;
int j = i;
while ( j >= 0 && b[i]==b[j] ) // note first time i==j !
{
count ++;
j --;
}
If you don't want to sort your array use this:
// find the biggest odd number
int oddInx = -1;
for ( int i = 0; i < n; i++ )
{
if ( b[i]%2 == 1 && ( oddInx < 0 || b[i] > b[oddInx] ) )
oddInx = i;
}
// count the biggest odd number
count = 0;
if ( oddInx >= 0 )
{
for ( int i = 0; i < n; i++ )
{
if ( b[i] == b[oddInx] )
count ++;
}
}

Error in function for Selection-Sort

My code for selection-sort
#include <stdio.h>
void selection_sort(int a[], int n);
int main()
{
int size;
printf("Enter the size of array: ");
scanf("%d",&size);
int b[size],i = 0;
printf("Enter %d integers to be sorted: ",size);
while(i++ < size)
scanf("%d",&b[i]);
selection_sort(b, size);
printf("Sorted integers(by selection sort) are: ");
for(int i = 0; i < size; i++)
printf("%d",b[i]);
return 0;
}
void selection_sort(int a[], int n)
{
while(n >= 0 )
{
if(n == 0)
break;
else
{
int i = 0, c = 0;
int largest = a[0];
while(i++ < n)
if(largest < a[i])
{
c = i ;
largest = a[i];
}
int temp = a[--n];
a[n] = largest;
a[c] = temp;
selection_sort(a, n);
}
}
}
on sorting the array in ascending order
3 4 1 2
is giving weird output
2293388 4 3 0
I checked this many time but failed to remove the problem.
What should I do to work it properly?
Algorithm used :
1. search for largest element in the array.
2. Move largest element to the last position of array.
3. Call itself recursively to sort the first n -1 element of the array.
Please don't give any other solution otherwise I will get confused.
EDIT
Ah, I see what goes wrong. First of all, while (i++ < n) does not do exactly what you expect it to do. It checks if the condition i < n is true, then it increments i. However, it seems that after the conditional check, i is already incremented in the body. So for example,
while (i++ < n)
printf ("%d ", i);
will print out (with n=4):
1 2 3 4
So you first need to change that. Secondly, the outer while-loop is not at all necessary. Using one loop will suffice. Again, change the while loop in here to while (i < n) and increment i in the body. SO the final code will be:
#include <stdio.h>
void selection_sort(int a[], int n);
int main()
{
int size;
printf("Enter the size of array: ");
scanf("%d", &size);
int b[size], i = 0;
printf("Enter %d integers to be sorted: ", size);
while(i < size) {
scanf("%d", &b[i]);
i++;
}
selection_sort(b, size);
printf("Sorted integers(by selection sort) are: ");
i = 0;
for(i = 0; i < size; i++)
printf("%d ", b[i]);
printf ("\n");
return 0;
}
void selection_sort(int a[], int n)
{
if(n == 0)
return;
else
{
int i = 0, c = 0;
int largest = a[0];
while(i < n) {
if(largest < a[i])
{
c = i;
largest = a[i];
}
i++;
}
int temp = a[--n];
a[n] = a[c];
a[c] = temp;
selection_sort(a, n);
}
}
I tested this with your given input (3 4 1 2) and it prints out a sorted list: 1 2 3 4.
Whenever you see such weird big numbers, its usually an array out of bounds issue. Please take a small data-set, say 5-6 numbers, and walk through your program. I am sure you can fix it. Good luck!!

Resources