Yagimutsu
Yagimutsu

Reputation: 57

Error Code: C2661: no overloaded function takes 6 arguments

This program does takes file names from a Queue ,after user entered them, which is myQue then put them into the mainQue after that it opens those files and decrypts them if possible. If decryption is successful then it writes the decrypted data into a new file.

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

I have checked everything but I cannot understand why the compiler gives me this error. I am using Microsoft Visual Studio 2015.

Upvotes: 0

Views: 1337

Answers (1)

rafix07
rafix07

Reputation: 20936

Read about thread constructor (here) and reference_wrapper

The arguments to the thread function are moved or copied by value. If a reference argument needs to be passed to the thread function, it has to be wrapped (e.g. with std::ref or std::cref).

Signature of your function is

void producer(Queue &myQue, Queue &mainQue , int thrNum, int time,string &input)

so you have to change the call of thread constructor to

prodThr[i] = thread(&producer, std::ref(myQue), std::ref(mainQue), 
   i + 1, time1[i], std::ref(inputFileName));

do the same for consumer function.

Upvotes: 2

Related Questions