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.
Related
The example I talked about is this one on cppreference.com.
The code snippet is pasted below.
int main(){
const std::size_t ThreadNumber = 5;
const int Sum = 5;
std::atomic<int> atom{0};
std::atomic<int> counter{0};
// lambda as thread proc
auto lambda = [&](const int id){
for (int next = 0; next < Sum;){
// each thread is writing a value from its own knowledge
const int current = atom.exchange(next);
counter++;
// sync writing to prevent from interrupting by other threads
std::osyncstream(std::cout)
<< '#' << id << " (" << std::this_thread::get_id()
<< ") wrote " << next << " replacing the old value "
<< current << '\n';
next = std::max(current, next) + 1;
}
};
std::vector<std::thread> v;
for (std::size_t i = 0; i < ThreadNumber; ++i){
v.emplace_back(lambda, i);
}
for (auto& tr : v){
tr.join();
}
std::cout << ThreadNumber << " threads adding 0 to "
<< Sum << " takes total "
<< counter << " times\n";
}
To me, the value of counter is 25 because 5 threads and each thread loops 5 times. However, the shown output is 16. I also ran it myself, the possible value varies, but it never gets to be 25.
Why the printed value of counter is actually smaller?
Consider one of the possible executions:
Lets say one of the threads finishes the loop before other threads start.
This gives you atom == 4. The next thread to enter the loop will get current == 4 and will exit the loop after the first iteration.
This way the second thread increments current once instead of 5 times like you expect it to.
I haven't taken the trouble to analyse the code in detail, but the for loop in the lambda is broken (or, at least, not doing what you are expecting it to do). If you replace it with something more straightforward, namely:
for (int next = 0; next < Sum; ++next){
then 25 is output.
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
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...
My apologies if this question looks simple. I'm still learning about threads. I already tried searching for a solution to this on here but didn't find any.
I'm trying to get my program to create a number of threads based on user input (ex: "cin >> 5" will create 5 threads) but it says the "i" in "threads myThreads[ i ]" needs to be a constant value. The code is below:
void exec(int n)
{
cout << "Thread " << n << endl;
}
int main()
{
int numThreads = 0;
// create threads
cin >> numThreads;
thread myThreads[numThreads]; // this part says myThreads "must be a constant value"
for (int i = 0; i < numThreads; i++)
{
myThreads[i] = thread(exec, i);
}
for (int i = 0; i < numThreads; i++)
{
myThreads[i].join();
}
cout << "Done!" << endl;
}
Any ideas as to how that section can be fixed? I've tried a few different ways but they haven't worked so far. Thank you very much.
There's no problem with multithreading. The problem is static array that you using as dynamic array.
Try something like this:
thread* myThreads = new thread[numThreads];
More about dynamic memory in C++:
http://www.cplusplus.com/doc/tutorial/dynamic/
UPD By James Adkison:
Do not forget to delete[] your array to avoid memory leaking.
How can I do something in parallel inside for loop? I mean that loop should be executed in one thread but his body should be executed parallel. But this code hasn't work:
int main(){
int ID;
int PROCESSES;
int source;
int dest;
int tag = 50;
char message[100];
MPI::Status status;
for (int i = 0; i < 2; i++){
MPI::Init();
ID = MPI::COMM_WORLD.Get_rank();
cout << "some text " << ID << " " << i << endl;
MPI::Finalize();
}
}
I think you have some misunderstanding about what MPI is. MPI doesn't automatically parallelize code, but gives you the ability to send messages from one process to another. When you execute your application, you say how many "copies" of the program to execute and then within the program, you explicitly tell MPI to send data from one process to another.
There are some very specific problems in your code as well. You can only call MPI_Init and MPI_Finalize once per process and it should be the first and last thing in your code. So your code should look something like this:
int main(){
int ID;
int PROCESSES;
int source;
int dest;
int tag = 50;
char message[100];
MPI::Status status;
MPI::Init();
ID = MPI::COMM_WORLD.Get_rank();
for (int i = 0; i < 2; i++){
cout << "some text " << ID << " " << i << endl;
}
MPI::Finalize();
}
Obviously, that code doesn't do anything useful, but just prints out each process's rank three times, but it's an example.
I'd recommend finding a good example of using MPI on the web. Your favorite search engine should be your friend here.