Given the code:
int vector[5] = {1, 2, 3, 4, 5};
int *pv = vector, value = 3;
for(int i = 0; i < 5; i++) {
*pv++ *= value;
}
for(int i = 0; i < 5; i++) {
printf("%d, ", *(pv+i));
}
I expect each individual element of the array pointed to by pv to be multiplied by 3.
Instead what I get as an output is:
32766, -1554513907, -527290408, -333409024, 32766,
What am I doing wrong?
The problem is that you incremented the pointer in the first for cycle in every loop, so when you get to the end of it, pv is already pointing to one past the end of vector.
For that reason all the values printed in the second for cycle represent residual values stored in addresses out of the bounds of the array, classic undefined behavior.
A quick fix would be to reset the pointer in between the two cycles:
for (int i = 0; i < 5; i++){
*pv++ *= value;
}
pv = vector; //here
for (int i = 0; i < 5; i++) {
printf("%d, ", *(pv + i));
}
Or use the iterator i in both cycles, since you already have it in the for, you might as well use it:
for (int i = 0; i < 5; i++){
pv[i] *= value;
}
for (int i = 0; i < 5; i++) {
printf("%d, ", pv[i]);
}
With this method the pointer is not incremented, it's always pointing to the beginning of the array, accessing its indexes is safe.
Note that I used array notation [] as it's slightly less cluttered than the pointer dereference notation.
In your program, the first for loop (ie)
for(int i = 0; i < 5; i++) {
*pv++ *= value;
}
Here, pointer(pv) gets incremented for 5 times and when the control exits the loop , pointer(pv) is now pointing to something which is out-of-bounds of your array size(vector)
Since you're using the same pointer variable in second for loop to print the array(vector) values, the garbage values gets printed.
You can solve this by reassigning your pointer variable(pv) back to the 1st position of your array either by
pv= vector;
// or
pv = &vector[0];
before your second for loop.
Related
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.
#include <stdio.h>
#include <stdlib.h>
int* removeNegatives(int *v, int *totv){
int i, j, aux=(*totv), t=0;
for(i=0; i<aux; i++){
if(v[i]<0){
t=v[i];
for(j=i; j<=aux; j++){
v[j]=v[j+1];
}
v[(*totv)-1]=t;
aux--;
i=-1;
}
else{
continue;
}
}
totv=&aux;
v=(int*)realloc(v,(*totv)*sizeof(int));
return(v);
}
int main(){
int *totv=NULL, *v=NULL, *z=NULL, i, j=0, a;
printf("How many numbers are you entering?\n");
scanf("%d",&i);
printf("Enter them, then:\n");
totv=&i;
do{
if(j<(*totv)){
scanf("%d",&a);
v=(int*)realloc(v,++j*sizeof(int));
v[j-1]=a;
}
}while(j<(*totv));
printf("\n");
printf("Size before: %d\n",*totv);
z=retiraNegativos(v,totv);
printf("Size after: %d\n",*totv);
printf("\n");
printf("[ ");
for(i=0; i<(*totv); i++){
printf("%d ",z[i]);
}
printf("]");
printf("\n");
free(z);
return(0);
}
I'm resizing the vector "v" according to the number of negative numbers the user has entered.
But the problem is that the pointer "totv" is not updating after I call the fucntion "removeNegatives".
Your help is greatly appreciated!
This may look unrelated to your question, but it isn't.
Consider this:
int foo(int bar)
{
bar = 123;
}
...
int x = 1;
foo(x);
// What's the value of x here?
...
Will x be updated after the call to foo?
Problem is here:
totv=&aux;
You assign your local copy of some pointer to a new address. This does not have any visible effect outside your function. What you actually wanted is not changing the pointer, but the value it points to, thus you need:
*totv=aux;
Additionally, you have a problem here:
for(j=i; j<=aux; j++)
v[j]=v[j+1];
In the last iteration, you will access your array at positions aux and aux + 1, both out of range of your array, at least on the first removal! Instead, you need:
for(j = i; j < aux - 1; j++)
or a little more elegant in my eyes:
for(j = i + 1; j < aux; j++)
v[j - 1]= v[j];
Some further hints:
You do not need any else continue;, if there isn't anything to follow the else branch anyway.
No need to restart the loop (i = -1;) right from the start, you can simply go on with the value you just copied (--i;). However, although technically not incorrect, prefer not modifying the loop variable of a for loop. This is something one does not expect from this kind of loop. If you really have to, then prefer a while loop instead.
You do not need to copy the removed values to the end if you cut them off afterwards anyway.
And if you do not want to keep the removed values, do not copy all the subsequent values each time you remove one value, prefer copying every value to be kept just once, see below.
Moving all elements in one go:
int* p = v;
for(unsigned int i = 0; i < aux; ++i)
{
int tmp = v[i];
if(tmp >= 0)
*p++ = tmp; // copy current value to first free position
}
An array with values { 1, -2, -3, 4, 5, -6, 7 } would now look like this:
{ 1, 4, 5, 7, 5, -6, 7 }. The last values just remain unchanged, p points to the first position to be cut off. So:
aux = p - v;
*totv = aux;
return (int*) realloc(v, aux * sizeof(int));
Be aware that you could return NULL this way, if reallocation fails. I'd assume this to be very unlikely, if reducing size, but for correctness:
p = realloc(v, aux * sizeof(int));
return p ? p : v;
So you'd return the unchanged array on failure. Consider some more fine-tuned error handling...
Here's the code and wondering if you can help me understand it.
/* Two dimensional array */
#include <stdio.h>
void main() {
int i, j, sum[2], mean[2];
int mark[3][2] = { { 34, 56}, { 48, 65}, { 53, 59} };
for (j = 0; j < 2; j++)
sum[j] = 0;
for (i = 0; i < 3; i++) {
for (j = 0; j < 2; j++) {
sum[j] = sum[j] + mark[i][j];
}
}
for (j = 0; j < 2; j++)
mean[j] = sum[j] / 3;
printf("Average mark in Mathematics is %d\n", mean[0]);
printf("Average mark in Chemistry is %d\n", mean[1]);
}
My understanding of it so far....
Define data types i, j, sum[2], mean[2] as integers.
Initialising the array....mark is data type int, the array should have 3 rows and 2 columns.
First for loop, j initialised at 0, condition: j has to be less than 2, update: add one onto the value of j. Sum of j = 0.
Also for 2nd loop, i initialised at 0, condition: i has to be less than 3, update: add one onto the value of i.
Similar for the next line that uses the for loop and value j.
I'm a bit confused about the syntax:
sum[j] = sum[j] + mark[i] [j]; does this mean, work out the sum of j and add it to the marks contained in the array displayed as [i] and [j].
After this is completed then similar j loop though not sure how this interacts with the previous loops.
Mean calculated and values printed to the screen.
When I've looked at the worked example...
sum[0] = 0 and sum[1] = 0, I don't really understand why sum[1] is also 0.
Firstly, i=0 and j=0,
sum[0] = sum[0] + mark [0,0]
then j=1
sum[1]=sum[1]+mark[0,1]
then
i=1, j=0
sum[0] = sum[0] + mark [1,0]
then
sum[1] = sum[1]+mark[1,1]
then i = 2, j=0
sum [0] = sum[0]+ mark[2,0]
then
sum[1] = sum[1]+ mark[2,1]
What is confusing me a bit is how the loops are interacting with each other and the values of i and j throughout.
I know that the 2d array would be in a table (that I can't seem to format here).
Would appreciate if anyone could shed some light on this.
sum[j] = sum[j] + mark[i][j]; can be simplified as sum[j] += mark[i][j];. It adds the contents of the cell at row i, column j of the 2D matrix mark to the jth element of array sum.
Accessing an element of a 2D array is written mark[i][j] in C, not mark[i, j].
Note that mark[i, j] is not a syntax error: the expression i, j is a comma expression, evaluating i, then discarding it and evaluating j. It is therefore the same as mark[j] which is not a matrix cell but a reference to the jth row of the 2D matrix.
Nope, an array is in fact a pointer (aka an address). When you define int sum[2], sum is the address of the first element of your array of two integer.
So sum is an int* or int[] (same).
Mark is an 2d array. Mark is in fact an array of array. So Mark contain addresses, and thoses addresses are the beggining of some arrays.
(In fact it can be different in the memory, but the compiler do the work).
Mark is a int**, or an address of address of int.
When you do:
for (i = 0; i < 3; i++) {
for (j = 0; j < 2; j++) {
sum[j] = sum[j] + mark[i][j];
}
}
It's like if you were saying
for each line i in the array, I want to do:
for each value j in the line, I want to do:
...;
Like this, you work on every "line" (or column, visualize the way you want), and for every "line", you work on every value.
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/