Mục đích của “;” ở cuối vòng lặp for?


76

Tôi tìm thấy mã sau:

Mục đích của chức năng là kiểm tra xem một số có phải là số nguyên tố hay không.

Tôi không hiểu tại sao vòng lặp for lại có ;:

Nếu không có điều đó, mã sẽ không hoạt động bình thường.

Giải thích là gì?


48
Vòng lặp for có dấu chấm phẩy ở cuối vì tác giả là EVIL! Nó sẽ đi trên đường riêng của nó trong những tình huống như thế này.
sh1

21
@ sh1 Hoặc, nếu tác giả muốn toàn bộ vòng lặp trên một dòng, { }có thể được sử dụng thay ;cho tài liệu rằng việc vòng lặp có phần thân trống và không bao gồm bất kỳ dòng nào tiếp theo là chủ ý.
Eliah Kagan

22
@EliahKagan, đôi khi tôi muốn nhấn mạnh sự trống rỗng của phần thân vòng lặp, tôi sẽ viết for (...) continue;.
sh1

8
@coredump Nhưng hai vấn đề với dấu chấm phẩy được sử dụng theo cách này là (1) có vẻ như một sai lầm, một nhà phát triển có ý tốt có thể loại bỏ một ngày nào đó; và (2) nếu bạn không nhìn thấy nó, bạn sẽ nghĩ rằng câu lệnh bên dưới nó sẽ là câu lệnh bị "lặp". Điều thứ hai là một mối nguy hiểm đặc biệt, bởi vì các lập trình viên học cách không chú ý đến dấu chấm phẩy ở cuối dòng; cũng giống như người đọc có xu hướng không thông báo nếu một câu không kết thúc với một dấu chấm
Dawood ibn Kareem

6
@ Marco13 Tại sao lại tự động cho rằng tác giả gốc là không biết gì? Bạn ghét kiểu viết này, rất tốt. Nhưng bạn sẽ thấy rất nhiều người thích forcách tiếp cận vòng lặp: xét cho cùng, có một khởi tạo, một điều kiện dừng và một lần lặp, được thể hiện tự nhiên bởi forcấu trúc. Bạn không đồng ý, nhưng tôi chắc chắn rằng tác giả biết whilevòng lặp là gì. Btw, đó là lý do tại sao bạn cần các quy ước viết mã trong một nhóm.
coredump

Câu trả lời:


89

Nó có nghĩa giống hệt như:


7
Và đây là cách tốt hơn nhiều để viết phần thân vòng lặp trống (mặc dù viết {}trên một dòng có thể là manh mối trực quan dễ dàng hơn cho phần thân trống). Nếu không có mã kế thừa, ngôn ngữ sẽ tốt hơn nếu không có ;quy tắc câu lệnh trống. Điều ;bắt buộc sau do ... while(...)cũng là ngu ngốc, nhưng ít nhất ở đó tôi đã thấy một số cách sử dụng thông minh của nó.
Marc van Leeuwen

5
@MarcvanLeeuwen Tôi thấy nó ;dễ đọc hơn. Khối trống trông giống như một tai nạn, giống như lập trình viên vừa quên điền vào phần thân. Câu nói trống không làm cho ý định của anh ta trở nên rõ ràng.
Paul

19
@Paulpro, tôi thấy cả hai đều là những sai lầm tiềm ẩn và for (...) { /* empty block */ }rõ ràng hơn là cả hai, chừng nào chứng tỏ rằng đó là cố ý.
atk

2
Tôi không phải là một Clập trình viên, nhưng tại sao làm điều này lại có ích?
Ethan Bierlein

6
@EthanBierlein 'công việc' được thực hiện bởi các câu lệnh bên trong ( ); điểm của vòng lặp này là kết thúc bằng countviệc có một giá trị cụ thể dựa trênzahl
MM

53

Vòng lặp for có fortừ khóa, theo sau là dấu ngoặc đơn chứa ba biểu thức tùy chọn được phân tách bằng dấu chấm phẩy, theo sau là phần nội dung thực thi trong mỗi lần lặp của vòng lặp.

Mục tiêu của vòng lặp for trong ví dụ của bạn là đặt giá trị của count, giá trị này sẽ được so sánh với zahltrong câu lệnh if sau đó. Điều này đạt được trong các biểu thức được phân tách bằng dấu chấm phẩy, vì vậy phần thân của vòng lặp không cần phải làm gì cả.

Vì vòng lặp không cần phải làm gì cả, nó sử dụng câu lệnh rỗng làm phần thân của nó.

Nếu phần ;cuối bị bỏ qua và không có thay đổi nào khác được thực hiện, thì câu lệnh if sau vòng lặp for sẽ tự nó trở thành phần thân của vòng lặp for. (Điều đó không có ý định và sẽ phá vỡ chương trình, như bạn đã quan sát.)

Tuy nhiên, làm cho phần thân vòng lặp của một người bao gồm một phần tử duy nhất ;trên cùng một dòng không phải là cách duy nhất để viết phần thân vòng lặp trống, cũng không phải là cách hợp lý nhất để làm như vậy. Nó hoạt động hoàn toàn tốt, nhưng vấn đề là những người đọc khác - và có lẽ là cùng một lập trình viên, quay lại dự án sau đó - có thể tự hỏi liệu nó có thực sự là một lỗi hay không. Rốt cuộc, một người gõ dấu chấm phẩy ở cuối dòng khá thường xuyên khi viết mã bằng ngôn ngữ kiểu C, vì vậy thật dễ dàng để gõ thêm một dấu chấm phẩy ở những nơi không thuộc về nó.

Vấn đề khác là, trong mã mà vòng lặp một dòng với ;phần thân của nó là kiểu đã chọn, rất khó để nhận ra ai đó thực sự đã mắc lỗi khi đặt một ;khi không thuộc.

Do đó, những lựa chọn thay thế này có thể phù hợp hơn:

  • đặt ;, thụt lề, trên dòng tiếp theo - như sh1 gợi ý
  • viết phần thân của vòng lặp dưới dạng một khối trống { }, thay vì một câu lệnh trống
  • làm cho phần thân vòng lặp trở thành một continue;câu lệnh, điều này chỉ đơn giản làm cho vòng lặp chuyển sang lần lặp tiếp theo của nó (giống như những gì xảy ra khi phần thân vòng lặp trống) - cũng như sh1 gợi ý

4
Trong khi tôi có thể đồng ý với ;{}, tôi sẽ thấy điều continue;cực kỳ kỳ lạ. Tôi sẽ nhìn nó như thể ai đó mong đợi continuemột vòng lặp bên ngoài hoặc một cái gì đó. Chắc chắn là một thời điểm WTF và bạn muốn tránh những điều này trong mã. Tôi muốn nói rằng {}nắm bắt ý định theo cách dễ đọc nhất.
Angew không còn tự hào về SO

5
Một tùy chọn khác (có thể được kết hợp với những cái khác) là chèn chú thích : for (...) /* do nothing */ ;, để làm rõ rằng đó là chủ ý.

2
Tôi sẽ thêm vào các lựa chọn thay thế để tăng biến bên trong vòng lặp , như:for(count=2; zahl % count != 0 && zahl >= count;) ++count;
Massa

3
@Massa - forvòng lặp được đếm theo định nghĩa; xuất bộ tăng ra khỏi vòng lặp khiến bạn không có lý do gì để sử dụng forso với whilebất kỳ điều gì.

@vaxquis bạn vẫn có khởi tạo; Dù sao thì tôi cũng đã int count = 2; while( zahl % count && zahl >= count ) ++count;bắt đầu rồi: D
Massa

41

Dấu chấm phẩy ở cuối vòng lặp for có nghĩa là nó không có nội dung. Nếu không có dấu chấm phẩy này, C nghĩ rằng ifcâu lệnh là phần thân của vòng lặp for.


4
+ int (PI / 3) để được chú ý mà không đi vào cuộc tranh luận "thực hành mã hóa tốt / xấu".

+1 chắc chắn, một câu trả lời thực tế rõ ràng, ngắn gọn, không thử và khai báo mã là kiểu xấu hoặc kiểu kém.
Vality

1
Vòng lặp for chắc chắn có một phần thân. Nó chỉ là phần thân chỉ bao gồm câu lệnh null ;,. Đơn độc ;có giá trị trên thực tế (nếu không thực sự) ở mọi nơi cho phép một câu lệnh, bởi vì một ;câu lệnh đơn độc là một câu lệnh rỗng (là một câu lệnh).
người dùng

22

Cú pháp của for vòng lặp ( câu lệnh lặp ) là

statementcó thể là một câu lệnh null ( ;). C11 6.8.3 nói

Câu lệnh null (chỉ bao gồm dấu chấm phẩy) không thực hiện thao tác nào.

Trong đoạn 5, nó đưa ra một ví dụ

Trong đoạn chương trình

một câu lệnh null được sử dụng để cung cấp một phần thân vòng lặp trống cho câu lệnh lặp .

Điều tương tự đang xảy ra ở

;được sử dụng để cung cấp phần thân vòng lặp trống cho forcâu lệnh. Nếu không có ;câu lệnh bên cạnh forvòng lặp sẽ được coi là phần thân của nó và sẽ được thực thi.


1
+ int (PI / 3) để được chú ý mà không đi vào cuộc tranh luận "thực hành mã hóa tốt / xấu".

@vaxquis; Có, bởi vì câu hỏi là về "tại sao vòng lặp for có ;ở cuối?" . Nó không phải là về "liệu nó là một thực hành tốt hay không?" .
haccks

17

Ngoài những gì các câu trả lời xuất sắc khác đã nói, tôi muốn chỉ ra rằng

(nghĩa là, một forvòng lặp với một câu lệnh trống được sử dụng để tăng "bộ đếm") tương đương với

điều đó sẽ làm cho mục tiêu của mã thậm chí rõ ràng hơn so với một số lựa chọn thay thế được liệt kê: nếu không có chú thích, như trong trường hợp đã trình bày, một vòng lặp với câu lệnh trống có thể gây nhầm lẫn cho một lập trình viên khác phải ghi chú hoặc sử dụng mã (như đã trường hợp với OP ở đây).

Ngữ cảnh có thể giúp phân biệt phạm vi thực sự của câu lệnh, nhưng giữa một forvòng lặp với một câu lệnh trống và một whilevòng lặp với một câu lệnh, cái sau đòi hỏi ít công việc hơn để hiểu phạm vi của nó.


1
Nitpick nhỏ: điều này không hoàn toàn tương đương vì trong phiên bản thứ hai countđược khai báo trong phạm vi lớn hơn.
coredump

Ý tôi là, nói chung ... ở đây countđược khai báo ở đầu hàm trong cả hai phiên bản.
coredump

2
@coredump: Xét rằng mục đích của vòng lặp này - trong trường hợp cụ thể này - là để đạt được countgiá trị chính xác để nó có thể được sử dụng thêm, countphải tồn tại trong một phạm vi lớn hơn để điều đó hoạt động và do đó nó hoàn toàn tương đương. (Nó vẫn còn một sự lạm dụng xấu xí của một forvòng lặp, tuy nhiên, và Federico là đúng rằng đây là The Way Right để diễn tả ngữ nghĩa có liên quan.)
Mason Wheeler

@MasonWheeler Có, tôi đã suy nghĩ về trường hợp chung. Cả hai thực sự là tương đương ở đây.
coredump

1
Tại sao vòng lặp for không rõ ràng? Tôi hiểu rằng một vòng lặp for ở đó một cách rõ ràng để có một khởi tạo, một điều kiện và một câu lệnh lặp được kết hợp với nhau một cách hợp lý. Không bao giờ cần sử dụng vòng lặp for nhưng trường hợp đó có vẻ hợp lý và được viết rõ ràng.
Vality

12

Các ; sau khi forvòng lặp chỉ đơn giản là phương tiện mà các forvòng lặp sẽ không làm bất cứ điều gì hơn tăng bộ đếm count.


12

forTuyên bố :

Câu lệnh for là một câu lệnh lặp có cấu trúc cho phép dễ dàng khởi tạo biến, kiểm tra biểu thức và sửa đổi biến. Nó rất thuận tiện cho việc thực hiện các vòng điều khiển ngược. Đây là dạng chung của câu lệnh for:

[...]

Tuyên bố Null :

Câu lệnh rỗng chỉ đơn thuần là một dấu chấm phẩy.

Một câu lệnh null không làm được gì cả. Nó không lưu trữ một giá trị ở bất cứ đâu. Nó không làm cho thời gian trôi qua trong quá trình thực hiện chương trình của bạn.

Thông thường, một câu lệnh null được sử dụng làm phần thân của câu lệnh lặp hoặc như một hoặc nhiều biểu thức trong câu lệnh for. Dưới đây là ví dụ về câu lệnh for sử dụng câu lệnh null làm phần thân của vòng lặp (và cũng tính căn bậc hai số nguyên của n, chỉ cho vui thôi):

Đây là một ví dụ khác sử dụng câu lệnh null làm phần thân của vòng lặp for và cũng tạo ra đầu ra:

Một câu lệnh null đôi khi cũng được sử dụng để theo sau một nhãn mà nếu không sẽ là thứ cuối cùng trong một khối.


Trong trường hợp của bạn, đó ;Tuyên bố Null của forTuyên bố :

Nếu không có nó, ifcâu lệnh trở thành for:

Do đó, hành xử khác nhau.


1
Trích dẫn độc đáo từ tài liệu. +1
Vality

10

Vòng lặp for ở đó chỉ để tăng giá trị của count.


9

a for vòng lặp sẽ (bình thường) có một phần thân,

nơi cơ thể được bao bọc trong niềng răng { }

Tuy nhiên, đối với một nội dung câu lệnh duy nhất, các dấu ngoặc nhọn là tùy chọn.

; là một câu lệnh trống.

Kết hợp ở trên, rõ ràng là forvòng lặp thực thi cho đến khi điều kiện trở thành false.


6

Vòng lặp for về cơ bản là lặp qua tất cả các số nhỏ hơn hoặc bằng zahlnhưng lớn hơn 2 và lưu trữ nó trong biến count. Khi nó lặp qua tất cả các số này, nó sẽ kiểm tra xem zahlcó chia hết cho không count. Nếu zahlchia hết count, vòng lặp bị dừng. Nếu không, vòng lặp bị dừng khi countbằngzahl .

Câu lệnh if sau vòng lặp for sẽ kiểm tra xem countcó bằng không zahl. Nếu đúng, thì điều đó có nghĩa là vòng lặp đi qua tất cả các số nhỏ hơn zahlvà lớn hơn 2. Điều này có nghĩa là vòng lặp zahlchia hết cho tất cả các số nhỏ hơn chính nó và lớn hơn 2, là zahlsố nguyên tố.


0

Nó chỉ ra câu lệnh mà vòng lặp for được sử dụng. Nó không được để trống. Ít nhất nó nên bao gồm một tuyên bố duy nhất. ; là câu lệnh rỗng mà quá trình lặp được thực hiện.

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.