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

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.

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...

Circular array and elimination in C, how to return the last "living" element index?

I am trying to write a code that will simulate a circle of a fixed size of people that have one sword. The closest "living person" to the current index will be eliminated and the sword will be passed to the next living person (after the one who got killed) and so on.
I want it to be written without linked lists.
Example:
A group of 3 people:
arr[0] = 1, arr[1] = 1, arr[2] = 1
First turn:
arr[0] KILLS arr[1] and the sword gets PASSED to arr[2]
Values of elements after the first turn:
arr[0] = 1, arr[1] = 0, arr[2] = 1
Second turn:
arr[2] KILLS arr[0] and stays the last player
Values of elements after the second turn:
arr[0] = 0, arr[1] = 0, arr[2] = 1
arr[2]'s index gets returned by the main function.
What I thought about was:
array
set the values all of elements to 1
circulate and check each time if (1 == arr[i])
set a flag to determine whether to kill or just pass the sword to this guy.
return the current index that indicates that's the index of the last player alive.
For example, lets say we have 5 people in our group:
[1] [1] [1] [1] [1]
First round:
give_sword = 0
i = 0 does not enter the first if because give_sword is not 1.
It enters the second if, and finds the closest living person using the function findClosestLivingPerson and gets his index and sets his value to 0 (== kills the closest living person).
It sets give_sword to 1.
Decreases the players_counter and checks if there is only one player left. If not, continues the loop.
This is my code:
#include <stdio.h>
int findClosestLivingPerson(int arr[], int index, int group_size);
int main (int argc, char *argv[])
{
int group_size = 0, players_counter = 0;
int i = 0, give_sword = 0;
int arr[100] = {0};
printf("Enter group size: \n");
scanf("%d",&group_size);
for (i = 0; i < group_size; i++)
{
arr[i] = 1;
}
players_counter = group_size;
for (i = 0; i < group_size; (i+1) % group_size)
{
if (1 == arr[i])
{
if(1 == give_sword) /* should give sword, not to kill */
{
give_sword = 0;
}
else /* should be killed */
{
arr[findClosestLivingPerson(arr,i, group_size)] = 0;
give_sword = 1;
--players_counter;
if (players_counter == 1)
{
break;
}
}
}
}
printf("Winner is %d ",i);
return 0;
}
int findClosestLivingPerson(int arr[], int index, int group_size)
{
for (; index < group_size; (index+1) % group_size)
{
if (arr[index] == 1)
return index;
}
return 0;
}
The compiler says:
In function ‘main’: last_man.c:23:43: warning: statement with no
effect [-Wunused-value] 23 | for (i = 0; i < group_size;
(i+1) % group_size)
last_man.c: In function ‘findClosestLivingPerson’: last_man.c:49:42:
warning: statement with no effect [-Wunused-value] 49 | for (;
index < group_size; (index+1) % group_size)
The (index+1) % group_size is meant to circulate through this array.
As the compiler says, (i+1) % group_size has no effect. It computes the remainder of the sum of i and one. After that, it does nothing with the result.
The third part of a for statement is just an expression that is evaluated. It does not automatically update the loop index or do anything else. If you want it to update i, you must write an assignment, like i = (i+1) % group_size.
I think you've misunderstood how for loop works .
Format should be like this:
for( initialization, condition, iteration )
example:
for( int i = 0; i < size; i = i + 1 )
(i + 1) % group_size isn't an iteration( it isn't assigning the result to i ) , what you really want to do is
i = ( i + 1 ) % group_size;
Same applies for the second warning .
I would suggest a different approach. Let's do this in a way that results in nice code.
struct actor {
int label;
struct actor *next;
};
With this struct we can make a nice linked list and loop it back around:
int n = 5;
int i;
struct actor *actors = calloc(n, sizeof *actors);
for (i = 0; i < n - 1; i++) {
actors[i].label = i;
actors[i].next = &actors[i+1];
}
actors[i].label = i;
actors[i].next = &actors[0];
Ok, now we can assign the first killer:
struct actor *k = actors;
We also need a kill function:
struct actor *kill(struct actor *a)
{
if (a->next != a) {
printf("%d kills %d\n", a->label, a->next->label);
a->next = a->next->next;
} else {
printf("%d is last man standing\n", a->label);
a->next = NULL;
}
return a->next;
}
What this does: it removes the next person from the circular linked list (as that is the one that is killed). The lookup time for the next person is always the same.
And with everything in place, we can start the spree:
while (k) {
k = kill(k);
}
This is not perfect code by any means, but it is a nice example of how you can make the algorithm incredibly simple if you put a little effort in setting up.

Returns in a recursive function

I am trying to understand how to use recursion in C, and I can't get how return works in it.
Please consider the following code:
int recur(int i)
{
printf("recur: i = %d\n", i);
if (i < 3)
{
recur(i + 1);
return 10;
}
else if (i < 5)
recur(i + 1);
return i;
}
int main(void)
{
int i = 0;
i = recur(i);
printf("i = %d\n", i);
return 0;
}
The output is:
recur: i = 0
recur: i = 1
recur: i = 2
recur: i = 3
recur: i = 4
recur: i = 5
i = 10
What does the last return, return i, do? Does this code even make sense?
The recursive calls of the function do not influence on the returned value. Only the first return met in the first instance of your recursive function will return a value to the parent function. Any other return met will just stop the function's instance the program is currently in.
Thus as the function was called in main with the argument 0
int i = 0;
i = recur(i);
The first return met is located inside of an if statement:
if (i < 3)
{
recur(i + 1);
return 10;
}
In this case, the recur function is called before returning a value to main. It will create another instance of recur which will do some stuff, but after this instance of recur has ended, the main instance of recur will continue and, in this case, will return 10 to the function main.
To know what your recursive function will return to the main function, you can simply comment all calls to a new instance of the function:
int recur(int i)
{
if (i < 3)
{
//recur(i + 1);
return 10;
}
else if (i < 5)
{
//recur(i + 1);
}
return i;
}
In this case, this is what the program will read:
int recur(int i)
{
if (i < 3)
return 10;
return i;
}
I think this is one of the easiest recursive function to understand.
int pow(int n, int x)
{
if (n != 1)
return x * pow(n - 1, x)
else
return x;
}
Let's study pow(3, 2) : 2^3 = 2 * 2 * 2 = 8
First iteration : pow(3, 2) returns 2 * pow(2, 2)
Second iteration : pow(2, 2) returns 2 * 2* pow(1, 2)
Third iteration : n == 1 so pow(1, 2) returns x = 2 * 2 * 2 = 8
A recursive function returns a call to itself at the i + 1 step of the process. In order to avoid an infinite loop, you have to make sur you have a break condition, which leads to a return to something different from a self-call.
You got at least one answer which helpfully explains the behaviour of your code.
I want to provide help via a different, additional path here. Both together provide different view points for you.
For that purpose I provide a version of your code augmented by instrumentation, which tells you more verbosely what happens.
This allows you to play with the code and observe, that will give you the really helpful answer.
Note:
the for(c lines are only for suggestive indentation;
I chose not to use a function for this, feeling that it keeps the interesting function calls more prominent
I added a parameter "nesting", it is for
making a part of the (hopefully useful) output
show that usually the recursive nesting has some influence
I introduced a local variable "j",
to show what happens with the reutrn values in most cases
Code:
#include <stdio.h>
int recur(int i, int nesting)
{ int c;
for(c=0;c<nesting;c++) { printf(" ");}
printf("recur[%d](%i)", nesting, i);
if (i < 3)
{ printf("i <3, calling recur[%d](%d)\n", nesting+1, i+1);
recur(i + 1, nesting+1);
for(c=0;c<nesting;c++) { printf(" ");}
printf("returning 10 from recur[%d], with i==%d\n", nesting, i);
return 10;
}
else if (i < 5)
{
int j=0;
printf("i <5, calling recur[%d](%d)\n", nesting+1, i +1);
j=recur(i + 1, nesting+1);
for(c=0;c<nesting;c++) { printf(" ");}
printf("ignored return value from recur[%d](%d) is %d", nesting+1, i+1, j);
}
printf("\n");
for(c=0;c<nesting;c++) { printf(" ");}
printf("returning i from recur[%d], with i==%d\n", nesting, i);
return i;
}
int main(void)
{
int i = 0;
i = recur(i, 0);
printf("the last return value did not get ignored: i = %d\n", i);
return 0;
}
Output:
recur[0](0)i <3, calling recur[1](1)
recur[1](1)i <3, calling recur[2](2)
recur[2](2)i <3, calling recur[3](3)
recur[3](3)i <5, calling recur[4](4)
recur[4](4)i <5, calling recur[5](5)
recur[5](5)
returning i from recur[5], with i==5
ignored return value from recur[5](5) is 5
returning i from recur[4], with i==4
ignored return value from recur[4](4) is 4
returning i from recur[3], with i==3
returning 10 from recur[2], with i==2
returning 10 from recur[1], with i==1
returning 10 from recur[0], with i==0
the last return value did not get ignored: i = 10
Note:
The recur[n](m) is of course no C syntax.
It just indicates a call to the function "recur" on nesting level "n" with parameter "m".
(Especially do not confuse the "[]" with arrays, they are not present.)
return 0 is the return from the main function, not from your recursive code.

how to initialize array of unknown size in c

I am doing a homework assignment for an intro to programming class in c.
I need to write a program that looks at an int array of unknown size (we are given a initializer list as the test case to use), and determine all the duplicates in the array.
To make sure that an element that was already found to be a duplicate doesn't get tested, I want to use a parallel array to the original that would hold the numbers of all the elements that were duplicates.
I need this array to be the same size as the original array, which of course we don't really know till the initializer list is given to us.
I tried using sizeof() to achieve this, but visual studio says that is an error due to the variable size (const int size = sizeof(array1);) not being constant. Am I not using sizeof correctly? Or is this logic flawed?
Perhaps there is another way to approach this, but I have yet to come up with one.
Here is the code included below, hope the comments don't make it too hard to read.
// Dean Davis
// Cs 1325
// Dr. Paulk
// Duplicates hw
#include <stdio.h>
int main()
{
int array1[] = { 0,0,0,0,123,124,125,3000,3000,82,876,986,345,1990,2367,98,2,444,993,635,283,544, 923,18,543,777,234,549,864,39,97,986,986,1,2999,473,776,9,23,397,15,822,1927,1438,1937,1956,7, 29,- 1 };
const int size = sizeof(array1);
int holdelements[size];
int a = 0; // counter for the loop to initialize the hold elements array
int b = 0; // counter used to move through array1 and be the element number of the element being tested
int c = 0; // counter used to move through holdelements and check to see if the element b has already been tested or found as duplicates
int d = 0; // counter used to move through array1 and check to see if there are any duplicates
int e = 0; // counter used to hold place in hold element at the next element where a new element number would go. sorry if that makes no sense
int flag = 0; // used as a boolian to make sure then large while loop ends when we reach a negative one value.
int flag2 = 0; // used as a boolian to stop the second while loop from being infinite. stops the loop when the end of hold elements has been reached
int flag3 = 0; // used to close the third while loop; is a boolian
int numberofduplicates=0;// keeps track of the number of duplicates found
for (a; a < size; a++)
{
if (a == (size - 1))
holdelements[a] = -1;
else
holdelements[a] = -2;
}
while (!flag)
{
flag2 = 0;
flag3 = 0;
if (array1[b] == -1)
flag = 1;
else
{
while ((!flag) && (!flag2))
{
if (holdelements[c] == -1)
flag2 = 1;
else if (array1[b] == holdelements[c])
{
b++;
c = 0;
if (array1[b] == -1)
flag = 1;
}
}
while (!flag3)
{
if (array1[d] == -1)
flag3 = 1;
else if (array1[b] == array1[d] && b != d)
{
printf("Duplicate of %d, index %d, was found at index %d.\n", array1[b], b, d);
holdelements[e] = d;
d++;
e++;
numberofduplicates++;
}
}
}
b++;
}
printf("Total Duplicates Found: %d\n", numberofduplicates);
return 0;
}
redo to the following:
const int size = sizeof(array1)/sizeof(int);

Array shows its pointer instead of its value

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].

Resources