Từ 1 tới 8 trên tổng số 8 kết quả

Đề tài: Cách cài đặt thời gian cho vòng lặp để bỏ qua lệnh cin?

  1. #1
    Ngày gia nhập
    12 2014
    Bài viết
    1

    Mặc định Cách cài đặt thời gian cho vòng lặp để bỏ qua lệnh cin?

    #include <iostream>
    using namespace std;

    void main()
    {
    int n = 0;
    while (true)
    {
    cin >> n;
    cout << n << endl;
    }
    }

    Ví dụ mình có đoạn chương trình trên. Làm thế nào để: Nếu sau 5 giây người dùng không nhập dữ liệu thì chương trình sẽ bỏ qua dòng lệnh cin >> n; và tiếp tục thực hiện các lệnh kế tiếp.
    Đã được chỉnh sửa lần cuối bởi Otomo : 02-12-2014 lúc 11:24 PM.

  2. #2
    Ngày gia nhập
    04 2011
    Nơi ở
    Hà Nội
    Bài viết
    248

    giải pháp ko được đẹp đẽ cho lắm: chỉ chạy trên windows
    hàm waitForInput sẽ chờ người dùng nhập đến khi ký tự delim được nhập vào hoặc hết thời gian chờ timeOut (tính theo ms) sau đó trả về các kí tự đã được nhập. Mỗi khi người dùng nhập 1 kí tự, thời gian chờ sẽ tự động quay về timeOut (tức là người dúng sẽ có timeOut ms nữa để nhập, nếu ko là hết cơ hội)
    C++ Code:
    1. #include <conio.h>
    2. #include <windows.h>
    3. #include <string>
    4. #include <iostream>
    5.  
    6. std::string waitForInput(unsigned int timeOut, char delim = '\r')
    7. {
    8.     std::string buff;
    9.     DWORD waitUntil = GetTickCount() + timeOut;
    10.     DWORD timeLeft = timeOut;
    11.     HANDLE stdInput = GetStdHandle(STD_INPUT_HANDLE);
    12.     while (true) {
    13.         if (WaitForSingleObject(stdInput, timeLeft) != WAIT_OBJECT_0) {
    14.             break;
    15.         }
    16.  
    17.         DWORD now = GetTickCount();
    18.  
    19.         if (kbhit()) {
    20.             int ch = getch();
    21.             std::cout << static_cast<char>(ch);
    22.                         if (ch == delim) {
    23.                 break;
    24.             }
    25.             buff.push_back(static_cast<char>(ch));
    26.             timeLeft = timeOut;
    27.             waitUntil = now + timeOut;
    28.         } else {
    29.             if (now >= waitUntil) {
    30.                 break;
    31.             }
    32.             timeLeft = waitUntil - now;
    33.         }
    34.        
    35.     }
    36.  
    37.     return buff;
    38.  
    39. }
    40.  
    41.  
    42.  
    43. int main()
    44. {
    45.     std::cout << waitForInput(5000); //chờ 5000 ms = 5s
    46. }
    Đã được chỉnh sửa lần cuối bởi greigaz : 02-12-2014 lúc 04:36 AM.

  3. #3
    Ngày gia nhập
    10 2014
    Bài viết
    13

    Đối với dạng toán này thì chỉ có cách dùng thread mới giải quyết vấn đề. Bạn tham khảo nhé

    Code:
    #include <windows.h>
    #include <iostream>
    
    using namespace std;
    
    namespace jsw {
    namespace threading {
    		class auto_event {
    			public:
    			auto_event(): _event(CreateEvent(0, false, false, 0)) {}
    			BOOL wait(DWORD timeout = 1) const
    			{
    			return WaitForSingleObject(_event, timeout) == WAIT_OBJECT_0;
    			}
    			BOOL set() { return SetEvent(_event); }
    			private:
    			HANDLE _event;
    		};
    		class thread {
    			public:
    			static thread start(
    			LPTHREAD_START_ROUTINE fn, LPVOID args = 0,
    			DWORD state = 0, DWORD timeout = 5000)
    			{
    			return thread(CreateThread(0, 0, fn, args, state, 0), timeout);
    			}
    			static void sleep(DWORD milliseconds) { Sleep(milliseconds); }
    			static void exit(DWORD exitCode) { ExitThread(exitCode); }
    			public:
    			thread(HANDLE thread, DWORD timeout): _thread(thread), _timeout(timeout) {}
    			~thread() { CloseHandle(_thread); }
    			DWORD exit_code() const
    			{
    			DWORD exitCode = NO_ERROR;
    			GetExitCodeThread(_thread, &exitCode);
    			return exitCode;
    		}
    		HANDLE handle() const { return _thread; }
    		BOOL is_alive() const { return exit_code() == STILL_ACTIVE; }
    		DWORD join() { return WaitForSingleObject(_thread, _timeout); }
    		DWORD suspend() { return SuspendThread(_thread); }
    		DWORD resume() { return ResumeThread(_thread); }
    		BOOL abort(DWORD exitCode) { return TerminateThread(_thread, exitCode); }
    
    		private:
    		HANDLE _thread;
    		DWORD _timeout;
    		};
    	}
    }
    #include <iostream>
    #include <string>
    int n;
    DWORD WINAPI get_n(LPVOID args)
    {
    	using namespace jsw::threading;
    	n = (int)((LPVOID*)args)[0];
    	auto_event *e = (auto_event*)((LPVOID*)args)[1];
    	cin>>n;
    	e->set();
    	return NO_ERROR;
    }
    int main()
    {
    	using namespace jsw::threading;
    	
    	auto_event e;
    	LPVOID args[2] = {&n, &e};
    	thread worker = thread::start(get_n, args);
    	if (e.wait(5000))
    	cout<<'\n'<< n <<"";
    
    	else {
    	worker.abort(NO_ERROR);
    	cout<< "time out";
    
    	}
        system("pause");
    }
    Học lập trình bắt đầu từ đâu ?

    www.laptrinhCcanban.com

  4. #4
    Ngày gia nhập
    04 2011
    Nơi ở
    Hà Nội
    Bài viết
    248

    Trích dẫn Nguyên bản được gửi bởi programmer_2014 Xem bài viết
    Đối với dạng toán này thì chỉ có cách dùng thread mới giải quyết vấn đề. Bạn tham khảo nhé

    Code:
    #include <windows.h>
    #include <iostream>
    ....
    có thể WaitForSingleObject trên cái handle của thread luôn, ko cần tạo event
    thread ko phải là cách duy nhất. Trường hợp này dùng thread lại ko hay lắm vì:
    1. Không kiểm soát được thời gian, người dùng đang nhập dở cũng có thể bị báo timeout
    2. TerminateThread
    3. Sau khi timeout (thread bị terminate), không thể gọi std::cin tiếp được nữa.
    P/S: nhớ ghi nguồn nhé bạn
    daniweb.com/software-development/cpp/threads/376986/timing-cmd-
    Đã được chỉnh sửa lần cuối bởi greigaz : 03-12-2014 lúc 03:43 PM.

  5. #5
    Ngày gia nhập
    07 2011
    Bài viết
    474

    @greigaz: cái hàm WaitForSingleObject là để làm gì @_@

    ta nhớ cái này trong này có người viết rồi :-? Có xử lý cái backspace nữa:
    if (c == '\b' || c == 0x7f) std::cout << "\b \b";

    trong vòng lặp while(1) thì còn phải thêm
    Sleep(16);
    để cho CPU đỡ kêu nữa

  6. #6
    Ngày gia nhập
    04 2011
    Nơi ở
    Hà Nội
    Bài viết
    248

    Mặc định Cách cài đặt thời gian cho vòng lặp để bỏ qua lệnh cin?

    Trích dẫn Nguyên bản được gửi bởi INTP Xem bài viết
    @greigaz: cái hàm WaitForSingleObject là để làm gì @_@

    ta nhớ cái này trong này có người viết rồi :-? Có xử lý cái backspace nữa:
    if (c == '\b' || c == 0x7f) std::cout << "\b \b";

    trong vòng lặp while(1) thì còn phải thêm
    Sleep(16);
    để cho CPU đỡ kêu nữa
    WaitForSingleObject là hàm API của windows để đợi 1 cái HANDLE nào đấy. Đợi đến khi nào thì tùy từng loại HANDLE. Vì là "Wait" nên ko lo tốn CPU, ko cần Sleep
    Mới đầu cũng search google mà ko thấy cái nào ổn cả nên thử nghịch xem sao
    Đúng là chưa tính đến xử lý cái backspace đấy

  7. #7
    Ngày gia nhập
    07 2011
    Bài viết
    474

    cái wait đó cứ bấm 1 phím là nó đợi thêm 5000 ms nên cả hàm có thể input hơn 5 giây @_@

    sleep cho nó chính xác. Thêm 1 hàm ktra xem ký tự nhập vào có nên in ra ko (http://www.cplusplus.com/reference/cctype/, có lẽ là ktra isgraph và isspace) thì in ra, còn ko thì đừng in :-?

    C++ Code:
    1. std::string timedInput(int ms)
    2. {
    3.   clock_t stop = clock() + static_cast<double>(ms)/1000 * CLOCKS_PER_SEC;
    4.   std::string s;
    5.   while (clock() <= stop)
    6.   {
    7.     if (kbhit()) {
    8.       char c = getch();
    9.       //xử lý c...
    10.     }
    11.     Sleep(16);
    12.   }
    13.   return s;
    14. }

    clock() là hàm chuẩn của C (có trong ctime), lấy số tick từ khi bắt đầu chương trình thì phải, Windows thì 1 giây nó tick 64 lần nên thường thường đo thời gian ko cần chính xác lắm người ta xài clock() nên thường trả về 0.015s là vậy ~ 1000/64 ~ 15ms ~ 0.015s. Mà đúng hơn thì hình như Linux CLOCKS_PER_SEC là 1000 nên clock() trả về chính xác tới ms nên người ta viết đo thời gian xài clock() cho code chuẩn, chuyển qua windows thì CLOCKS_PER_SEC là 64 => 0.015 0.031 thay vì 0.007 0.018 v.v...

    viết vậy thì chỉ có kbhit() và getch() là cần đến conio.h thôi @_@ chuyển qua mấy OS khác ngoài Windows thì chỉ cần tìm 2 hàm này...
    Đã được chỉnh sửa lần cuối bởi INTP : 04-12-2014 lúc 08:00 AM.

  8. #8
    Ngày gia nhập
    04 2011
    Nơi ở
    Hà Nội
    Bài viết
    248

    Trích dẫn Nguyên bản được gửi bởi INTP Xem bài viết
    cái wait đó cứ bấm 1 phím là nó đợi thêm 5000 ms nên cả hàm có thể input hơn 5 giây @_@

    sleep cho nó chính xác. Thêm 1 hàm ktra xem ký tự nhập vào có nên in ra ko (http://www.cplusplus.com/reference/cctype/, có lẽ là ktra isgraph và isspace) thì in ra, còn ko thì đừng in :-?
    ...
    ban đầu ko muốn busy wait nên mới dùng WaitForSingleObject Nhưng cách này portable hơn
    còn cái nhấn 1 phím cho thêm 5s vì ta ko muốn đang nhập dở thì bị timeout

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn