Array shows its pointer instead of its value - c

I'm stuck in some trouble, unfortunately I'm still learning the details of this language.
I have the following code
#define SIZE 5
typedef struct
{
int start;
int end;
int nElements;
int vetor[SIZE];
} TSTACK;
and I try to inser values in its array using the following function:
void Push(TSTACK *s, int elementInsert)
{
if(IsFull(s))
{
printf("%s\n", "# ERROR: full.");
}
else
{
s->end++;
if(s->end == SIZE)
{
s->end = 0;
}
s->vetor[s->end] = elementInsert;
s->nElements++;
}
}
and I use the following function to show elements:
void Display(TSTACK *s)
{
int i;
if (isEmpty(s))
{
printf("%s\n", "# ERROR: empty");
}
else
{
for (i = 0; i < s->nElements; i++)
{
printf ("value: %d\n", s->vetor[i]);
}
}
}
My question is that I don't get the same result when I add different amount of elements, when I insert 5 elements, the Display function display all the elements correctly, but when I insert less than 5, the first item appears to be its pointer:
The following main results in 4201166, 3, 5, 7
int main(void)
{
TSTACK test;
test.start = 1;
test.end = 0;
test.nElements = 0;
Push(&test, 3);
Push(&test, 5);
Push(&test, 7);
Push(&test, 3);
Display(&test);
}
The following main results in 5, 3, 5, 7, 3
int main(void)
{
TSTACK test;
test.start = 1;
test.end = 0;
test.nElements = 0;
Push(&test, 3);
Push(&test, 5);
Push(&test, 7);
Push(&test, 3);
Push(&test, 5);
Display(&test);
}
Can someone show me where I am wrong?

When you "insert" an element, you do it at
s->vetor[s->end]
But before you do that you increase s->end, so the first element will be at s->vetor[1]. Since the first element (s->vetor[0]) is not initialized, you will have a random value there. That is the reason you have a strange value first in the four-value insert.
When you insert a fifth value, you have the check for s->end == SIZE where you set s->end to zero, so the last value in that case will end up in the first place in the array.
The solution, that will solve both of the above problems, is to increase s->end after you assigned the value to the array.

When you print the stack:
for (i = 0; i < s->nElements; i++)
{
printf ("value: %d\n", s->vetor[i]);
}
You are starting at index 0, but your stack implementation starts at index 1, so when you have less than 5 elements the first item is not initialized. Perhaps you can fix this by changing start value to 0.

First problem: Local variables aren't initialized, they contain garbage unless you initialize them.
Second problem: You start assigning at array index 1 instead of 0. Only when you insert five elements will it work, because you check if end == SIZE and if so set end = 0, making the fift insert set the first element vetor[0].

Related

last number in a function array

I want to write a function where I have a given array and number N. The last occurrence of this number I want to return address. If said number cannot be found I want to use a NULL-pointer
Start of the code I've made:
int main(void) {
int n = 3;
int ary[6] = { 1,3,7,8,3,9 };
for (int i = 0; i <= 6; i++) {
if (ary[i] == 3) {
printf("%u\n", ary[i]);
}
}
return 0;
}
result in command prompt:
3
3
The biggest trouble I'm having is:
it prints all occurrences, but not the last occurrence as I want
I haven't used pointers much, so I don't understand how to use the NULL-pointer
I see many minor problems in your program:
If you want to make a function, make a function so your parameters and return types are explicit, instead of coding directly in the main.
C arrays, like in most languages, start the indexing at 0 so if there are N element the first has index 0, then the second has 1, etc... So the very last element (the Nth) has index N-1, so in your for loops, always have condition "i < size", not "i <= size" or ( "i <= size-1" if y'r a weirdo)
If you want to act only on the last occurence of something, don't act on every. Just save every new occurence to the same variable and then, when you're sure it was the last, act on it.
A final version of the function you describe would be:
int* lastOccurence(int n, int* arr, int size){
int* pos = NULL;
for(int i = 0; i < size; i++){
if(arr[i] == n){
pos = &arr[i]; //Should be equal to arr + i*sizeof(int)
}
}
return pos;
}
int main(void){
int n = 3;
int ary[6] = { 1,3,7,8,3,9 };
printf("%p\n", lastOccurence(3, ary, 6);
return 0;
}
Then I'll add that the NULL pointer is just 0, I mean there is literally the line "#define NULL 0" inside the runtime headers. It is just a convention that the memory address 0 doesn't exist and we use NULL instead of 0 for clarity, but it's exactly the same.
Bugs:
i <= 6 accesses the array out of bounds, change to i < 6.
printf("%u\n", ary[i]); prints the value, not the index.
You don't actually compare the value against n but against a hard-coded 3.
I think that you are looking for something like this:
#include <stdio.h>
int main(void)
{
int n = 3;
int ary[6] = { 1,3,7,8,3,9 };
int* last_index = NULL;
for (int i = 0; i < 6; i++) {
if (ary[i] == n) {
last_index = &ary[i];
}
}
if(last_index == NULL) {
printf("Number not found\n");
}
else {
printf("Last index: %d\n", (int)(last_index - ary));
}
return 0;
}
The pointer last_index points at the last found item, if any. By subtracting the array's base address last_index - ary we do pointer arithmetic and get the array item.
The cast to int is necessary to avoid a quirk where subtracting pointers in C actually gives the result in a large integer type called ptrdiff_t - beginners need not worry about that one, so just cast.
First of all, you will read from out of array range, since your array last element is 5, and you read up to 6, which can lead in segmentation faults. #Ludin is right saying that you should change
for (int i = 0; i <= 6; i++) // reads from 0 to 6 range! It is roughly equal to for (int i = 0; i == 6; i++)
to:
for (int i = 0; i < 6; i++) // reads from 0 to 5
The last occurrence of this number I want to return as address.
You are printing only value of 3, not address. To do so, you need to use & operator.
If said number cannot be found I want to use a NULL-pointer
I don't understand, where do you want to return nullpointer? Main function can't return nullpointer, it is contradictory to its definition. To do so, you need to place it in separate function, and then return NULL.
If you want to return last occurence, then I would iterate from the end of this array:
for (int i = 5; i > -1; i--) {
if (ary[i] == 3) {
printf("place in array: %u\n", i); // to print iterator
printf("place in memory: %p\n", &(ary[i])); // to print pointer
break; // if you want to print only last occurence in array and don't read ruther
}
else if (i == 0) {
printf("None occurences found");
}
}
If you want to return an address you need yo use a function instead of writing code in main
As you want to return the address of the last occurence, you should iterate the array from last element towards the first element instead of iterating from first towards last elements.
Below are 2 different implementations of such a function.
#include <stdio.h>
#include <assert.h>
int* f(int n, size_t sz, int a[])
{
assert(sz > 0 && a != NULL);
// Iterate the array from last element towards first element
int* p = a + sz;
do
{
--p;
if (*p == n) return p;
} while(p != a);
return NULL;
}
int* g(int n, size_t sz, int a[])
{
assert(sz > 0 && a != NULL);
// Iterate the array from last element towards first element
size_t i = sz;
do
{
--i;
if (a[i] == n) return &a[i];
} while (i > 0);
return NULL;
}
int main(void)
{
int n = 3;
int ary[] = { 1,3,7,8,3,9 };
size_t elements = sizeof ary / sizeof ary[0];
int* p;
p = g(n, elements, ary); // or p = f(n, elements, ary);
if (p != NULL)
{
printf("Found at address %p - value %d\n", (void*)p, *p);
}
else
{
printf("Not found. The function returned %p\n", (void*)p);
}
return 0;
}
Working on the specified requirements in your question (i.e. a function that searches for the number and returns the address of its last occurrence, or NULL), the code below gives one way of fulfilling those. The comments included are intended to be self-explanatory.
#include <stdio.h>
// Note that an array, passed as an argument, is converted to a pointer (to the
// first element). We can change this in our function, because that pointer is
// passed BY VALUE (i.e. it's a copy), so it won't change the original
int* FindLast(int* arr, size_t length, int find)
{
int* answer = NULL; // The result pointer: set to NULL to start off with
for (size_t i = 0; i < length; ++i) { // Note the use of < rather than <=
if (*arr == find) {
answer = arr; // Found, so set our pointer to the ADDRESS of this element
// Note that, if multiple occurrences exist, the LAST one will be the answer
}
++arr; // Move on to the next element's address
}
return answer;
}
int main(void)
{
int num = 3; // Number to find
int ary[6] = { 1,3,7,8,3,9 }; // array to search
size_t arrlen = sizeof(ary) / sizeof(ary[0]); // Classic way to get length of an array
int* result = FindLast(ary, arrlen, num); // Call the function!
if (result == NULL) { // No match was found ...
printf("No match was found in the array!\n");
}
else {
printf("The address of the last match found is %p.\n", (void*)result); // Show the address
printf("The element at that address is: %d\n", *result); // Just for a verification/check!
}
return 0;
}
Lots of answers so far. All very good answers, too, so I won't repeat the same commentary about array bounds, etc.
I will, however, take a different approach and state, "I want to use a NULL-pointer" is a silly prerequisite for this task serving only to muddle and complicate a very simple problem. "I want to use ..." is chopping off your nose to spite your face.
The KISS principle is to "Keep It Simple, St....!!" Those who will read/modify your code will appreciate your efforts far more than admiring you for making wrong decisions that makes their day worse.
Arrays are easy to conceive of in terms of indexing to reach each element. If you want to train in the use of pointers and NULL pointers, I suggest you explore "linked lists" and/or "binary trees". Those data structures are founded on the utility of pointers.
int main( void ) {
const int n = 3, ary[] = { 1, 3, 7, 8, 3, 9 };
size_t sz = sizeof ary/sizeof ary[0];
// search for the LAST match by starting at the end, not the beginning.
while( sz-- )
if( ary[ sz ] == n ) {
printf( "ary[ %sz ] = %d\n", sz, n );
return 0;
}
puts( "not found" );
return 1; // failed to find it.
}
Consider that the array to be searched is many megabytes. To find the LAST match, it makes sense to start at the tail, not the head of the array.
Simple...

Find "Empty Frame" In an Array (simulation on LRU and OS)

I am having trouble coming up with a working helper function for my main, I believe the problem with my main program not working is because of this helper function.
its is supposed to loop through an array and see if there is an empty frame, i.e. an element that equals 1.
i have an array like this
int freeFrames[8] = {0, 1, 1, 1, 1, 1, 1 , 1};
and the helper function like this
int findEmptyFrame(int freeFrames[])
{
int i, index;
for(i = 1; i < 8; i++)
{
printf("FreeFrame = %d\n",i); // simple print statment
if(freeFrames[i] == 1){
index = i;
return index;
}
else{
return -1;
}
}
}
when I loop thru the array in my main Program it only ever reaches the 1st frame and returns it and doesn't ever cycle thru the next next element besides the first one
this is the section in my main where i am calling the function
else{
x = findEmptyFrame(freeFrames);
printf("X IS %d\n",x );
if(x > 0){
printf("IN IF BEFORE findEmptyFrame\n");
PT[pageNumber].fNum = x;
PT[pageNumber].vi = 0;
frameNumber = PT[pageNumber].fNum;
PA = (frameNumber << d) + dNum;
fwrite(&PA,sizeof(unsigned long), 1, myWriteFile);
printf("The Logical Address is at %lx and Translated Physical Addres is at %lx\n",LA, PA);
lruCount[frameNumber] = clock;
reverseMap[x] = pageNumber;
}
and an example of what i am currently getting is something like this
IN IF BEFORE findEmptyFrame
The Logical Address is at b70 and Translated Physical Addres is at f0
FreeFrame = 1
X IS 1
The reason this is happening is because in your for loop, if the freeFrame[i] is not equal to 1, the if condition fails. It therefore goes to the else part and returns -1. Therefore, you cannot return -1 within the for loop. You have to return it outside, like below:
int findEmptyFrame(int freeFrames[])
{
int i, index;
for(i = 0; i < 8; i++)
{
printf("FreeFrame = %d\n",i); // simple print statment
if(freeFrames[i] == 1){
freeFrames[i] = 0; //Change here
return i;
}
}
return -1;
}
What this does is, if there is a 1 in the array, it returns the index. If not, the whole for loop ends and only then it returns -1.
Also, indexing in the for loop must start from 0.
If you want the first free frame to be marked used, you additionally have to do that before returning the index. Check the change in code.

A function in C runs for a set of values but gives Segmentation Fault: 11 for another

I am trying to find unique non-zero intersection between two sets. I have written a program which works for some set of arrays but gives segmentation fault for some. I have been trying to figure out why but have failed, any help will be greatly valued. The thing is the functions defined (NoRep and ComEle) are working fine but are unable to return the value to the assigned pointer in the case when Seg Fault is shown. Below is the code:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
int* ComEle(int ar_1[], int size_ar1, int ar_2[], int size_ar2);
int* NoRep(int a[], int l1);
int main ()
{
// Case 1: Gives segmentation fault
int A[10] = {1,1,0,2,2,0,1,1,1,0};
int B[10] = {1,1,1,1,0,1,1,0,4,0};
int *C = ComEle(A,10,B,10); printf("check complete\n");
// //Case 2: Does not give segmentation fault
// int A[4] = {2,3,4,5};
// int B[4] = {1,2,3,4};
// int *C = ComEle(A,4,B,4); printf("check complete\n");
}
//---------------- Local Functions --------------------//
int* ComEle(int ar_1[], int size_ar1, int ar_2[], int size_ar2) {
// sort of intersection of two arrays but only for nonzero elements.
int i=0, j=0, cnt1 = 0;
int temp1 = size_ar1+size_ar2;
int CE1[temp1]; for(i=0;i<temp1;i++) {CE1[i] = 0;}
/* Size of CE1 is knowingly made big enough to accommodate repeating
common elements which can expand the size of resultant array to
values bigger than those for the individual arrays themselves! */
for(i=0;i<size_ar1;i++) {
j = 0;
while(j<size_ar2) {
if(ar_1[i]==ar_2[j] && ar_1[i]!=0) {
CE1[cnt1] = ar_1[i];
cnt1++;
}
j++;
}
}
// Have to remove repeating elements.
int *CE = NoRep(CE1, cnt1);
for(i=0;i<(CE[0]+1);i++) {printf("CE:\t%d\n", CE[i]);}
printf("ComEle: %p\n",CE);
return(CE);
}
int* NoRep(int a[], int l1) {
int cnt = 0, i = 0, j =0;
int *NR; NR = (int*)calloc((l1), sizeof(int));
//int NR[l1]; for(i=0;i<l1;i++) {NR[i] = 0;}
for(i=0;i<l1;i++) {
j = 0;
while(j<i) {
if(a[i]==a[j]) {break;}
j++;
}
if(j == i) {
cnt++;
NR[cnt] = a[i];
}
}
NR[0] = cnt; // First element: # of relevant elements.
printf("NoRep: %p\n",NR);
return(NR);
}
Thanks again for your help!
Take a look at this code:
int temp1 = size_ar1+size_ar2;
int CE1[temp1]; for(i=0;i<temp1;i++) {CE1[i] = 0;}
/* Size of CE1 is knowingly made big enough to accommodate repeating
common elements which can expand the size of resultant array to
values bigger than those for the individual arrays themselves! */
for(i=0;i<size_ar1;i++) {
j = 0;
while(j<size_ar2) {
if(ar_1[i]==ar_2[j] && ar_1[i]!=0) {
CE1[cnt1] = ar_1[i];
cnt1++;
}
j++;
}
}
Here you have nested loops, i.e. a for-loop with a while-loop inside. So - in worst case - how many times can cnt1 be incremented?
The answer is size_ar1 * size_ar2
But your code only reserve size_ar1 + size_ar2 element for CE1. So you may end up writing outside the array.
You can see this very easy by printing cnt1 inside the loop.
In other words - your CE1 is too small. It should be:
int temp1 = size_ar1*size_ar2; // NOTICE: * instead of +
int CE1[temp1]; for(i=0;i<temp1;i++) {CE1[i] = 0;}
But be careful here - if the input arrays are big, the VLA gets huge and you may run in to stack overflow. Consider dynamic memory allocation instead of an array.
Besides the accepted answer: I have been missing a break statement in the while loop in ComEle function. It was not giving me the expected value of cnt1. The following will be the correct way to do it:
for(i=0;i<size_ar1;i++) {
j = 0;
while(j<size_ar2) {
if(ar_1[i]==ar_2[j] && ar_1[i]!=0) {
CE1[cnt1] = ar_1[i];
cnt1++;
break;
}
j++;
}
}
This will also do away with the requirement for a bigger array or dynamic allocation as suggested (and rightly so) by #4386427

C Pointer to an Array example stops working

I'm working on an example and my code is stopped woking when I run it.(Note that I translated the question to English so sorry for grammar mistakes.)
Here is the question:
myShrink() function's prototype is like this:
void myShrink(int *param1, const int param2);
myShrink() function should find the average of the array param1 then should increment the element by 1 if its less than average, or should decrement the element by 1 if it's more than average. param2 is a number of elements in an array.
Here is the content of the main() function:
void myStretch(int *param1, const int param2);
int main () { int myArray[] = {2, 4, 2, 4, 2, 4};
int index;
myStretch(myArray, 6);
printf("UPDATED ARRAY: ");
for(index = 0; index < 6; index++){
printf("%d\t", myArray[index]);
}
return 0;
}
---------The result when we run the program:-----
UPDATED ARRAY: 1 5 1 5 1 5
Now this was the question part what we need to is basically programming the content of myShrink() function and here is my work:
void myShrink(int *param1, const int param2)
{
int array[param2];
param1=array;//Using pointer to point elements of array
int average=0;
int i,j;
for(i=0;i<param2;i++)
{
average+=*(param1 + i);//Adding each element of array
}
average=average/param2;//Then dividing result to param2 to find average
for(j=0;j<param2;j++)
{
if(*(param1+j)<average)//if below average
{
*(param1+j)+=1;//increment
}
else if(*(param1+j)>average)//if above average
{
*(param1+j)-=1;//decrement
}
}
}
But its stops working when I run it. Where I did make mistake and how can I fix it?
Just do this:
#include<stdio.h>
void myStretch(int *param1, const int param2);
int main () { int myArray[] = {2, 4, 2, 4, 2, 4};
int index;
myStretch(myArray, 6);
printf("UPDATED ARRAY: ");
for(index = 0; index < 6; index++){
printf("\n%d\t", myArray[index]);
}
return 0;
}
void myStretch(int *param1, const int param2)
{
int average=0;
int i,j;
for(i=0;i<param2;i++)
{
average+=*(param1 + i);//Adding each element of array
}
average=average/param2;//Then dividing result to param2 to find average
for(j=0;j<param2;j++)
{
if(*(param1+j)<average)//if below average
{
(*(param1+j))+=1;//increment
}
else if(*(param1+j)>average)//if above average
{
printf("%d ",(*(param1+j)));
(*(param1+j))-=1;//decrement
}
}
}
Now first thing: your result is wrong. It should be 3 3 3 3 3 3. As the average in this case is 3 and therefore 2 will become 3 and 4 will also become 3. Secondly you don't have to assign a new array inside the function. Just do it this way. Third mistake:
*(param1+j)>average
should be replaced by
(*(param1+j))>average
and similarly for less than sign.
UPDATE: Also note that many people argue that array[param2] is legal or not. When you declare such an array they are called Variable Length Array(VLA). This is allowed in modern C compilers but older compilers like Turbo C don't allow.
In below myShrink function, after 'param1=array;' statement param1 start pointing to array which has garbage inside.
void myShrink(int *param1, const int param2){
int array[param2];
param1=array;//Using pointer to point elements of array
int average=0;
int i,j;
//debug code to shows param1 points to array which has garage inside
int index =0 ;
for(index = 0; index < 6; index++){
printf("myDebug: %d\n", param1[index]);
}
for(i=0;i<param2;i++)
{
average+=*(param1 + i);//Adding each element of array
}
average=average/param2;//Then dividing result to param2 to find average
for(j=0;j<param2;j++)
{
if(*(param1+j)<average)//if below average
{
*(param1+j)+=1;//increment
}
else if(*(param1+j)>average)//if above average
{
*(param1+j)-=1;//decrement
}
}}

array address do not increment correctly in C

I am trying to make a recursive function to print the content of an array.
The main looks like this:
#include <stdio.h>
static int s_index;
int main(void) { int even[] = {2, 4, 6, 8}; s_index = 0; print(even);}
The print function looks like this:
void print(int * array) {
if(s_index > 3) {
printf("\n"); return;
}
printf(" %d ", *array); ++s_index; print(array + s_index);
}
What I notice is:
if &even is 0x7fffffffdbf0 then (array + s_index) increments as follow with s_index:
s_index = 0 : 0x7fffffffdbf0;
s_index = 1 : 0x7fffffffdbf4;
s_index = 2 : 0x7fffffffdbfc;
it should be 0x7fffffffdbf8!!?
It is blowing my mind, could someone help with that?
Thank you for your answers.
You made a logical mistake in your recursive call. See what happens:
Assume &even = 0x7fffffffdbf0
First call:
array = 0x7fffffffdbf0 ; s_index = 0.
You increase s_index and pass into the second call array + s_index, which yields:
Second call:
array = 0x7fffffffdbf4 ; s_index = 1.
Again, you increase s_index and pass into the third call array + s_index, which yields:
array = (0x7fffffffdbf4) + 2 => 0x7fffffffdbfc
You should only increase array by 1 for each recursive call, and remove s_index completely (that's the point of the recursion, to get rid of global variables)
Please get rid of the global value s_index.Change your func signature as shown below
int main(void)
{
int even[] = {2, 4, 6, 8,10,12};
print(even,(sizeof(even)/sizeof(int)));
}
void print(int * array,int len) {
if( len == 0)
{
printf("\n"); return;
}
else
{
printf(" %d ", *(array));
print(array+1,len-1);
}
}
Please don't do really strange and obscure things for no apparent reason, such as using recursion where simple loops are faster, safer and more readable. Because when you are doing really strange things on purpose, other equally strange things tend to happen unexpectedly.
#include <stdio.h>
void print(int* array, size_t size)
{
for(size_t i=0; i<size; i++)
{
printf("value:%d address:%p\n", array[i], (void*)&array[i]);
}
}
int main(void)
{
int even[] = {2, 4, 6, 8};
print(even, 4);
}

Resources