2015-09-17 4 views
0

Я начал изучать манипуляции с потоками и начал с простой программы, предназначенной для генерации случайных заглавных букв. Буквы произвольно генерируются и добавляются в массив символов через производителя, а любые добавленные выводятся как строчные. Потребитель просто выводит обычную заглавную букву из массива char. До сих пор у меня было следующее:Продюсер-потребитель в C++ 11

#include <iostream>   
#include <thread>    
#include <mutex>    
#include <condition_variable> 
#include <random> 

std::mutex mtx; 
std::condition_variable cv; 

int count = 0, buff_size = 0; 
char* buff; 

int random_int(int lower_bound) { 
    std::random_device seed; 
    std::mt19937 generator(seed()); 
    std::uniform_int_distribution<int> dist(lower_bound, std::nextafter(26, DBL_MAX)); 

    return dist(generator); 
} 

char random_char(int lower_bound) { 
    return 'A' + (random_int(lower_bound) % 26); 
} 

/* Consumer 

Reads characters from the buffer and prints them. 

*/ 
void consume(int job) { 
    std::unique_lock<std::mutex> lck(mtx); 

    while (count == 0) { 
     cv.wait(lck); 
    } 

    /* 
    job + 1 = Running 
    job = Ready 
    */ 
    for (int i = 0; i < buff_size; i++) { 
     std::cout << buff[i] << std::endl; 
    } 

    count--; 
} 

/* Producer 

Randomly generates letters at (pos > buff_size & pos <= 26), 
inserts them at the next available position in the buffer, 
and then prints out the lowercase form of the inputted letter. 

*/ 
void produce(int job) { 
    std::unique_lock<std::mutex> lck(mtx); 

    for (int i = 0; i < buff_size; i++) { 
     buff[i] = random_char(buff_size); 
     std::cout << tolower(buff[i]) << std::endl; 
    } 

    count++; 
    cv.notify_one(); 
} 

int main() { 
    int buf_size = 0; 

    std::cout << "The Producer-Consumer Problem (in C++11!)" << std::endl << "Enter the buffer size: "; 
    std::cin >> buf_size; 

    if (buf_size > 0 && buf_size <= 26) { 
     // set the buffer size 
     buff_size = buf_size; 
     buff = new char[buff_size]; 
    } 
    else { 
     // rage quit 
     exit(1); 
    } 

    std::thread production[10], processed[10]; 

    /* Initialize the arrays */ 
    for (int order = 0; order < buff_size; order++) { 
     production[order] = std::thread(produce, order); 
     processed[order] = std::thread(consume, order); 
    } 

    /* Join the threads to the main threads */ 
    for (int order = 0; order < buff_size; order++) { 
     processed[order].join(); 
     production[order].join(); 
    } 

    // free the allocated memory 
    delete[] buff; 
} 

Мой выход, однако, представляет собой смесь заглавных букв и случайных чисел. Что не так? Это мой первый эксперимент, так что будьте осторожны. :)

+2

Вы отметили C++ 11 в этом сообщении, и я также вижу в вашем коде 'buff = new char [buff_size]'. Я бы рекомендовал использовать 'std :: vector' вместо массива или, по крайней мере, с помощью интеллектуального указателя типа' std :: unique_ptr' или 'std :: shared_ptr' для управления динамически распределенными вещами - они помогут вам не забудьте удалить их. – Steve

+0

'std :: tolower' возвращает' int'. – zch

+0

@Steve Спасибо за рекомендацию! Я собирался использовать такую ​​структуру данных, как это, но поскольку это моя первая попытка, я просто хотел визуализировать все вместе. Не уверен, действительно ли это вопрос SO или CR. Не могли бы вы отправить ответ на некоторые примеры этих структур данных? Последние два для меня новы. – T145

ответ

3

выход однако представляет собой смесь заглавных букв и случайных чисел.

См. Комментарий zch. Я думаю, что он имел в виду:

Вместо:

std::cout << tolower(buff[i]) << std::endl; 

попробовать

std::cout << char(tolower(buff[i])) << std::endl; 

или

std::cout << (char)tolower(buff[i]) << std::endl; 

Поскольку C++ тег, вы, возможно, следует использовать static_cast

std::cout << static_cast<char>(tolower(buff[i])) << std::endl;  
+0

Поскольку это помечено C++, 'static_cast' должен быть предпочтительнее приведения в стиле C. – Snps

+0

Он отлично работает, спасибо! Для будущего потомства: SO link about static_cast. Было ли что-то, что вы видели, что было не так или могло быть улучшено в отношении моей фактической реализации производителя-cosumer? – T145

+0

@ T145 Существует еще один сайт обмена Stack под названием [Code Review] (http://codereview.stackexchange.com/), который был бы идеальным местом для запроса отзывов о рабочем коде. – Steve