Đến nội dung


Hình ảnh
* - - - - 1 Bình chọn

[Thảo luận] Code lisp như thế nào để hạn chế lỗi cho người dùng?


  • Please log in to reply
44 replies to this topic

#21 ThuyLinh313

ThuyLinh313

    biết lệnh mtext

  • Members
  • PipPipPipPip
  • 288 Bài viết
Điểm đánh giá: 142 (tàm tạm)

Đã gửi 24 May 2013 - 10:38 PM

Khi mới tham gia diễn đàn mình có lập topic kiểm soát lỗi, một kiểu topic tương tự thế này. Khi đó mình không hiểu sao một vài bạn nhảy vào ném đá topic của mình ghê lắm. Trong topic đó ban Ketxu có giải thích về việc sử dung vl-cmdf và command rồi. Bạn ĐVH có tham gia topic đó mà


  • 0

#22 Doan Van Ha

Doan Van Ha

    biết lệnh adcenter

  • CADViet Team
  • PipPipPipPipPipPipPip
  • 5451 Bài viết
Điểm đánh giá: 2625 (tuyệt vời)

Đã gửi 24 May 2013 - 10:40 PM

dùng (initget (+ 2 4)) để bắt buộc nhập số >0

1).  (initget 6) là còn thiếu trường hợp.

2). Đưa (initget 6) vào lisp như thế nào, bạn đề xuất code xem.


  • 0

* Chỉ nên yêu cầu Lisp khi bạn làm việc đó mất cả ngày nhưng họ chỉ viết 1 giờ. Đừng nêu yêu cầu Lisp khi bạn chỉ làm 1 giờ nhưng bắt họ phải mất cả ngày.

* Nhờ viết lisp cũng như đi khám bệnh. Chỉ gởi căn cước và than sắp chết thì không bác sỹ nào cứu sống được.


#23 ketxu

ketxu

    Copier - Paster - Editor

  • Moderator
  • PipPipPipPipPipPipPip
  • 5682 Bài viết
Điểm đánh giá: 2605 (tuyệt vời)

Đã gửi 24 May 2013 - 11:08 PM

- Getdist chấp nhận số nhỏ hơn 0, nhưng khi đi với p đằng trước thì giá trị trả về dương

- vl-cmdf đúng là .. gọi command bằng vl ^^ Nhưng thằng này  coi cả app là một object, nó định giá các tham số trước khi thực hiện, có vấn đề thì k thực hiện, không sao thì gửi chuổi này đến CAD thực thi, k ngu như command, chạy đến đâu tính đến đó, lỗi mới dùng ^^ Ngoài ra còn một số lợi ích khác, trường hợp này chưa bàn tới, ket cũng k rành lắm ^^


  • 3

Thành viên nhóm CadMagic.
Mời bạn ghé thăm facebook nhóm - Page viết lisp theo yêu cầu  :
CAD MAGIC


#24 Doan Van Ha

Doan Van Ha

    biết lệnh adcenter

  • CADViet Team
  • PipPipPipPipPipPipPip
  • 5451 Bài viết
Điểm đánh giá: 2625 (tuyệt vời)

Đã gửi 24 May 2013 - 11:22 PM

Khi mới tham gia diễn đàn mình có lập topic kiểm soát lỗi, một kiểu topic tương tự thế này. Khi đó mình không hiểu sao một vài bạn nhảy vào ném đá topic của mình ghê lắm. Trong topic đó ban Ketxu có giải thích về việc sử dung vl-cmdf và command rồi. Bạn ĐVH có tham gia topic đó mà

Xanh: 2 comment đều chỉ đich danh Ket nên để Ket trả lời tốt hơn. Với lại, bi nhiêu thì trong help có nói, còn ngoài ra không hiểu được gì thêm ngoài help.

Đỏ: vâng, có tham gia và cũng có bị ném đá.

@Ket: có p nó vẫn lỗi Ket à. Chắc Ket không ngồi trên máy.


  • 0

* Chỉ nên yêu cầu Lisp khi bạn làm việc đó mất cả ngày nhưng họ chỉ viết 1 giờ. Đừng nêu yêu cầu Lisp khi bạn chỉ làm 1 giờ nhưng bắt họ phải mất cả ngày.

* Nhờ viết lisp cũng như đi khám bệnh. Chỉ gởi căn cước và than sắp chết thì không bác sỹ nào cứu sống được.


#25 Polyline

Polyline

    biết lệnh mirror

  • Members
  • PipPipPip
  • 159 Bài viết
Điểm đánh giá: 18 (tàm tạm)

Đã gửi 25 May 2013 - 08:13 AM

Mình phản đối cách bắt buộc người dùng phải nhập cho đến khi nhập thành công (bằng vòng lặp (while hay (initget. Cách này rất thô bạo và không chuyên nghiệp. Theo mình, nếu người dùng không nhập đủ thông tin thì chỉ cần kết thúc mà không làm gì là được. Giả sử người ta gõ lệnh xong, người dùng mới thấy nó chưa cần thiết, mà người ta không thể thoát ra được, thì chỉ có cách nhấn ESC và thoát ngang, như vậy rất không thuận tiện.

 

Về (command và (vl-cmdf, có vấn đề cần lưu ý là chúng không thể thay thế cho nhau hoàn toàn. Ví dụ đoạn code sau:
(command ".circle" (setq d (getpoint)) 1 ".move" (entlast) "" d pause)

Nếu thay (command bằng (vl-cmdf thì nó sẽ không thể thực hiện bình thường được! :)


  • 0

#26 Tue_NV

Tue_NV

    KS Võ Quang Tuệ

  • Moderator
  • PipPipPipPipPipPipPip
  • 4296 Bài viết
Điểm đánh giá: 3804 (đỉnh cao)

Đã gửi 25 May 2013 - 08:35 AM

Mình phản đối cách bắt buộc người dùng phải nhập cho đến khi nhập thành công (bằng vòng lặp (while hay (initget. Cách này rất thô bạo và không chuyên nghiệp. Theo mình, nếu người dùng không nhập đủ thông tin thì chỉ cần kết thúc mà không làm gì là được. Giả sử người ta gõ lệnh xong, người dùng mới thấy nó chưa cần thiết, mà người ta không thể thoát ra được, thì chỉ có cách nhấn ESC và thoát ngang, như vậy rất không thuận tiện.

 

Về (command và (vl-cmdf, có vấn đề cần lưu ý là chúng không thể thay thế cho nhau hoàn toàn. Ví dụ đoạn code sau:
(command ".circle" (setq d (getpoint)) 1 ".move" (entlast) "" d pause)

Nếu thay (command bằng (vl-cmdf thì nó sẽ không thể thực hiện bình thường được! :)

 

1-/ Đồng ý

2-/ Đọc code cũng đã hiểu rồi bạn. Vl-cmdf định giá các tham số trước khi thực hiện lệnh.

(entlast) trong code trên thì trong vl-cmdf được định giá là đối tượng tạo ra cuối cùng của bản vẽ

còn trong command thì do đọc đến đâu thực thi lệnh đến đó nên (entlast) hiểu là circle vừa được tạo ra

3./ vl-cmdf còn được dùng để làm điều kiện cho hàm if


  • 2

#27 Doan Van Ha

Doan Van Ha

    biết lệnh adcenter

  • CADViet Team
  • PipPipPipPipPipPipPip
  • 5451 Bài viết
Điểm đánh giá: 2625 (tuyệt vời)

Đã gửi 25 May 2013 - 08:54 AM

1). Về vl-cmdf: tất cả những gì Ket+Polyme+Tue_NV nói đều đúng cả, và help cũng nói thế rồi. Và thậm chí nó còn khác nhau vài tí nữa, cũng có trong help.

2). @Polyme+Tue_NV: đây chỉ là ví dụ đưa ra để dẫn dắt cho 1 vấn đề bẫy lỗi mà thôi, tỉ như ví dụ này là 1 trích đoạn trong 1 lisp dài, mà nếu nhập sai đoạn đầu thì đoạn sau bị lỗi. Chứ chẳng ai đi viết 1 lisp kiểu cực đoan như vậy, và chắc sẽ bị user ném đá ngay thôi.

Tóm lại: tôi vẫn mong muốn mọi người tìm cách bẫy lỗi theo y/c đề bài, vì qua mấy comment cũng chưa tìm ra được cách nào tốt cả.


  • 1

* Chỉ nên yêu cầu Lisp khi bạn làm việc đó mất cả ngày nhưng họ chỉ viết 1 giờ. Đừng nêu yêu cầu Lisp khi bạn chỉ làm 1 giờ nhưng bắt họ phải mất cả ngày.

* Nhờ viết lisp cũng như đi khám bệnh. Chỉ gởi căn cước và than sắp chết thì không bác sỹ nào cứu sống được.


#28 gia_bach

gia_bach

    biết lệnh adcenter

  • CADViet Team
  • PipPipPipPipPipPipPip
  • 1436 Bài viết
Điểm đánh giá: 1426 (rất tốt)

Đã gửi 26 May 2013 - 12:30 PM

Mình phản đối cách bắt buộc người dùng phải nhập cho đến khi nhập thành công (bằng vòng lặp (while hay (initget. Cách này rất thô bạo và không chuyên nghiệp. Theo mình, nếu người dùng không nhập đủ thông tin thì chỉ cần kết thúc mà không làm gì là được. Giả sử người ta gõ lệnh xong, người dùng mới thấy nó chưa cần thiết, mà người ta không thể thoát ra được, thì chỉ có cách nhấn ESC và thoát ngang, như vậy rất không thuận tiện.

.....

Có gì đó không ổn rồi!

Hãy xem cách Cad làm việc với lệnh Circle :

+ khi yêu cầu nhập bán kính nếu User nhập số âm hoặc bằng 0, Cad sẽ yêu cầu nhập lại ......và nhập lại cho tới khi giá trị là số dương. 

-> như vậy bạn gọi CAD là " rất thô bạo và không chuyên nghiệp" ?

 

Giả sử môt Lisp yêu cầu nhập khoảng 10 giá trị đầu vào, khi nhập đến giá trị thứ 4-5 thì phát hiện giá trị nhập trước đó là sai ?

-> nhấn ESC và nhập lại từ đầu.

Một Lisp khác sẽ kiểm tra ngay từ đầu giá trị hợp lệ khi nhập (VD : phải là số dương) sau đó mới cho nhập tiếp giá trị thứ 2,thứ 3, ....

Lisp nào sẽ chuyên nghiệp hơn, ít mất thời gian hơn, hiệu quả hơn ??


  • 2

#29 Doan Van Ha

Doan Van Ha

    biết lệnh adcenter

  • CADViet Team
  • PipPipPipPipPipPipPip
  • 5451 Bài viết
Điểm đánh giá: 2625 (tuyệt vời)

Đã gửi 27 May 2013 - 07:28 AM

Vẫn đang chờ mọi người đưa ra phương án bẫy lỗi cho bài #12.


  • 0

* Chỉ nên yêu cầu Lisp khi bạn làm việc đó mất cả ngày nhưng họ chỉ viết 1 giờ. Đừng nêu yêu cầu Lisp khi bạn chỉ làm 1 giờ nhưng bắt họ phải mất cả ngày.

* Nhờ viết lisp cũng như đi khám bệnh. Chỉ gởi căn cước và than sắp chết thì không bác sỹ nào cứu sống được.


#30 Polyline

Polyline

    biết lệnh mirror

  • Members
  • PipPipPip
  • 159 Bài viết
Điểm đánh giá: 18 (tàm tạm)

Đã gửi 27 May 2013 - 08:55 AM

@gia_bach: Có vẻ như bác đã quá lời rồi! Theo mình, khi một hàm nào đó yêu cầu từ 4 số liệu đầu vào trở lên thì nên nghĩ ngay đến phương án giao diện hộ p thoại, ở đó người dùng có thể nhập 1 lần tất cả các tham số theo bất kỳ thứ tự nào. Bác đặt ra giả sử đến 10 tham số đầu vào trong một lisp thì rất xa lạ đối với AutoCAD rồi!

 

#13: Mình thử gán (setq p "a") trước khi chạy lệnh nhưng nó vẫn thực hiện ngon ơ! Như vậy, nếu một hàm có khai báo biến cục bộ, khi gặp biến toàn cục thì nó vẫn lấy theo biến cục bộ, sau đó hoàn trả lại giá trị của biến toàn cục sau khi thực hiện xong - Điều này có thể các bác đã biết nhưng với mình đây là điều mới mẻ => Việc đặt biến cục bộ không những giải phóng bộ nhớ mà còn giúp tránh xung đột về biến trùng tên.


  • 0

#31 tien2005

tien2005

    biết lệnh properties

  • Members
  • PipPipPipPip
  • 257 Bài viết
Điểm đánh giá: 94 (tàm tạm)

Đã gửi 27 May 2013 - 09:04 AM

mình code lại vẽ hình tròn. Các Bạn góp ý thêm

(defun c:vht ( / p r)
(while (not (setq p (getpoint "\nSpecify center point for circle: "))))
  (while (or (not r) (equal r 0.0 0.00001))
    (setq r (getdist "\nSpecify radius of circle: " p))
    )
 (vl-cmdf "circle"  p (abs r))
 (princ))

 

 


  • 0

#32 gia_bach

gia_bach

    biết lệnh adcenter

  • CADViet Team
  • PipPipPipPipPipPipPip
  • 1436 Bài viết
Điểm đánh giá: 1426 (rất tốt)

Đã gửi 27 May 2013 - 02:34 PM

@gia_bach: Có vẻ như bác đã quá lời rồi! Theo mình, khi một hàm nào đó yêu cầu từ 4 số liệu đầu vào trở lên thì nên nghĩ ngay đến phương án giao diện hộ p thoại, ở đó người dùng có thể nhập 1 lần tất cả các tham số theo bất kỳ thứ tự nào. Bác đặt ra giả sử đến 10 tham số đầu vào trong một lisp thì rất xa lạ đối với AutoCAD rồi!

.....

Chỉ là minh họa thôi. Nhưng thực tế thì vẫn có lisp y/cầu nhập trên 10 tham số đầu vào (VD: vẽ mặt cắt + kích thước).

Cho dù có dùng hộp thoại thì vẫn phải viết hàm bẫy lỗi cho nó (VD: tham số chiều dài mà user lại nhập chữ )

Hơn nữa cá nhân tôi cho rằng : nhập dữ liệu từ hộp thoại tốc độ nhập không nhanh bằng nhập trực tiếp từ dòng lệnh ?!

 

Tuy nhiên với 1 lisp chỉ y/cầu nhập 2 tham số, nếu 1 trong 2 tham số nhập sai thì user cũng phải nhập lại từ đầu. 

VD: với lệnh Trim mở rông tham khảo http://www.cadviet.c...h-trim-mo-rong/

(sorry HÀ nhé)

- khi yêu cầu Chon 1 doi tuong dao cat: nếu user chọn nhầm đường gióng kích thước (dễ nhầm lẫn với Line) thì các thao tác chọn sau đó sẽ vô nghĩa và tốn th/gian vô ích.

 

 

@Hà:

Với lệnh VHT tại dòng nhắc Pick diem 1:  nếu user nhập chỉ 1 giá trị số (VD : 15) không phải là tọa độ điểm thì lệnh vẫn vẽ ra đường tròn nhưng tâm đuòng tròn sẽ là 1 điểm nào đó mà qui luật của nó cần các Lisper nghiên cứu thêm.


  • 1

#33 Doan Van Ha

Doan Van Ha

    biết lệnh adcenter

  • CADViet Team
  • PipPipPipPipPipPipPip
  • 5451 Bài viết
Điểm đánh giá: 2625 (tuyệt vời)

Đã gửi 27 May 2013 - 04:43 PM

@Bác Gia_bach:

1). Màu tím số 1: đã bổ sung để hạn chế bớt lỗi ở bên đó.

2). Màu tím số 2: vâng, getpoint chấp nhận cả int và real. Nó liên quan lastpoint. Vấn đề ở đây chỉ là 1 ví dụ để bẫy lỗi thôi.

Thank bác!

Thêm ý này: nhập từ command thường nhanh hơn dialog, nhưng nhập từ dialog dễ kiểm soát hơn.

@Polyme: tôi đã từng thiết kế dialog, nhưng cũng có cái phải nhập trong dialog một số lớn các thông số, đồng thời phải nhập từ command cũng 1 số lớn thông số.

@Tien2005: dùng abs thì không lỗi nhưng hơi cưỡng ép nhỉ?


  • 1

* Chỉ nên yêu cầu Lisp khi bạn làm việc đó mất cả ngày nhưng họ chỉ viết 1 giờ. Đừng nêu yêu cầu Lisp khi bạn chỉ làm 1 giờ nhưng bắt họ phải mất cả ngày.

* Nhờ viết lisp cũng như đi khám bệnh. Chỉ gởi căn cước và than sắp chết thì không bác sỹ nào cứu sống được.


#34 Doan Van Ha

Doan Van Ha

    biết lệnh adcenter

  • CADViet Team
  • PipPipPipPipPipPipPip
  • 5451 Bài viết
Điểm đánh giá: 2625 (tuyệt vời)

Đã gửi 29 May 2013 - 09:39 AM

Giải pháp bẫy lỗi đề xuất cho bài #12. Ai có giải pháp hay hơn thì đề xuất nhé?

(defun C:VHT( / p r)
 (if
  (and
   (not (initget 1))
   (setq p (getpoint "\nSpecify center point for circle: "))
   (not (initget 7))
   (setq r (getdist p "\nSpecify radius of circle: ")))
  (command ".circle" "non" p r))
 (princ))
 


  • 0

* Chỉ nên yêu cầu Lisp khi bạn làm việc đó mất cả ngày nhưng họ chỉ viết 1 giờ. Đừng nêu yêu cầu Lisp khi bạn chỉ làm 1 giờ nhưng bắt họ phải mất cả ngày.

* Nhờ viết lisp cũng như đi khám bệnh. Chỉ gởi căn cước và than sắp chết thì không bác sỹ nào cứu sống được.


#35 Doan Van Ha

Doan Van Ha

    biết lệnh adcenter

  • CADViet Team
  • PipPipPipPipPipPipPip
  • 5451 Bài viết
Điểm đánh giá: 2625 (tuyệt vời)

Đã gửi 31 May 2013 - 10:57 AM

Mời các bạn đọc bài #1 đã được update, và sẽ liên tục được update...

Đồng thời, mời các bạn xem lisp dưới đây có thể bị lỗi hay không. Từ đó chúng ta sẽ rút ra kết luận.

(defun C:HA()
 (or a (setq a 1))
 (setq a (cond ((getint (strcat "\nNhap 1 so nguyen <" (itoa a) ">: "))) (a)))
 (1+ a))
 


  • 0

* Chỉ nên yêu cầu Lisp khi bạn làm việc đó mất cả ngày nhưng họ chỉ viết 1 giờ. Đừng nêu yêu cầu Lisp khi bạn chỉ làm 1 giờ nhưng bắt họ phải mất cả ngày.

* Nhờ viết lisp cũng như đi khám bệnh. Chỉ gởi căn cước và than sắp chết thì không bác sỹ nào cứu sống được.


#36 ketxu

ketxu

    Copier - Paster - Editor

  • Moderator
  • PipPipPipPipPipPipPip
  • 5682 Bài viết
Điểm đánh giá: 2605 (tuyệt vời)

Đã gửi 31 May 2013 - 12:48 PM

Không kể đến ngắt đột ngột thì a là biến toàn cục, hoàn toàn có thể bị thay đổi thông tin bởi Lisp khác (thành chuỗi, thành số thực ...) , nếu cẩn thận thì đặt tên biến hơi dị một chút, và kiểm tra điều kiện về a (thêm ở chỗ or a )


  • 1

Thành viên nhóm CadMagic.
Mời bạn ghé thăm facebook nhóm - Page viết lisp theo yêu cầu  :
CAD MAGIC


#37 Doan Van Ha

Doan Van Ha

    biết lệnh adcenter

  • CADViet Team
  • PipPipPipPipPipPipPip
  • 5451 Bài viết
Điểm đánh giá: 2625 (tuyệt vời)

Đã gửi 31 May 2013 - 02:16 PM

Cám ơn Ketxu! Đúng là như thế. Và một giải pháp để sửa lại lisp trên, tránh bị lỗi do tàn dư của lisp khác, có thể như thế này.

(Lý thuyết về vấn đề này sẽ được bổ sung ở bài đầu tiên #1).

(defun C:HA()
 (or (and a (= (type a) 'int)) (setq a 1))
 (setq a (cond ((getint (strcat "\nNhap 1 so nguyen <" (itoa a) ">: "))) (a)))
 (1+ a))
 


  • 1

* Chỉ nên yêu cầu Lisp khi bạn làm việc đó mất cả ngày nhưng họ chỉ viết 1 giờ. Đừng nêu yêu cầu Lisp khi bạn chỉ làm 1 giờ nhưng bắt họ phải mất cả ngày.

* Nhờ viết lisp cũng như đi khám bệnh. Chỉ gởi căn cước và than sắp chết thì không bác sỹ nào cứu sống được.


#38 Doan Van Ha

Doan Van Ha

    biết lệnh adcenter

  • CADViet Team
  • PipPipPipPipPipPipPip
  • 5451 Bài viết
Điểm đánh giá: 2625 (tuyệt vời)

Đã gửi 06 June 2013 - 11:42 AM

Chúng ta trở lại với bài vẽ Circle bằng 1 lỗi khác. Lỗi này thường ít được để ý và nếu không để ý thì sẽ khó phát hiện.

Mời mọi người tìm lỗi sau đây, và đề xuất phương án bẫy lỗi.

[Chú ý: các lỗi sẽ update liên tục ở bài #1].

(defun C:VHT( / p r)
 (if
  (and
   (not (initget 1))
   (setq p (getpoint "\nSpecify center point for circle: "))
   (not (initget 7))
   (setq r (getdist p "\nSpecify radius of circle: ")))
  (entmake (list '(0 . "Circle") (cons 10 p) (cons 40 r))))
 (princ))
 


  • 0

* Chỉ nên yêu cầu Lisp khi bạn làm việc đó mất cả ngày nhưng họ chỉ viết 1 giờ. Đừng nêu yêu cầu Lisp khi bạn chỉ làm 1 giờ nhưng bắt họ phải mất cả ngày.

* Nhờ viết lisp cũng như đi khám bệnh. Chỉ gởi căn cước và than sắp chết thì không bác sỹ nào cứu sống được.


#39 lyky

lyky

    biết vẽ polygon

  • Members
  • PipPip
  • 70 Bài viết
Điểm đánh giá: 126 (tàm tạm)

Đã gửi 07 June 2013 - 02:37 PM

Doan Van Ha, on 31 May 2013 - 14:09, said:

(defun C:HA()
(or (and a (= (type a) 'int)) (setq a 1))
(setq a (cond ((getint (strcat "\nNhap 1 so nguyen <" (itoa a) ">: "))) (a))) (1+ a))
;;; Tuy nhien, neu:
(defun C:HA( / a)....)
;;; Thi gia tri tham khao khong duoc luu lai!

Cách này chẳng những hạn chế được lỗi, mà còn rất tiện dụng trong trường hợp giá trị nhập thường được lặp lại, chúng ta có thể sắp xếp thành một hàm con dùng để nhập số nguyên "an toàn" hơn và nếu có thể, thay thế hàm getint, như sau:

(defun TgI (RV MSG REF / S U V)
(setq s (if msg msg (strcat "\nNhap so nguyen " (vl-symbol-name rv))))
(setq v (eval rv) u (if (= (type v) 'int) v ref))
(setq v (getint (strcat s " [" (itoa u) "]:")))
(set rv (if v v u)))
;;;........................Vi du;;;
(TgI 'sn "Vo Nguyen Giap" 19110825)

  • 1

22665_13x13progress.gif   22665_lyky.gif   22665_13x13progress.gif


#40 Tue_NV

Tue_NV

    KS Võ Quang Tuệ

  • Moderator
  • PipPipPipPipPipPipPip
  • 4296 Bài viết
Điểm đánh giá: 3804 (đỉnh cao)

Đã gửi 07 June 2013 - 04:03 PM

Chào bạn Lyky!

Bạn viết nếu (defun c:HA(/ a) .... thì giá trị tham khảo a không được lưu giữ lại.

 

Nhưng nếu hàm bạn viết là (defun TgI (RV MSG REF / S U V SN);;;;;; thì với ví dụ bạn viết là (TgI 'sn "Vo Nguyen Giap" 19110825) thì biến SN cũng không được lưu giữ lại mà.

Mình thấy "an toàn" như nhau. 


  • 1