此程序的确从队列中获取文件名,在用户输入文件名后,该文件名即为 myQue ,然后将其放入 mainQue 中,然后打开这些文件并将其解密。如果可能的话。如果解密成功,则它将解密后的数据写入新文件。
Main.cpp
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include "Queue.h"
#include "randgen.h"
#include <thread>
#include <mutex>
using namespace std;
Queue myQue; //My structure to store the file names
Queue mainQue; //Main que for the threads
RandGen Ran; //Random Generator object
// Mutexes for certain restrictions
std::mutex mtx_blockMyQue, mtx_blockMainQue, mtx_blockPrint;
//Function for decrypt the message
void decipher(string str, int shift)
{
for (int i = 0; i < str.length(); ++i)
{
if (str[i] >= 'a' && str[i] <= 'z')
{
str[i] = str[i] + shift;
}
}
}
//Function for finding the most frequent letter
char mostFrequent(string text)
{
int max = 0;
int count = 0;
char maxCharcter;
for (char q = 'a'; q <= 'z'; q++)
{
count = 0;
for (int i = 0; i<text.length(); i++)
{
if (text[i] == q)
count++;
}
if (count>max)
{
max = count;
maxCharcter = q;
}
}
return maxCharcter;
}
void sleepThr(int thrNum, int time)
{
mtx_blockPrint.lock();
this_thread::sleep_for(chrono::milliseconds(time));
cout << "Producer Thread - " << thrNum << " starts sleeping for " << time << "milliseconds" << endl;
mtx_blockPrint.unlock();
}
//What producer threads do
void producer(Queue &myQue, Queue &mainQue , int thrNum, int time,string &input)
{
this_thread::sleep_for(chrono::milliseconds(time)); //Sleep thread
cout << "Producer Thread - " << thrNum << " starts sleeping for " << time << "milliseconds" << endl;
//sleepThr(thrNum, time);
mtx_blockMyQue.lock(); //Thread locked
if (myQue.isEmpty()==false)
{
cout << "Producer Thread - " << thrNum << " is now enqueuing '" << input << "'" << endl;
//Value to be dequeued and then to be enqueued
//Dequeueing the value
mainQue.enqueue(input); //Enqueueing the value
}
mtx_blockMyQue.unlock(); //Thread unlocked
//mtx_blockPrint.lock(); //Thread locked
this_thread::sleep_for(chrono::milliseconds(time)); //Sleep thread
cout << "Producer Thread - " << thrNum << " starts sleeping for " << time << "milliseconds" << endl;
//mtx_blockPrint.unlock(); //Thread unlocked
}
//What consumer threads do
void consumer(Queue &mainQue, int thrNum , int time , string &input, fstream &reader)
{
//this_thread::sleep_for(chrono::milliseconds(time)); //Sleep thread
//cout << "Consumer Thread - " << thrNum << " starts sleeping for " << time << "milliseconds" << endl;
mtx_blockPrint.lock(); //Thread locked
this_thread::sleep_for(chrono::milliseconds(time)); //Sleep thread
cout << "Consumer Thread - " << thrNum << " starts sleeping for " << time << "milliseconds" << endl;
mtx_blockPrint.unlock(); //Thread unlocked
mtx_blockMainQue.lock();
cout << "Consumer Thread - " << thrNum << " is now handling '" << input << "'" <<endl;
string line;
reader.open(input);
if (!reader.is_open())
{
cout << "Consumer Thread - " << thrNum << " cannot process '" << input << "', there is no such file!" << endl;
}
else
{
getline(reader, line, '.'); //Read file ignoring '.'
char mostChr = mostFrequent(line); //The most frequent char
char e = 'e';
int intChr = mostChr; //Decimal of the most frequent char
int intE = e; //Decimal of the char 'e'
int shiftNum = intChr - intE; //Shift number
decipher(line, shiftNum); //Decrypting the message
string outputFile = input + "_decrypted.txt";
ofstream output(outputFile); //Opening a new output file for decrypted message
output << line; //Putting the decrypted message into the file
output.close(); //Closing the output file
cout << "Consumer Thread - " << thrNum << " is done handling " << input << " with a shift of " << shiftNum << " and written the result to '" << outputFile << "'" << endl;
}
reader.close();
mtx_blockMainQue.unlock();
}
int main() {
fstream reader; //Reader
string inputFileName; //File name
int time1[2], time2[3];
cout << "Enter a file name: ";
cin >> inputFileName;
myQue.enqueue(inputFileName); //Storing the file name in my structure
//Do this task until the dash(-) character entered
while(inputFileName != "-")
{
cout << "Enter a file name: ";
cin >> inputFileName;
myQue.enqueue(inputFileName);
}
thread prodThr[2]; //Constructing Producer Threads
thread consThr[3]; //Constructing Consumer Threads
/*
for (int i = 0; i < 1; i++) {
time1[i] = Ran.RandInt(1000, 4000);
prodThr[i] = thread(&sleepThr, i + 1, time1[i]);
}
for (int i = 0; i < 2; i++)
{
time2[i] = Ran.RandInt(2500, 3500);
consThr[i] = thread(&sleepThr, i + 1, time2[i]);
}
*/
while (myQue.isEmpty() == false)
{
for (int i = 0; i<2; i++) {
time1[i] = Ran.RandInt(1000, 4000);
myQue.dequeue(inputFileName);
prodThr[i] = thread(&producer, myQue, mainQue, i + 1, time1[i], inputFileName);
}
for (int i = 0; i<3; i++) {
time2[i] = Ran.RandInt(2500, 3500);
if (mainQue.isEmpty() == false)
{
mainQue.dequeue(inputFileName);
consThr[i] = thread(&consumer, mainQue, i + 1, time2[i], inputFileName, reader);
}
}
//Joining Producer Threads
for (int i = 0; i < 2; i++) {
prodThr[i].join();
}
//Joining Consumer Threads
for (int i = 0; i<3; i++) {
consThr[i].join();
}
}
return 0;
}
Queue.cpp
#include <iostream>
#include "Queue.h"
using namespace std;
//************************************************
// Constructor. Generates an empty queue *
//************************************************
Queue::Queue()
{
front = nullptr;
rear = nullptr;
}
//********************************************
// Function enqueue inserts the value in num *
// at the rear of the queue. *
//********************************************
void Queue::enqueue(string val)
{
if (isEmpty()) //if the queue is empty
{ //make it the first element
front = new QueueNode(val);
rear = front;
}
else //if the queue is not empty
{ //add it after rear
rear->next = new QueueNode(val);
rear = rear->next;
}
}
//**********************************************
// Function dequeue removes the value at the *
// front of the queue, and copies it into num. *
//**********************************************
void Queue::dequeue(string &val)
{
QueueNode *temp;
if (isEmpty())
{
exit(1);
}
else //if the queue is not empty
{ //return front's value, advance front and delete old front
val = front->value;
temp = front;
front = front->next;
delete temp;
}
}
//*********************************************
// Function isEmpty returns true if the queue *
// is empty, and false otherwise. *
//*********************************************
bool Queue::isEmpty() const
{
if (front == nullptr)
return true;
else
return false;
}
//********************************************
// Function clear dequeues all the elements *
// in the queue. *
//********************************************
void Queue::clear()
{
string val; // Dummy variable for dequeue
while(!isEmpty())
dequeue(val); //delete all elements
}
Queue.h
#ifndef DYNINTQUEUE_H
#define DYNINTQUEUE_H
#include <string>
using namespace std;
struct QueueNode
{
string value;
QueueNode *next;
QueueNode(string val, QueueNode *ptr = nullptr)
{
value = val;
next = ptr;
}
};
class Queue
{
private:
// These track the front and rear of the queue.
QueueNode *front;
QueueNode *rear;
public:
// Constructor.
Queue();
// Member functions.
void enqueue(string);
void dequeue(string &);
bool isEmpty() const;
void clear();
};
#endif
randgen.cpp
#include <time.h> // for time()
#include <stdlib.h> // for rand/srand
#include "randgen.h"
#include <cmath>
#include <iostream>
using namespace std;
int RandGen::ourInitialized = 0;
void RandGen::SetSeed(int seed)
// postcondition: system srand() used to initialize seed
// once per program (this is a static function)
{
if (0 == ourInitialized)
{ ourInitialized = 1; // only call srand once
srand(seed); // randomize
}
}
RandGen::RandGen()
// postcondition: system srand() used to initialize seed
// once per program
{
if (0 == ourInitialized)
{ ourInitialized = 1; // only call srand once
time_t now;
time (&now); // localtime bir zamandan itibaren geçen saniye formatında
// now değişkenine kaydedilir.
srand(int((sin(double(now))*1000000)));//Gökhan
// seed'imiz her saniye bir artmasın diye
// daha random artsın diye sinusunu alıyorum
// srand(unsigned(time(0))); // randomize
}
}
int RandGen::RandInt(int max)
// precondition: max > 0
// postcondition: returns int in [0..max)
{
return int(RandReal() * max);
}
int RandGen::RandInt(int low, int max)
// precondition: low <= max
// postcondition: returns int in [low..max]
{
return low + RandInt(max-low+1);
}
double RandGen::RandReal()
// postcondition: returns double in [0..1)
{
return rand() / (double(RAND_MAX) + 1);
}
double RandGen::RandReal(double low, double high)
{
double width = fabs(high-low);
double thelow = low < high ? low : high;
return RandReal()*width + thelow;
}
randgen.h
#ifndef _RANDGEN_H
#define _RANDGEN_H
#include <limits.h> // for INT_MAX
// designed for implementation-independent randomization
// if all system-dependent calls included in this class, then
// other classes can make use of this class in independent manner
// all random numbers are uniformly distributed in given range
//
// RandGen() --- constructor sets seed of random # generator
// once per program, not per class/object
//
// RandInt(int max)
// RandInt(int low,int max) - return random integer in range [0..max)
// when one parameter used, [low..max] when
// two parameters used
//
// examples: rnd.RandInt(6) is random integer [0..5] or [0..6)
// rnd.RandInt(3,10) is random integer [3..10]
// rnd.RandInt() is random integer [0..INT_MAX)
//
// RandReal() -- returns random double in range [0..1)
// RandReal(double low, double max) -- random double in range [low..max)
class RandGen
{
public:
RandGen(); // set seed for all instances
int RandInt(int max = INT_MAX); // returns int in [0..max)
int RandInt(int low, int max); // returns int in [low..max]
double RandReal(); // returns double in [0..1)
double RandReal(double low, double max); // range [low..max]
static void SetSeed(int seed); // static (per class) seed set
private:
static int ourInitialized; // for 'per-class' initialization
};
#endif
我已经检查了所有内容,但是我不明白为什么编译器会给我这个错误。我正在使用Microsoft Visual Studio 2015。
答案 0 :(得分:2)
了解thread
构造函数(here)和reference_wrapper
线程函数的参数按值移动或复制。如果需要将引用参数传递给线程函数,则必须将其包装(例如,使用std :: ref或std :: cref)。
您的功能签名是
void producer(Queue &myQue, Queue &mainQue , int thrNum, int time,string &input)
因此您必须将 thread 构造函数的调用更改为
prodThr[i] = thread(&producer, std::ref(myQue), std::ref(mainQue),
i + 1, time1[i], std::ref(inputFileName));
对consumer
函数执行相同操作。