Dining philosophers using semaphores (BACI) - concurrency

I have to solve the dining philosophers problem by using semaphores. In my code every second philosopher is taking a chopstick and the rest are waiting.
I still have some errors in the main function. Can you tell me how to initiate Chopstick[k]? I'm a beginner in BACI.
binarysem ChopStick[5];
binarysem speak;
void philosopher(int index){
int i,k;
int x;
x=0;
for(i=0;i<k;i++){
cout << "I am philosopher: " << index << " and i am thinking "<< endl;
signal(speak);
if(index % 2 == 0){
wait(ChopStick[index]);
wait(ChopStick[(index+1) % 5]);
}
else{
wait(ChopStick[index]);
wait(ChopStick[(index+1) % 5]);
}
x++;
wait(speak);
cout <<"I am philosopher: "<< index <<" and i eat: "<< x << "times" << endl;
signal(speak);
signal(ChopStick[index]);
signal(ChopStick[(index+1) % 5]);
main(){
int k;
for(k=0;k<5;k++){
initialsem(ChopStick[k],1);
initialsem(speak,1);
}
cobegin
{
philosopher(1); philosopher(2); philosopher(3); philosopher(4); philosopher(5);
}
}

According to this BACI summary, it sounds like arrays should be initialized like in C. So you would want something like:
binarysem initialsem[5];
(where 5 is the length of the array, and binarysem is the datatype of the array elements)

Related

Mean and Mode of vector array - How can I make a smaller improvement in the function

Doing an exercise to find the mean and mode of a list of numbers input by a user. I have written the program and it works, but I'm wondering if my function 'calcMode' is too large for this program. I've just started looking into functions which is a first attempt. Would it be better to write smaller functions? and if so what parts can I split? Im pretty new to C++ and also looking if I can improve this code. Is there any changes I can make to make this run more efficient?
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int calcMean(vector<int> numberList)
{
int originNumber = numberList[0];
int nextNumber;
int count = 0;
int highestCount = 0;
int mean = 0;
for (unsigned int i = 0; i <= numberList.size() - 1; i++)
{
nextNumber = numberList[i];
if (nextNumber == originNumber)
count++;
else
{
cout << "The Number " << originNumber << " appears " << count << " times." << endl;
count = 1;
originNumber = nextNumber;
}
}
if (count > highestCount)
{
highestCount = count;
mean = originNumber;
}
cout << "The Number " << originNumber << " appears " << count << " times." << endl;
return mean;
}
int main()
{
vector<int> v;
int userNumber;
cout << "Please type a list of numbers so we can arrange them and find the mean: "<<endl;
while (cin >> userNumber) v.push_back(userNumber);
sort(v.begin(), v.end());
for (int x : v) cout << x << " | ";
cout << endl;
cout<<calcMean(v)<<" is the mean"<<endl;
return 0;
}
One thing to watch out for is copying vectors when you don't need to.
The function signature
int calcMode(vector<int> numberList)
means the numberList will get copied.
int calcMode(const & vector<int> numberList)
will avoid the copy. Scott Meyer's Effective C++ talks about this.
As an aside, calling is a numberList is misleading - it isn't a list.
There are a couple of points that are worth being aware of in the for loop:
for (unsigned int i = 0; i <= numberList.size()-1; i++)
First, this might calculate the size() every time. An optimiser might get rid of this for you, but some people will write
for (unsigned int i = 0, size=numberList.size(); i <= size-1; i++)
The size is found once this way, instead of potentially each time.
They might even change the i++ to ++i. There used to a potential overhead here, since the post-increment might involve an extra temporary value
One question - are you *sure this gives the right answer?
The comparison nextNumber == originNumber is looking at the first number to begin with.
Try it with 1, 2, 2.
One final point. If this is general purpose, what happens if the list is empty?
Would it be better to write smaller functions?
Yes, you can make do the same job using std::map<>; which could be
a much appropriate way to count the repetition of the array elements.
Secondly, it would be much safer to know, what is the size of the
array. Therefore I suggest the following:
std::cout << "Enter the size of the array: " << std::endl;
std::cin >> arraySize;
In the calcMode(), you can easily const reference, so that array
will not be copied to the function.
Here is the updated code with above mentioned manner which you can refer:
#include <iostream>
#include <algorithm>
#include <map>
int calcMode(const std::map<int,int>& Map)
{
int currentRepetition = 0;
int mode = 0;
for(const auto& number: Map)
{
std::cout << "The Number " << number.first << " appears " << number.second << " times." << std::endl;
if(currentRepetition < number.second )
{
mode = number.first; // the number
currentRepetition = number.second; // the repetition of the that number
}
}
return mode;
}
int main()
{
int arraySize;
int userNumber;
std::map<int,int> Map;
std::cout << "Enter the size of the array: " << std::endl;
std::cin >> arraySize;
std::cout << "Please type a list of numbers so we can arrange them and find the mean: " << std::endl;
while (arraySize--)
{
std::cin >> userNumber;
Map[userNumber]++;
}
std::cout << calcMode(Map)<<" is the mode" << std::endl;
return 0;
}
Update: After posting this answer, I have found that you have edited your function with mean instead of mode. I really didn't get it.
Regarding mean & mode: I recommend you to read more. Because in general, a data set can have multiple modes and only one mean.
I personally wouldn't split this code up in smaller blocks, only if i'd want to reuse some code in other methods. But just for this method it's more readable like this.
The order of excecution is aroun O(n) for calc which is quite oke if you ask me

Trouble with semaphore implementation

I am meant to write a program that takes 2 different command line options and uses semaphore to alternate the output from "First" to "Next". More detail -
• Program runs twice with different command line options
progName randNumber fRunSeed "F" & progName randNumber nRunSeed "N" &
• F = First run, N = Next run
• Each run is meant to generate randNum amount of random numbers, but couts a line after each random number.
• Use semaphores to alternate couts between the F run and the N run. (F being first)
The output should include the run (F or N), the process ID, and the random number.
So far I have the header file written, and some of the actual code processing. But I do not know where to actually implement the semaphore... I do understand the purpose of a semaphore, and that this program does not really utilize it well but it is what I am meant to use.
Could someone please look at my code and either guide me in the right direction of where to insert the semaphore, or tell me how to do so?
Thank you for all of the help -- Code below
My header:
union semun {
int val;
struct semid_ds *buf;
ushort *array;
};
class Semaphore {
private:
const unsigned int SemCount;
int SemID;
public:
Semaphore (key_t key, int howManySemaphoresToCreate);
void Init (int SemaphoreNumber, int Value);
int ReadValue (int SemaphoreNumber);
// Decrease the value of a semaphore, semaphoreNumber, by 1
void Wait (int SemaphoreNumber);
// Increase the value of a semaphore, semaphoreNumber, by 1.
void Signal (int SemaphoreNumber);
// Remove the semaphore group.
void Destroy( );
};
And the code that I wrote to handle the data processing. I do not know where to insert semaphore, so right now the actual code is a rough sketch.
int main(int argc, char *argv[]){
int firstSeed = atoi(argv[2]);
int nextSeed = atoi(argv[2]);
int numRandNums = atoi(argv[1]);
if(argv[3] == "F"){
srand(firstSeed);
for(int i = 0; i < numRandNums; i++){
cout << "F: " << "ID: " << getpid() << " Num: " << rand() << endl;
}
}
else if(argv[3] == "N"){
srand(nextSeed);
for(int j = 0; j < numRandNums; j++){
cout << "N: " << "ID: " << getpid() << " Num: " << rand() << endl;
}
}
}
I know this website isn't for people to finish your work for you, but at this point I do not understand the actual implementation of semaphores, and although I have read a lot about them I cannot find examples similar enough to what I need to do to actually see the similarities. Also, I do not think getpid() is the proper way to get the process ID for semaphores, but as I said, just a rough draft for now.
Thank you to anyone that can help me with this.
Here is what I think you can do to add semaphores in your code-
int main(int argc, char *argv[]){
//two semaphores to check if it is time to ru==do first run or next run
Semaphore firstRun=0,nextRun=0;
int firstSeed = atoi(argv[2]);
int nextSeed = atoi(argv[2]);
int numRandNums = atoi(argv[1]);
//Now the program is ready for first run
firstRun.signal();
//the following code is only executed when we have signal in firstRun so the wait function is used
firstRun.wait();
if(argv[3] == "F"){
srand(firstSeed);
for(int i = 0; i < numRandNums; i++){
cout << "F: " << "ID: " << getpid() << " Num: " << rand() << endl;
}
//First Run has been done so generate signal for second
nextRun.signal();
}
//similarly a wait on nextRun to ensure it executes after firt run is finished
nextRun.wait();
else if(argv[3] == "N"){
srand(nextSeed);
for(int j = 0; j < numRandNums; j++){
cout << "N: " << "ID: " << getpid() << " Num: " << rand() << endl;
}
}
}
Or you could only one semaphore nextRun as I think the use of firstRun was trivial in my code.

Reading into an Array Multiple Times

I'm having a little trouble with my code. It's pretty much supposed to open two files, and compare the first twenty line of the file "StudentAnswers.txt" [inputted as a char into a char array] against a char value in (each line of another file) "CorrectAnswers.txt" in another array at the same position (index). It's like a linear search, but the same position in the arrays. Then a report should be displayed, detailing which question the student missed, the given answer, the correct answer, and if the student passed (got >= 70%) or not, like the following:
Report for Student X:
2 (A/D), 3 (C/D), 5(D/A)
This student passed the exam!
Then it should clear the SAArray, and feed the next twenty lines from StudentAnswers.txt, and start the process all over again. I guess the program has to determine the number of students from (lines of 'StudentAnswers.txt' file / 20).
I'm having trouble displaying the report, and having the array clear itself after the program. I'm guessing this can be done with a while loop and an accumulator for the number of students (to be determined by above equation).
Also, Visual Studio seems to go to "Missed __ questions for a total of ___ %", and then keep looping -858993460.
Any help would be appreciated.
#include <iostream>
#include <fstream>
#include <string>
#include <array>
#include <algorithm>
using namespace std;
void GradeReturn(char[], char[], int, int, int);
string PassFail(float);
int main()
{
ifstream SA("StudentAnswers.txt");
ifstream CA("CorrectAnswers.txt");char CAArray[20];
char SAArray[20];
// char SA2Array[20];
bool isCorrect;
int correct;
int incorrect;
int counter;
correct = 0;incorrect = 0;
counter = 0;
cout << endl;
if (!SA.fail())
{
cout << "'StudentAnswers.txt' file opened successfully." << endl;
cout << "'CorrectAnswers.txt' file opened successfully." << endl << endl;
int a = 0;
int b = 0;
while (a < 20)
{
CA >> CAArray[a];
a++;
} // while loop to feed char into the array
while (b < 20)
{
SA >> SAArray[b];
b++;
}
} // while loop to feed char into array
CA.close(); // closing "CorrectAnswers.txt"
SA.close(); // closing "StudentAnswers.txt"
GradeReturn(&CAArray[counter], &SAArray[counter], correct, incorrect, counter);
return 0;
}
void GradeReturn(char CAArray[], char SAArray[], int correct, int incorrect, int counter)
{
float percent;
float hundred;
int student;
int catcher[20];
int writeCatcher; int starter;
int catcher_size;
student = 0;
writeCatcher = 0;
catcher_size = ((sizeof catcher) / 4);
while (counter < 20)
{
if ((CAArray[counter]) == (SAArray[counter]))
{
correct++;
cout << "Good job!" << endl;
} // correct handling
else
{
incorrect++;
cout << "You got question " << counter << " wrong." << endl;
counter >> catcher[writeCatcher];
writeCatcher++;
} // incorrect handling
counter++;
} // while loop to determine if a student got a question right or wrong
static_cast <float> (incorrect); // float conversion
cout << endl; // for cleanliness
percent = ((static_cast <float> (correct)) / 20); // percentage
hundred = percent * 100;
PassFail(percent);
if (PassFail(percent) == "pass")
{
student++;
cout << "Report for Student " << student << ":" << endl;
cout << "-----------------------------" << endl;
cout << "Missed " << incorrect << " questions out of 20 for ";
cout << hundred << " % correct." << endl << endl;
starter = 0;
while (starter < (sizeof catcher)
{
if(1=1)
{
catcher_size
}
else
{
cout << "";
starter++;
}
}
}
else if (PassFail(percent) == "fail")
{
student++;
cout << "Missed " << incorrect << " questions out of 20 for ";
cout << hundred << " % correct." << endl << endl;
while (starter < catcher_size)
{
if ((catcher[starter]) == -858993460)
{
starter++;
}
else
{
cout << "";
starter++;
}
}
}
return;
}
string PassFail(float percent)
{
if (percent >= 0.70) // if <pass>
{
return "pass";
}
else // if <fail>
{
return "fail";
}
cout << endl;
}
To get a loop you should keep streams open instead of closing them after reading 20 lines.
As pseudo code that would be:
a = 0;
while(streams_not_empty)
{
CA >> CAArray[a];
SA >> SAArray[a];
++a;
if (a == 20)
{
GradeReturn(&CAArray[counter], &SAArray[counter], correct, incorrect, counter);
a = 0; // Reset a
}
}
CA.close(); // closing "CorrectAnswers.txt"
SA.close(); // closing "StudentAnswers.txt"
You would also need to pass correct, incorrect, counter by reference so that the GradeReturn can change their value and their by do the accumulation.
Like:
void GradeReturn(char CAArray[], char SAArray[], int& correct, int& incorrect, int& counter)
Further you shouldn't rely on being able to read exactly Nx20 lines from the files every time. A file could have, e.g. 108 (5x20 + 8) lines, so you code should be able to handle the with only 8 lines. In other words, don't hard code 20 in your function like while (counter < 20). Instead pass the number of lines to be handled and do while (counter < number_to_handle).
Something like this as pseudo code:
a = 0;
while(streams_not_empty)
{
CA >> CAArray[a];
SA >> SAArray[a];
++a;
if (a == 20)
{
GradeReturn(&CAArray[counter], &SAArray[counter], correct, incorrect, counter, a);
// ^
a = 0; // Reset a
}
}
if (a != 0)
{
// Process the rest
GradeReturn(&CAArray[counter], &SAArray[counter], correct, incorrect, counter, a);
}
CA.close(); // closing "CorrectAnswers.txt"
SA.close(); // closing "StudentAnswers.txt"
One problem you have is you're trying to compare C-style strings with the == operator. This will compare them essentially as if they were pointers to char, i.e. compare whether they point at the same location in memory, not compare the contents of the string. I urge you to look up array-decay and c-string variables to understand more.
Specifically, if (PassFail(percent) == "pass") isn't going to do what you want it to. strcomp doc, strncmp doc using std::string variables instead of c-style strings would all work, but it would be better simply to compare percent to a value, i.e. if(percent >= 0.70 directly instead of calling PassFail and comparing a string.
There are many other issues here also, you at one point call PassFail but do nothing with the return value. The only side affect of PassFail is cout << endl, if that's what you intend, it's a poor decision and hard to read way to put a newline on the console.
Try asking your compiler for more warnings, that's often helpful in finding these types of issues. -Wall -Wextra work for gcc, you may have to read your compiler manual...

C++ - How to count how many times occur the same string in a list

I searched a lot on google and stackoverflow but I couldn't find my answer. I'm actually reading a C++ book (C++ Primer 5th Edition) and they're asking me to do an exercise.
"Write a program that reads several transactions and counts how many transactions occur for each ISBN" (Console Project)
This is my code atm :
Sales_item currentItem, item;
if (cin >> currentItem)
{
int cnt = 1;
while (cin >> item)
{
if (currentItem.isbn() == item.isbn())
{
++cnt;
}
else
{
cout << currentItem.isbn() << " occurs " << cnt << " times " << endl;
cnt = 1;
currentItem = item;
}
}
cout << item.isbn() << " occurs " << cnt << " times " << endl;
}
I won't explain how work the transactions so I'm gonna ask it in another way.
I type in my console 6(or more) random strings as exemple:
101A
102A
101A
101A
103A
102A
I want the result the result (output) to be:
101A occurs 3 times.
102A occurs 2 times.
103A occurs 1 times.
How would you do that?
Using std::map instead of list will be easier.
int main()
{
map<string,int> stringMap;
for (int i=0;i<3;i++)
{
cout<<"Enter string: ";
string s;
cin>>s;
if(stringMap.find(s)!=stringMap.end())
{
stringMap[s]++;
}
else
{
stringMap[s]=1;
}
}
for (map<string,int>::const_iterator itr = stringMap.cbegin(); itr!=stringMap.cend(); ++itr)
{
if(itr->second > 1)
cout<<itr->first << " occurs "<<itr->second<<" times"<<endl;
else
cout<<itr->first << " occurs "<<itr->second<<" time"<<endl;
}
return 0;
}
There are multiple approaches to a question like this, so the best would depend on your constraints. My approach would be:
while(GetInputString(str)) {
myStruct* ptr = existingList.Find(str);
if (!ptr) {
existingList.Add(str);
} else {
ptr->IncrementCount();
}
}
I've tried not to solve your problem for you - hopefully the answer gives you a template to work with...
#include <iostream>
#include <vector>
#include "Sales_item.h"
using namespace std;
void book_transactions(string isbn, int count);
int main()
{
vector<Sales_item> book_vec;
Sales_item book;
int total_transactions = 1;
// Reads in Sales_item objects
while (cin >> book)
{
book_vec.push_back(book);
}
// Compares ISBNs in vector, if two isbns are equal total transactions increases
for (int i = 0; i < book_vec.size() - 1; i++)
{
if (book_vec[i].isbn() == book_vec[i+1].isbn())
{
total_transactions = book_vec[i].get_units_sold() + book_vec[i+1].get_units_sold();
book_transactions(book_vec[i].isbn(), total_transactions);
}
}
}
void book_transactions(string isbn, int count)
{
cout << "ISBN: " << isbn << " " << "Transactions: " << count << endl;
}
I went into the Sales_item.h class and added a method to get the number of units sold. There was already a class member (unsigned return type) under private. I just created a getter and then created a vector of Sales_items. This solution seems to work. I'm sure the intended problem is not for an N set of sales_items, however this should work as a "duct-tape" solution. There is no need to play around with pointers at this point. A simple vector array and an algorithm to compare adjacent objects works just fine.

c++ while loop do max 1 time

class knygos {
public:
int nr;
char pavadinimas[25];
char autorius[25];
int egz_sk;
void go_to(int x, int y) {
COORD c;
c.X = x - 1;
c.Y = y - 1;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
}
void knygu_sarasas() {
ifstream myFile("data.bin", ios::in | ios::binary);
while (myFile.read ((char *) this, sizeof (knygos))) {
go_to(2,6);
cout << nr << endl;
cout << "Pavadinimas" << pavadinimas << endl;
cout << "Autorius" << autorius << endl;
cout << "Egzemploriai "<< egz_sk << endl;
}
myFile.close();
}
};
void main() {
knygos ob;
ob.knygu_sarasas();
}
Why when I use function go_to(2,6); while loop work only 1 time, when i not use this function loop work normaly (6 times) I not know where is problem, plese help guys ;)
Do you realize that if you set the cursor IN the loop to the (2, 6) position, all interation will wite to the SAME place, effetivly overwriting each other, and only producing "one" output for all 6 or many cicles?
You can using ncurses library for type of input such as keyboard/mouse and and output such as screen.If you use mvprintw() family functions,You can set X and Y same as gotoxy in DOS.
I forgot cout and cin and use ncurses library, you can learn it from here.