I was working on the following 2d-array program to output this result shown in picture:
I can't seem to get the min value for the result and get it displayed in array form.
The code is below:
#include<stdio.h>
#define NUMROWS 2
#define NUMCOLS 3
//accessing elements of 2D array using pointers
int main(void){
const int table[NUMROWS][NUMCOLS]={{1,2,3},{5,6,7}};
int minvals[NUMROWS];
int i, j;
int *ptr = &table;
//accessing the elements of 2D array using ptr
printf("table values: min value\n");
for(int i=0;i<NUMROWS;i++){
for(int j=0;j<NUMCOLS;j++)
printf("%d ",*((ptr+i*NUMCOLS)+j));
printf("\n");
}
for(int i=0;i<NUMROWS;i++){
for(int j=0;j<NUMCOLS;j++)
printf("%d ",*((ptr+i*NUMCOLS)+j)<minvals[i]);
}
return 0;
}
The existence of minvals would imply that you are expected to calculate the minimum value of each 'row' of table before then moving on to printing. As it stands, had your program properly calculated the minimum values of each array, your printing would be rather out of order.
There's no need to do any tricky, manual pointer manipulation. Simple array subscription is much clearer.
Let's start simple and return to basics by looking at the way we find the minimum value in a one dimensional array, as it is the core of this problem.
To find the minimum value in an array we need a few things to start:
An array
The length of the array
An initial value to compare against
The array itself is obviously each subarray of table, and the length in this case is known to be NUMCOLS. Our initial value should either be INT_MAX (or another type-appropriate maximum constant found <limits.h>), such that every element in the array is equal to or less than our initial value, or a value from the array itself.
Often times we opt for the second option here, choosing the first element in the array as our initial value, and comparing it to the second and onward elements.
As such, finding the minimum value in a single 'row' would look like this
const int row[NUMCOLS] = { 9, 2, 5 };
int min = row[0];
for (int i = 1; i < NUMCOLS; i++)
if (row[i] < min)
min = row[i];
but since we want to find and record the minimum value of each 'row' in table, we're going to use a nested loop. Instead of the min variable from before, we store each value in the associated index of our minvals array.
for (i = 0; i < NUMROWS; i++) {
minvals[i] = table[i][0];
for (j = 1; j < NUMCOLS; j++)
if (table[i][j] < minvals[i])
minvals[i] = table[i][j];
}
When it comes time to print, we're going to repeat our nested loop. Our inner loop prints each element of each 'row' of table, and we end each iteration of the outer loop by printing the value found in minvals with the same index of our 'row'.
for (i = 0; i < NUMROWS; i++) {
for (j = 0; j < NUMCOLS; j++)
printf("%6d", table[i][j]);
printf(":%6d\n", minvals[i]);
}
Here's a working example.
#include <stdio.h>
#define NUMROWS 2
#define NUMCOLS 3
int main(void) {
const int table[NUMROWS][NUMCOLS] = {
{ 9, 2, 5 },
{ 3, -4, -12 }
};
int minvals[NUMROWS];
int i, j;
for (i = 0; i < NUMROWS; i++) {
minvals[i] = table[i][0];
for (j = 1; j < NUMCOLS; j++)
if (table[i][j] < minvals[i])
minvals[i] = table[i][j];
}
puts("Table value: minimum values");
for (i = 0; i < NUMROWS; i++) {
for (j = 0; j < NUMCOLS; j++)
printf("%6d", table[i][j]);
printf(":%6d\n", minvals[i]);
}
}
A good further exercise for you would be to compose the logic of the inner loop for finding minimum values into a more generic function. Its function signature would look like
int min(int *array, size_t length);
allowing it to work on arrays of varying sizes. Then our outer loop could be as simple as:
for (i = 0; i < NUMROWS; i++)
minvals[i] = min(table[i], NUMCOLS);
The line
int *ptr = &table;
is wrong, because &table is of type int (*)[2][3] (i.e. a pointer to the entire table), whereas ptr is a pointer to a single element. Also, your pointer is non-const, so it cannot point be made to point into a const array.
If you want ptr to point to a single int value, then you should declare it the following way:
const int *ptr = &table[0][0];
Also, you are reading the contents of the array minvals, although that array contains uninitialized data. This does not make sense and causes undefined behavior.
Instead of doing complex pointer arithmetic with the expression
*((ptr+i*NUMCOLS)+j))
you can simply write the following:
table[i][j]
That way, you do not need the pointer ptr and your code is simpler.
Related
I have to find all of the elements which have the maximum frequency. For example, if array a={1,2,3,1,2,4}, I have to print as 1, also 2. My code prints only 2. How to print the second one?
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define n 6
int main(){
int a[n]={1,2,3,1,2,4};
int counter=0,mostFreq=-1,maxcnt=0;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
if(a[i]==a[j]){
counter++;
}
}
if(counter>maxcnt){
maxcnt=counter;
mostFreq=a[i];
}
}
printf("The most frequent element is: %d",mostFreq);
}
How to print the second one?
The goal it not only to print a potential 2nd one, but all the all of the elements which have the maximum frequency.
OP already has code that determines the maximum frequency. Let us build on that. Save it as int target = mostFreq;.
Instead of printing mostFreq, a simple (still O(n*n)) approach would perform the same 2-nested for() loops again. Replace this 2nd:
if(counter>maxcnt){
maxcnt=counter;
mostFreq=a[i];
}
With:
if(counter == target){
; // TBD code: print the a[i] and counter.
}
For large n, a more efficient approach would sort a[] (research qsort()). Then walk the sorted a[] twice, first time finding the maximum frequency and the 2nd time printing values that match this frequency.
This is O(n* log n) in time and O(n) in memory (if a copy of the original array needed to preserve the original). If also works well with negative values or if we change the type of a[] from int to long long, double, etc.
The standard student solution to such problems would be this:
Make a second array called frequency, of the same size as the maximum value occurring in your data.
Init this array to zero.
Each time you encounter a value in the data, use that value as an index to access the frequency array, then increment the corresponding frequency by 1. For example freq[value]++;.
When done, search through the frequency array for the largest number(s). Optionally, you could sort it.
We can (potentially) save some effort in an approach with unsorted data by creating an array of boolean flags to determine whether we need to count an element at all.
For the array {1, 2, 3, 1, 2, 4} we do have nested for loops, so O(n) complexity, but we can avoid the inner loop entirely for repeated numbers.
#include <stdio.h>
#include <stdbool.h>
int main(void) {
int arr[] = {1, 2, 3, 1, 2, 4};
size_t arr_size = sizeof(arr) / sizeof(*arr);
bool checked[arr_size];
for (size_t i = 0; i < arr_size; i++) checked[i] = false;
unsigned int counts[arr_size];
for (size_t i = 0; i < arr_size; i++) counts[i] = 0;
for (size_t i = 0; i < arr_size; i++) {
if (!checked[i]) {
checked[i] = true;
counts[i]++;
for (size_t j = i+1; j < arr_size; j++) {
if (arr[i] == arr[j]) {
checked[j] = true;
counts[i]++;
}
}
}
}
unsigned int max = 0;
for (size_t i = 0; i < arr_size; i++) {
if (counts[i] > max) max = counts[i];
}
for (size_t i = 0; i < arr_size; i++) {
if (counts[i] == max)
printf("%d\n", arr[i]);
}
return 0;
}
Im stuck with a piece of my Arduino code
Basically I have a multi dimensional array in which every index will store a random letter. But after a small time (eg. 900 milliseconds) every value in the index will move up to the index above it. Ofcourse when the index reaches e.g. [9][0] it will go to the largest index like [9][9]
E.g.: myArray[9][8] contains "K" and myArray[9][7] contains "L"
The "K" in myArray[9][8] will be put in myArray[9][7] and the "L" in myArray[9][7] will go to myArray[9][6] etc. etc
But I have no clue how to do this in C...
myArray[9][8] = myArray[9][7] obviously wouldnt work
There is not problem with assignment, but you must save the element you are writing over first.
In this example all the rewritten values are kept in the last slot of every row, this is just an example- not the only way to go, if you need to move the letters across the rows as well the idea is similar.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void moveLettersInRow(char sArr[][3], int row)
{
int i = 0;
int j = 0;
char temp ;
for (i = 0; i < row; ++i)
{
for(j = 2 ;j > 0;--j)
{
temp = sArr[i][j-1]; /*save the value to be rewritten */
sArr[i][j-1]= sArr[i][2]; /* set the last val in its new place*/
sArr[i][2]= temp; /* set the last elem to the latest rewritten value*/
}
}
}
void printArr(char arr[][3], int size)
{
int i = 0, j= 0;
for(i = 0; i< size; ++i)
{
for(j = 0; j< 3; ++j)
{
printf("%c | ", arr[i][j]);
}
printf("\n");
}
}
int main()
{
char arr[2][3]= {{'a','b','c'},{'a','b','c'}};
moveLettersInRow(arr, 2);
printArr(arr, 2);
return 0;
}
There are several ways to go about this. One would be to use a temporary variable while copying, as Kami Cuk and Fred pointed out.
Another way, which would avoid copying the values, would be to index the array using a modulo operation while reading the array.
myArray[9][(index + offset) % numberOfElementsInArray]
index and offset should both be positive integers.
numberOfElementsInArray is the number of elements in myArray[9]
To get a -1 offset with a positive integer, set offset to numberOfElementsInArray - 1
I created an array called elements_n which has the elements 0 to N-1 where N is 2. The below numbers are the elements of the array called elements_n:
0 1
I have another array called Arr which has the following elements:
0 1 3 1 2 4
If any of the first 3 elements of the array Arr are equal to the first element of elements_n which is 0, I would like to delete that element from the array called Arr. I then repeat the same process for the next 3 elements of the array Arr. So to explain myself better, I will use the following example:
Compare the first 3 elements of array Arr which are 0, 1, 3 to the first element of elements_n which is 0. Since Arr[0] == elements_n[0]. I delete Arr[0] from the array Arr.
Compare the next 3 elements of array Arr which are 1, 2, 4 to the second element of elements_n which is 1. Since Arr[3] == elements_n[1]. I delete Arr[3] from the array Arr. So the elements that should be left in the array Arr are:
1 3 2 4
When I implemented it myself in C programming with the code found below the end result is coming:
1 3 3 2 2 4
Rather than:
1 3 2 4
This is the code I implemented:
#include <stdio.h>
#include <stdlib.h>
#define N 2
int main() {
unsigned *elements_n = malloc(N * sizeof(unsigned));
for (int i = 0; i < N; i++) {
elements_n[i] = i; //Created an array which has the elements 0 to N-1
}
printf("\n");
unsigned Arr[6] = { 0, 1, 3, 1, 2, 4 };
unsigned position_indices[2] = { 3, 3 }; //Moving every 3 elements in the Arr array.
int count = 0;
int index = 0;
unsigned *ptr_Arr = &Arr[0];
do {
for (int i = 0; i < position_indices[count]; i++) {
if (ptr_Arr[i] == elements_n[count]) {
index = i + 1; //Index of the Arr element that has the same value as the element in the array elements_n
for (int j = index - 1; j < position_indices[count] - 1; j++) {
ptr_Arr[j] = ptr_Arr[j + 1];
}
}
}
printf("\n");
ptr_Arr += position_indices[count] - 1;
count++;
} while (count < 2);
for (int i = 0; i < 6; i++) {
printf("%d\t", Arr[i]);
}
printf("\n");
free(elements_n);
return 0;
}
You might try something like this (not tested).
#include <stdio.h>
#include <stdlib.h>
#define N 2
int main()
{
unsigned *elements_n = malloc(N * sizeof(unsigned));
for (int i = 0; i < N; i++)
{
elements_n[i] = i; //Created an array which has the elements 0 to N-1
}
unsigned Arr[6] = { 0, 1, 3, 1, 2, 4 };
int dest_index = 0;
int src_index = 0;
int count = sizeof(Arr)/sizeof(Arr[0]);
for ( ; src_index < count; src_index++)
{
int group = src_index / 3;
if (Arr[src_index] != elements_n[group])
{
Arr[dest_index++] = Arr[src_index];
}
}
for (int i = 0; i < dest_index; i++)
{
printf("%d\t", Arr[i]);
}
printf("\n");
free(elements_n);
return 0;
}
You need to keep track of how many elements you removed from the array.
My solution:
#include <stdio.h>
#include <stddef.h>
#include <assert.h>
#include <string.h>
size_t fancy_delete_3(const int elems[], size_t elemssize, int arr[], size_t arrsize)
{
assert(elems != NULL);
assert(arr != NULL);
assert(arrsize%3 == 0);
assert(elemssize*3 == arrsize);
// we need to count the removed elements, to know how much we need to shift left
size_t removed = 0;
// for each element in elems
for (size_t i = 0; i < elemssize; ++i) {
// check the three correponding elements in arr
for (size_t j = i*3; j < (i+1)*3; ++j) {
assert(j >= removed);
const size_t pos = j - removed;
// if elems[i] matches any of the corresponding element in arr
if (elems[i] == arr[pos]) {
// remove element at position pos
assert(arrsize >= pos + 1);
// I don't think this can ever overflow
memmove(&arr[pos], &arr[pos + 1], (arrsize - pos - 1) * sizeof(int));
++removed;
// array is one element shorter, so we can just decrease the array size
assert(arrsize > 0);
--arrsize;
}
}
}
// we return the new size of the array
return arrsize;
}
#define __arraycount(x) sizeof(x)/sizeof(x[0])
int main()
{
int elements_n[] = {0,1};
int arr[] = {0,1,3, 1,2,4};
size_t newsize = fancy_delete_3(elements_n, __arraycount(elements_n), arr, __arraycount(arr));
printf("arr size=%zu {", newsize);
for (size_t i = 0; i < newsize; ++i)
printf("%d,", arr[i]);
printf("}\n");
return 0;
}
You have several related problems around how you perform deletions. In the first place, it's not clear that you understand that you cannot actually delete anything from a C array. The closest you can come is to overwrite it with something else. Often, pseudo-deletion from an array is implemented by moving each of the elements following the deleted one one position forward, and reducing the logical length of the array.* You seem to have chosen this alternative, but (problem 1) you miss maintaining or updating a logical array length.
Your problem is made a bit more complicated by the fact that you logically subdivide your array into segments, and you seem not to appreciate that your segments are variable-length in that, as described, they shrink when you delete an element. This follows from the fact that deleting an element from one group does not change the assignments of elements to other groups. You do have a mechanism in position_groups that apparently serves to track the sizes of the groups, and in that sense its name seems ill-fitting. In the same way that you need to track and update the logical length of the overall array, you'll need to track and update the lengths of the groups.
Finally, you appear to have an off-by-one error here:
for (int j = index - 1; j < position_indices[count]-1; j++)
that would be clearer if position_indices were better named (see above), but recognizing that what it actually contains is the size of each group, and that index and j represent indices within the group, it follows that the boundary condition for the iteration should instead be just j < position_indices[count]. That's moot, however, because you're going to need a somewhat different approach here anyway.
Suggestion, then:
When you delete an element from a group, move up the entire tail of the array, not just the tail of the group.
In service to that, update both group size and logical array size when you perform a deletion, remembering that that affects also where each subsequent group starts.
When you examine or output the result, remember to disregard array elements past the logical end of the array.
* "Logical array size" means the number of (leading) elements that contain meaningful data. In your case, the logical array size is initially the same as the physical array size, but each time you delete an element (and therefore move up the tail) you reduce the logical size by one.
You never really "deleted" any element, you just shifted-down the
second and third elements from each 3-group. And then, when
printing, you iterated over the whole array.
Arrays are just continuous blocks of memory, so you need a
different strategy. You could traverse the original array with
two indexes, one as the general index counter and other as
the index for the shifted slot. If the current element is
different from the corresponding elements_n item, copy it to
the secondary index and increase it.
In case nothing is equal to the elements_n item, you would just
reassign the array elements to themselves. However, as soon as
one is equal you will be shifting them with the advantage of
keeping track of the new size.
Also, calculating the corresponding elements_n item is a simple
matter of dividing the current index by 3, so you don't even need
an extra variable to that.
#include <stdio.h>
#define N 2
int main()
{
unsigned elements_n[N] = { 0, 1 };
unsigned Arr[N*3] = { 0, 1, 3, 1, 2, 4 };
int i, j;
for (i = 0, j = 0; i < N*3; i++)
if (Arr[i] != elements_n[i/3])
Arr[j++] = Arr[i];
for (i = 0; i < j; i++)
printf(" %d", Arr[i]);
printf("\n");
return 0;
}
I wrote a brief piece of code. It has two functions: bubbleSort is a bubble sorting function (smallest to largest), and "int main" is used to test this piece of code with an int array of size 5.
I'd like this to destructively sort the array, and not simply pass through a copy. I have looked and looked, but I am still not entirely clear how this should work. What am I missing here?
#include <stdio.h>
void bubbleSort(int values[], int n);
int main(void) {
//set simple test array to make sure bubbleSort works
int arr[5] = {5,4,3,2,1};
//run it through function, and then print the now sorted array to make sure
bubbleSort(arr, 5);
printf("%i", arr);
return 0;
}
void bubbleSort(int values[], int n)
{
for (int i = 0; i < n; i++) {
for (int j = 0, hold = 0; j < n-i; j++) {
if (values[j] > values[j+1]) {
hold = values[j+1];
values[j+1] = values[j];
values[j] = hold;
}
}
}
return;
}
Note: The rest of my code looks sound to my amateur coding mind, but please give me pointers on what i can improve, what can be better, etc. I thought about using recursion for the bubble sort but i'm not yet as comfortable with C as I'd like to be to implement that. However if you have suggestions i'll be more than happy to read them.
thanks!
Looks like your function is sorting the array (although with some bugs) and you are just printing the result incorrectly. printf doesn't know how to print arrays. Instead, you need to use a loop to print each integer one at a time:
for(int i=0; i<5; i++){
printf("%d ", arr[i]);
}
printf("\n");
After changing this, the output is 1 2 3 4 5, as expected.
However, as mentioned in the comments, there are some bugs in the implementation of the bubblesort. For example, it tries to read elements from indedex after the end of the array, which is undefined behavior (namely, j+1 can be 5, which is out of bounds). I would recommend checking your book again to get a correct implementation of bubblesort.
There is one issue in you bubble sort code which must be fixed. Your inner loop has the issue:
/* for (int j = 0, hold = 0; j < n-i; j++) { */ // ISSUE here
for (int j = 0, hold = 0; j < n-i-1; j++) { // j < n-i-1 should be the condition
This is becasue, take the case of when i = 0, i.e. the first iterartion of outer for loop. This time, j < n - i will be true when j is one less than n - which is the last index of your array. Then you do comaprision between values[j] and values[j+1], where values[j+1] is clearly out of bound of your array. This will invoke undefined behavior, and your function will not give deterministic results.
Next improvement could be that your outer loop only needs to iterate from i = 0 till i < n-1, i.e. one times less than the total elements. You are interating one time more than needed.
Third, you can use a flag to keep track of weather you swap at least once in your inner loop. If there there are no swaps in inner loop then it means that array is already sorted. So at the end of each iteration of inner loop you can see if any swap was done, and if no swaps were done then break out of the outer loop. This will improve performance in cases where array is already almost sorted.
void bubbleSort(int values[], int n)
{
int swap; // To use as a flag
// for (int i = 0; i < n; i++) {
for (int i = 0; i < n-1; i++) {
swap = 0; // set swap flag to zero
// for (int j = 0, hold = 0; j < n-i; j++) {
for (int j = 0, hold = 0; j < n-i-1; j++) {
if (values[j] > values[j+1]) {
hold = values[j+1];
values[j+1] = values[j];
values[j] = hold;
swap = 1; // swap was done
}
}
if (swap == 0) // If no swap was done
break; // Means array already sorted
}
return;
}
And, although not related to your sorting function, as others have pointed out, printf("%i", arr); is wrong, and will invoke undefined behavior because you are using a wrong format specifier in printf. It seems like you are trying to print the array. For that you can do:
// printf("%i", arr);
for (int i = 0; i < 5; i++)
printf("%d ", arr[i];)
printf("\n");
Your code already sorts the array in-place - although there is a bug in it. I'll address the subject of the question only (in-place sorting of an array in C) as comments have already highlighted the bugs with the sort function.
The print-out of the result is incorrect though as it tries to print the arr pointer as an integer:
sort.c:10:18: warning: format specifies type 'int' but the argument has type 'int *' [-Wformat]
printf("%i", arr);
~~ ^~~
1 warning generated.
However changing this to:
for (int i = 0; i < 5; i++)
printf("%i", arr[i]);
fixes the problem with the output.
Perhaps your confusion comes from how arrays are actually a syntactic way to access pointers in C. arr is a pointer. arr[1] is the same as *(arr + 1) (the contents of the pointer arr + 1 using pointer arithmetic, which increments the pointer by the sizeof the type). So when you pass arr into the function, you are passing a pointer to the existing array, then you are modifying its contents, sorting the array in-place.
So, I'm just working on C code, particularly a function which accepts 3 arguments: an array, the size of the array, and the number of max elements you want returned.
Here's my code:
int* findMaxElements(int base_array[],int size_of_base_array, int number_of_elements_to_find);
int main( void )
{
printf("Find Max Values in an Array\n\n");
// Set up array
int kinch[6] = {1,2,3,4,5,6};
// Pass to function and get a pointer to new array filled with only the max elements
int *given = findMaxElements(kinch,6,3);
for(int i = 0; i < 3; i++)
{
printf("\nMax Value = %d\n", *(given + i));
}
return 0;
}
int* findMaxElements(int base_array[],int size_of_base_array, int number_of_elements_to_find)
{
// Set up all initial variables
int i,k,c,position;
int maximum = 0;
int returnArray[100];
/*Actual Algorythm */
for(i = 0; i < number_of_elements_to_find; i++)
{
// Get the max value in the base array
for(k = 0; k < size_of_base_array; k++)
{
if(base_array[k] > maximum)
{
maximum = base_array[k];
}
}
// Find the position of the max value
for(position = 0; position < size_of_base_array; position++)
{
if(base_array[position] == maximum)
{
break;
}
}
// Delete the maximum value from the array and shift everything
for(c = position - 1; c < size_of_base_array - 1; c++)
{
base_array[c] = base_array[c+1];
}
// Reduce the size of the array
size_of_base_array -= 1;
// Push max value into return array
returnArray[i] = maximum;
// Reset max value
maximum = 0;
}
return returnArray;
}
I have a feeling somewhere in the function something goes wrong.
// Set up array
int kinch[6] = {1,2,3,4,5,6};
// Pass to function and get a pointer to new array filled with only the max elements
int *given = findMaxElements(kinch,6,3);
for(int i = 0; i < 3; i++)
{
printf("\nMax Value = %d\n", *(given + i));
}
This should output the numbers 6, 5, and 4, because they are the three largest in the array, however the output I get is always 6, 6, and 6. What's wrong with it?
This may not be your only problem, but in the lines
for(c = position - 1; c < size_of_base_array - 1; c++)
{
base_array[c] = base_array[c+1];
}
You copy the element at [c+1] (which is the maximum) to [c] - so you keep finding the max...
You should start the loop with c = position, not c = position - 1.
And add keyword static in front of the array you use to store the return values, so they remain valid (this is one way to address the issue that Jonathan Leffler identified).
One problem is that you are returning a pointer to a local variable, returnArray, in the function. You can't do that reliably — it leads to undefined behaviour.
There may well be other problems too, but that's enough to be a show-stopper on its own.
The whole approach to find the Kth largest element is not efficient and elegant. I will suggest you to modify your algorithm, although with above suggestions it will work fine, but it's not good way to solve this problem.
I will suggest you to look into below link to modify your algorithm
http://www.geeksforgeeks.org/k-largestor-smallest-elements-in-an-array/