hệ thống (tạm dừng trực tiếp); - Tại sao nó sai?


131

Đây là một câu hỏi mà tôi không hiểu lắm:

Lệnh system("pause");này được dạy cho các lập trình viên mới như một cách để tạm dừng chương trình và đợi đầu vào bàn phím tiếp tục. Tuy nhiên, nó dường như được nhiều lập trình viên kỳ cựu cau mày vì điều gì đó không nên được thực hiện ở các mức độ khác nhau.

Một số người nói rằng nó là tốt để sử dụng. Một số người nói rằng nó chỉ được sử dụng khi bạn bị khóa trong phòng và không có ai đang xem. Một số người nói rằng họ sẽ đích thân đến nhà bạn và giết bạn nếu bạn sử dụng nó.

Tôi, bản thân tôi là một lập trình viên mới, không được đào tạo lập trình chính thức. Tôi sử dụng nó bởi vì tôi được dạy để sử dụng nó. Điều tôi không hiểu là nếu nó không phải là thứ được sử dụng, thì tại sao tôi lại được dạy sử dụng nó? Hoặc, mặt trái, nó thực sự không phải là xấu sau tất cả?

suy nghĩ của bạn về chủ đề này là gì?



5
Rõ ràng mọi người thích các cuộc gọi của họ để tạm dừng để thực sự hiệu quả. Nói cách khác, "Nhanh lên và dừng lại!"
Lee Louviere

63
Bạn đã được dạy phải vì thường giáo viên là các lập trình viên xấu

Vui lòng đọc lời khuyên này về cách đặt câu hỏi hay: [ Cách hỏi ], [Viết câu hỏi hoàn hảo ].
Adi Inbar

9
@wich hoàn toàn vô nghĩa.
Michael Chourdakis

Câu trả lời:


85

Nó cau mày vì đây là một bản hack dành riêng cho nền tảng không liên quan gì đến việc học lập trình, mà thay vào đó là để tìm hiểu về một tính năng của IDE / OS - cửa sổ giao diện điều khiển được khởi chạy từ Visual Studio đóng khi chương trình kết thúc, và vì vậy người dùng mới không thấy đầu ra của chương trình mới.

Bodge trong Hệ thống ("tạm dừng") chạy chương trình "tạm dừng" dòng lệnh Windows và đợi cho đến khi kết thúc chương trình - cửa sổ giao diện điều khiển vẫn mở để bạn có thể đọc đầu ra.

Một ý tưởng tốt hơn sẽ là đặt một điểm dừng ở cuối và gỡ lỗi nó, nhưng điều đó một lần nữa có vấn đề.


6
Visual Studio có thể chạy chương trình ở hai chế độ: có hoặc không có gỡ lỗi. Khi chạy trong chế độ gỡ lỗi, nó sẽ dừng ở điểm ngắt đầu tiên. Nếu bạn chưa xác định, nó sẽ chạy chương trình và đóng bàn điều khiển. Vì vậy, nếu bạn muốn chương trình console dừng lại, chỉ cần đặt điểm dừng, hoặc, thậm chí tốt hơn, chạy nó mà không cần gỡ lỗi! Điều đó sẽ thực thi chương trình và dừng giao diện điều khiển.
Ivan Mesic

Đây không chỉ là một tính năng của Visual Studio - nếu bạn chạy chương trình giao diện điều khiển từ Windows (nghĩa là trái ngược với việc tải một dấu nhắc lệnh và chạy nó từ đó), nó cũng sẽ đóng khi thực hiện xong.
JBentley

2
Re1 Re Re, cửa sổ giao diện điều khiển được khởi chạy từ Visual Studio sẽ đóng khi chương trình kết thúc thực hiện, không, chỉ khi chương trình được chạy trong trình gỡ lỗi. Reem chạy chương trình "tạm dừng" dòng lệnh Windows, không có trường hợp nào ( pauselà một lệnh nội bộ cmd.exe). Danh sách các ý tưởng tốt hơn cũng thiếu trầm trọng.
Chúc mừng và hth. - Alf

Tôi nghĩ rằng câu trả lời này là người duy nhất chạm vào khía cạnh rằng đây là một cách giải quyết. Nó hoạt động xung quanh hành vi của một môi trường thực thi cụ thể sẽ đóng một cửa sổ đầu cuối trước khi bạn có thể đọc đầu ra chương trình. Điều bạn nên làm là khắc phục môi trường đó. Nếu điều đó không thể được thực hiện, hãy sử dụng cách giải quyết này, có thể chỉ khi IsDebuggerPresent()trả về đúng và ghi lại cách giải quyết này một cách chính xác ("tại sao mã này ở đây?").
Ulrich Eckhardt

43

Nó chậm. Đó là nền tảng phụ thuộc. Nó không an toàn.

Đầu tiên: Nó làm gì. Gọi "hệ thống" theo nghĩa đen giống như gõ một lệnh vào dấu nhắc lệnh của windows. Có rất nhiều thiết lập và phân tích cho ứng dụng của bạn để thực hiện cuộc gọi như vậy - và chi phí đơn giản là vô lý.

Điều gì xảy ra nếu một chương trình gọi là "tạm dừng" được đặt vào PATH của người dùng? Chỉ cần gọi hệ thống ("tạm dừng") chỉ đảm bảo rằng chương trình có tên là "tạm dừng" được thực thi (hy vọng rằng bạn không có tên thực thi có tên là "tạm dừng"!)

Chỉ cần viết hàm "Tạm dừng ()" của riêng bạn sử dụng _getch. OK, chắc chắn, _getch cũng phụ thuộc vào nền tảng (lưu ý: nó được định nghĩa trong "conio.h") - nhưng nó đẹp hơn nhiều so với việc system()bạn đang phát triển trên Windows và nó có tác dụng tương tự (mặc dù bạn có trách nhiệm cung cấp văn bản với cout hoặc hơn).

Về cơ bản: tại sao lại giới thiệu rất nhiều vấn đề tiềm ẩn khi bạn chỉ cần thêm hai dòng mã và một dòng bao gồm và có được một cơ chế linh hoạt hơn nhiều?


61
Đối với ai đó phàn nàn về sự phụ thuộc nền tảng, chắc chắn có vẻ lạ khi đề xuất _getch, đặc biệt là khi C ++ tiêu chuẩn cung cấp getchar.
paxdiablo

33
tôi cảm thấy hơi trớ trêu khi tính toán chi phí tương tác với con người)
ShPavel

1
@Spagpants: Có lẽ bạn không hiểu sự khác biệt giữa nhận đầu vào từ con người, và tạo ra hình ảnh và âm thanh người.
yzt

1
@ Cheersandhth.-Alf - Hửm? Khi tôi viết bài này, 8 năm trước, tôi vừa hoàn thành việc gỡ lỗi một vấn đề do 'hệ thống ("tạm dừng") gây ra bởi vì tên thực thi của dự án được gọi là "tạm dừng" và nó sẽ đi vào một vòng lặp vô hạn. Quan điểm của tôi vẫn đứng vững, tôi không chắc tại sao bạn nói tôi không đúng.

2
@paxdiablo getchar yêu cầu một đầu vào và sau đó nhấn enter. _getch chỉ cần một phím bấm cho dù đó là phím nào. Để giả lập _getch trên linux, bạn cần 5-6 dòng mã để thay đổi chế độ bảng điều khiển, sau đó thay đổi lại thành mặc định. Nó không giống nhau, nó làm những điều khác nhau. getchar không phải là sự thay thế cho _getch.
Barnack

29
  • chậm: nó phải vượt qua rất nhiều mã Windows không cần thiết và một chương trình riêng cho một thao tác đơn giản
  • không di động: phụ thuộc vào chương trình tạm dừng
  • phong cách không tốt: thực hiện cuộc gọi hệ thống chỉ nên được thực hiện khi thực sự cần thiết
  • gõ nhiều hơn: Hệ thống ("tạm dừng") dài hơn getchar ()

một getchar () đơn giản nên làm tốt.


26

Sử dụng system("pause");là Ungood Practice ™ vì

  • Nó hoàn toàn không cần thiết .
    Để giữ cho giao diện điều khiển cửa sổ đang mở của chương trình ở cuối khi bạn chạy nó từ Visual Studio, sử dụng Ctrl+ F5để chạy nó mà không cần gỡ lỗi, hoặc nơi khác một breakpoint ở nẹp cuối cùng đúng }của main. Vì vậy, không có vấn đề trong Visual Studio. Và tất nhiên không có vấn đề gì khi bạn chạy nó từ dòng lệnh.

  • Thật rắc rối & khó chịu
    khi bạn chạy chương trình từ dòng lệnh. Để thực hiện tương tác, bạn phải nhấn một phím ở cuối để không có mục đích gì. Và để sử dụng trong tự động hóa một số nhiệm vụ pauserất không mong muốn!

  • Nó không phải là di động.
    Unix-Land không có pauselệnh tiêu chuẩn .

Các pauselệnh là một nội cmd.exelệnh và không thể ghi đè, như là sai lầm tuyên bố trong ít nhất một câu trả lời khác. Tức là nó không phải là một rủi ro bảo mật và tuyên bố rằng các chương trình AV chẩn đoán nó cũng đáng ngờ như yêu cầu ghi đè lệnh (xét cho cùng, một chương trình C ++ systemđang ở vị trí để thực hiện tất cả những gì mà trình thông dịch lệnh có thể làm, và hơn). Ngoài ra, trong khi cách tạm dừng này cực kỳ kém hiệu quả theo các tiêu chuẩn thông thường của lập trình C ++, thì điều đó hoàn toàn không thành vấn đề khi kết thúc chương trình của người mới.

Vì vậy, các yêu cầu trong hàng loạt câu trả lời trước đây là không chính xác và lý do chính bạn không nên sử dụng system("pause") hoặc bất kỳ lệnh chờ nào khác ở cuối của bạn main, là điểm đầu tiên ở trên: nó hoàn toàn không cần thiết, nó hoàn toàn không có mục đích , nó chỉ là rất ngớ ngẩn.


1
Đôi khi cần thực hành Ungood ™ để kiểm tra nhanh .... cái mà chúng ta gọi là "nhanh và bẩn"
Michael Haephrati

22

Tóm lại, nó phải tạm dừng thực thi chương trình và thực hiện cuộc gọi hệ thống và phân bổ các tài nguyên không cần thiết khi bạn có thể sử dụng một cái gì đó đơn giản như cin.get (). Mọi người sử dụng Hệ thống ("PAUSE") vì họ muốn chương trình đợi cho đến khi họ nhấn enter để họ có thể thấy đầu ra của họ. Nếu bạn muốn một chương trình chờ đầu vào, có các hàm được tích hợp cho các chức năng cũng đa nền tảng và ít đòi hỏi hơn.

Giải thích thêm trong này bài viết.


Wow, bạn một lần nữa! bạn sống ở đây à? Dù sao, cảm ơn, tôi sẽ đọc một số. Trong khi đó, suy nghĩ của bạn về vấn đề này là gì?
Thực hiện

Tôi đã có câu hỏi tương tự khi tôi mới bắt đầu C vài năm trước, và tôi đã được chỉ vào cùng một bài viết. Tôi sử dụng getchar () cá nhân.
John T

Ho wow ... Tôi đã không thực hiện C ++ trong một thời gian nhưng vâng .. chắc chắn có nhiều cách tốt hơn để đạt được kết quả tương tự
Newtopian

16

Bạn có thể sử dụng std::cin.get()từ iostream:

#include <iostream> // std::cout, std::cin
using namespace std;

int main() {
   do {
     cout << '\n' << "Press the Enter key to continue.";
   } while (cin.get() != '\n');

   return 0;
}

Bên cạnh đó, system('pause')chậm và bao gồm một tệp mà bạn có thể không cần : stdlib.h. Nó phụ thuộc vào nền tảng và thực sự gọi một hệ điều hành 'ảo'.


3
Tôi được dạy sử dụng System("pause")trong khóa học lập trình năm đầu tiên, nhưng tôi muốn có thể chạy các chương trình của mình trên máy Mac, vì vậy tôi phải tìm hiểu về nó cin.get().
daviewales

10

Bởi vì nó không phải là hàng xách tay.

pause

là một chương trình chỉ dành cho windows / dos, vì vậy mã này sẽ không chạy trên linux. Hơn nữa, systemkhông thường được coi là một cách rất tốt để gọi một chương trình khác - nó thường tốt hơn để sử dụng là CreateProcesshay forkhay cái gì tương tự.


4

Như được liệt kê trên các câu trả lời khác, có nhiều lý do bạn có thể tìm thấy để tránh điều này. Tất cả sôi sục vì một lý do khiến phần còn lại phải nhại lại. Các System()chức năng vốn không an toàn / không đáng tin cậy, và không nên được đưa vào một chương trình trừ khi cần thiết.

Đối với một bài tập của học sinh, điều kiện này không bao giờ được đáp ứng, và vì lý do này, tôi sẽ thất bại một bài tập mà thậm chí không chạy chương trình nếu có cuộc gọi đến phương thức này. (Điều này đã được làm rõ từ đầu.)


4

Đối với tôi, nói chung là không có ý nghĩa gì khi chờ đợi trước khi thoát ra mà không có lý do. Một chương trình đã hoàn thành công việc của nó chỉ nên kết thúc và bàn giao lại tài nguyên của nó cho người tạo ra nó.

Người ta cũng không âm thầm chờ đợi trong một góc tối sau một ngày làm việc, chờ đợi ai đó vỗ vai.


7
Đây là một câu trả lời ngớ ngẩn. Một phần của chương trình "thực hiện công việc" là hiển thị kết quả công việc của nó cho người dùng. Do đó, nó không nên kết thúc cho đến khi người dùng thông báo rằng họ đã kết thúc với nó. Một chương trình biến mất khỏi màn hình của người dùng một nano giây sau khi nó hiển thị kết quả của nó, là vô ích.
JBentley

1
@JBentley: Tôi đã nói về tình huống sau khi hiển thị kết quả, nếu có. Để hiển thị kết quả, tồn tại các mẫu thích hợp, như tín hiệu, ngắt, bộ hẹn giờ, cuộn lại trong thiết bị đầu cuối, tệp của bạn. system("pause")trong bản thân nó không hiển thị bất cứ điều gì. Một chương trình giao diện dòng lệnh được gọi không phải từ dòng lệnh và đóng quá sớm sẽ được gọi sai và với các tùy chọn sai, và sử dụng system("pause")để phá vỡ một chương trình được gọi sai thực sự không phải là điều nên làm.
Sebastian Mach

1
Tôi có nghĩa là, chỉ cần tưởng tượng cat, less, vi, OpenOffice, Mathematica, GNU Octave, những gì nếu họ muốn sử dụng system("pause")? Điều đó sẽ gây phiền nhiễu.
Sebastian Mach

2
Vâng, điều đó sẽ gây phiền nhiễu, nhưng bây giờ bạn đang nói cụ thể về các vấn đề của system("pause"), trong khi câu trả lời của bạn nói về "chờ đợi trước khi thoát", đó là một khái niệm tổng quát hơn nhiều. Nhiều ví dụ bạn đưa ra thực tế là "đợi trước khi thoát", cho đến khi người dùng thông báo cho chương trình rằng họ muốn nó thoát. Tôi đồng ý rằng đó system("pause")không phải là một cách tốt để đạt được điều đó và có những giải pháp tốt hơn, nhưng đó không phải là câu trả lời của bạn.
JBentley

1
@JBentley Oh, hoàn toàn: nếu một sự chậm trễ / chờ đợi / nhắc nhở là một phần của ngữ nghĩa của chương trình, pauseđi!
Các cuộc đua nhẹ nhàng trong quỹ đạo

3
system("pause");  

là sai vì nó là một phần của API Windows và vì vậy nó sẽ không hoạt động trong các hệ điều hành khác.

Bạn nên cố gắng chỉ sử dụng các đối tượng từ thư viện chuẩn C ++. Một giải pháp tốt hơn sẽ là viết:

cin.get();
return 0;

Nhưng nó cũng sẽ gây ra vấn đề nếu bạn có mã khác cintrong mã của mình. Bởi vì sau mỗi lần cin, bạn sẽ chạm vào một Enterhoặc \nmột ký tự khoảng trắng. cinbỏ qua nhân vật này và để nó trong vùng đệm nhưng cin.get(), vẫn giữ nhân vật này. Vì vậy, kiểm soát của chương trình đạt đến dòng return 0và giao diện điều khiển được đóng lại trước khi cho phép bạn xem kết quả.
Để giải quyết điều này, chúng tôi viết mã như sau:

cin.ignore();  
cin.get();  
return 0;

Đó là một chút sai lầm. system()là tiêu chuẩn và không dành riêng cho MS Windows. Tuy nhiên, pauselệnh shell là một di sản của DOS và thường chỉ được tìm thấy ở đó.
Ulrich Eckhardt

1

Đây là một lý do bạn không nên sử dụng nó: nó sẽ làm phiền hầu hết các chương trình chống vi-rút đang chạy trên Windows nếu bạn chuyển chương trình này sang máy khác vì đó là mối đe dọa bảo mật. Ngay cả khi chương trình của bạn chỉ bao gồm một cout << "hello world\n"; system("pause"); tài nguyên đơn giản. Nó nặng về tài nguyên và chương trình được truy cập vào lệnh cmd, điều mà các vi-rút coi là mối đe dọa.


-1

sự chuyên nghiệp để sử dụng hệ thống ("PAUSE"); trong khi tạo các phần nhỏ của chương trình của bạn là để tự gỡ lỗi nó. nếu bạn sử dụng nó để nhận kết quả của các biến trước trong và sau mỗi quá trình bạn đang sử dụng để đảm bảo rằng chúng đang hoạt động đúng.

Sau khi thử nghiệm và chuyển nó thành toàn bộ phần còn lại của giải pháp, bạn nên loại bỏ các dòng này. nó thực sự tốt khi kiểm tra thuật toán do người dùng xác định và đảm bảo rằng bạn đang thực hiện mọi thứ theo đúng thứ tự cho kết quả mà bạn muốn.

Bạn không muốn sử dụng điều này trong một ứng dụng sau khi bạn đã kiểm tra nó và đảm bảo rằng nó hoạt động tốt. Tuy nhiên, nó cho phép bạn theo dõi mọi thứ đang diễn ra. Đừng sử dụng nó cho các ứng dụng Người dùng cuối.


-3

Tất cả chỉ là vấn đề về phong cách. Nó rất hữu ích để gỡ lỗi nhưng nếu không thì không nên sử dụng nó trong phiên bản cuối cùng của chương trình. Nó thực sự không quan trọng đối với vấn đề bộ nhớ bởi vì tôi chắc chắn rằng những kẻ đã phát minh ra hệ thống ("tạm dừng") đã dự đoán rằng nó sẽ được sử dụng thường xuyên. Ở một góc nhìn khác, các máy tính được điều chỉnh trên bộ nhớ của chúng cho mọi thứ khác mà chúng ta sử dụng trên máy tính và nó không gây ra mối đe dọa trực tiếp như cấp phát bộ nhớ động, vì vậy tôi khuyên bạn nên dùng nó để gỡ lỗi mã, nhưng không có gì khác.


6
Nó thực sự không quan trọng đối với vấn đề bộ nhớ bởi vì tôi chắc chắn rằng những kẻ đã phát minh ra hệ thống ("tạm dừng") đã dự đoán rằng nó sẽ được sử dụng thường thực sự không có ý nghĩa gì. Không ai "phát minh" ra thứ này, pauseđược thiết kế để sử dụng trong các chương trình hàng loạt của DOS, nó chưa bao giờ được sử dụng theo cách như thế này. Hơn nữa, có nhiều cách thay thế tốt hơn trước khi bất kỳ ai đủ điên rồ để gõ cụm từ system("pause");.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.