2009-05-16 41 views
29

Tôi đang thực hiện các bài tập trong cuốn sách mới của Stroustrup "Programming Principles and Practice Using C++" và tự hỏi liệu có ai trên SO đã thực hiện chúng và sẵn sàng chia sẻ kiến ​​thức không? Cụ thể về máy tính được phát triển trong Chương 6 và 7. Ví dụ: các câu hỏi về việc thêm! toán tử và sqrt(), pow() vv Tôi đã làm những điều này nhưng tôi không biết liệu giải pháp mà tôi có là "tốt" để làm mọi thứ, và không có giải pháp nào được xuất bản trên trang web của Bjarne. Tôi muốn biết nếu tôi đi đúng hướng. Có lẽ chúng ta có thể tạo một wiki cho các bài tập?Thêm! toán tử và sqrt(), pow() vv cho ứng dụng ví dụ máy tính

Về cơ bản tôi có trình phân tích cú pháp mã thông báo. Nó đọc một char tại một thời điểm từ cin. Nó có nghĩa là để tokenise biểu thức như 5 * 3 + 1 và nó hoạt động tuyệt vời cho điều đó. Một trong các bài tập là thêm một hàm sqrt(). Vì vậy, tôi sửa đổi mã tokenising để phát hiện "sqrt (" và sau đó trở về một đối tượng Token đại diện sqrt.Trong trường hợp này tôi sử dụng char 's' .Đây có phải là cách những người khác sẽ làm điều đó? Nếu tôi cần phải thực hiện tội lỗi()? những tuyên bố trường hợp sẽ nhận được lộn xộn.

char ch; 
cin >> ch; // note that >> skips whitespace (space, newline, tab, etc.) 

switch (ch) { 
    case ';': // for "print" 
    case 'q': // for "quit" 
    case '(': 
    case ')': 
    case '+': 
    case '-': 
    case '*': 
    case '/': 
    case '!': 
     return Token(ch);  // let each character represent itself 
    case '.': 
    case '0': case '1': case '2': case '3': case '4': 
    case '5': case '6': case '7': case '8': case '9': 
     {  
      cin.putback(ch);   // put digit back into the input stream 
      double val; 
      cin >> val;    // read a floating-point number 
      return Token('8',val); // let '8' represent "a number" 
     } 
    case 's': 
     { 
      char q, r, t, br; 
      cin >> q >> r >> t >> br; 
      if (q == 'q' && r == 'r' && t == 't' && br == '(') { 
       cin.putback('('); // put back the bracket 
       return Token('s'); // let 's' represent sqrt 
      } 

     } 

    default: 
     error("Bad token"); 
} 
+0

Chỉ cần đăng mã của bạn ở đây và rất nhiều người sẽ vui lòng cho bạn biết những gì có thể được cải thiện. Trang web này là tất cả wiki bạn cần. :) – jalf

+0

Ok tôi sẽ sớm cập nhật! – PowerApp101

+0

Chưa từng thấy bài tập, nhưng có vẻ lạ là bạn cố gắng tăng gấp đôi số điểm chữ số và dấu thập phân mà bạn gặp phải. – jbasko

Trả lời

210
  • có vài giải pháp được đăng trên Stroustrup - Programming và ý chí hơn được comin g theo thời gian.

  • Hãy thử giải quyết các bài tập chỉ bằng các tính năng ngôn ngữ và cơ sở thư viện được trình bày cho đến nay trong sách - người dùng mới làm quen không thể làm gì khác. Sau đó quay lại sau để xem cách giải pháp có thể được cải thiện.

+2

Có, tôi đã gian lận với bản đồ ... nó không xuất hiện cho đến các chương sau. Tôi thực sự thích cuốn sách bằng cách này. Tôi nghĩ rằng máy tính thực sự có thể hữu ích trong thế giới thực, đó không phải là điều bạn có thể nói về các mẫu được trình bày trong hầu hết các cuốn sách giới thiệu. – PowerApp101

0

tôi sẽ di chuyển 'sqrt' phát hiện vào một phương pháp khác để phát hiện chức năng. về cơ bản, tôi sẽ loại bỏ phát hiện những 's' và thêm một cái gì đó bên trong trường hợp mặc định mà sẽ đọc chuỗi lên đến một '('.

Nếu không '(' được phát hiện, sau đó lỗi.

Nếu bạn đọc thành công một chuỗi, vượt qua đó để một tên hàm pa rser sử dụng chuỗi so sánh để tạo ra một mã thông báo đại diện cho một cuộc gọi đến sqrt hoặc sin hoặc bất cứ chức năng nào bạn thích. Phương pháp kiểm tra các tên hàm cũng có thể bị lỗi nếu nó đọc một chuỗi mà nó không nhận ra.

+0

Ok tôi sẽ cố gắng và thực hiện điều này Điều đó có thể tách ra các chức năng độc đáo – PowerApp101

10

Tôi nghĩ bản đồ về chuỗi hoạt động con trỏ có thể là một cách súc tích để đại diện cho những thứ như sqrt, sin, cos vv mà phải mất một đôi duy nhất và trả về một đôi:

map<std::string, double (*)(double)> funcs; 
funcs["sqrt"] = &sqrt; 
funcs["sin"] = &sin; 
funcs["cos"] = &cos; 

Sau đó, khi Phát hiện phân tích cú pháp một chuỗi chính xác (str) nó có thể gọi hàm với một đối số (arg) như sau:

double result = funcs[str](arg); 

Với phương thức này, một cuộc gọi có thể xử lý tất cả các trường hợp chức năng (loại đó).

Thực ra tôi không chắc đó có phải là cú pháp đúng hay không, có ai xác nhận không?

Điều này có vẻ giống như phương pháp có thể sử dụng không?

+7

Nó có thể, nhưng Bjarne Stroustrup trả lời câu hỏi của bạn sự. Cúi đầu. –

4

Nó là dễ dàng hơn để làm việc với các lớp thừa kế và chức năng ảo: mỗi lớp chuyên đọc đầu vào riêng của mình ...

class base{public: 
virtual double calc()=0; 
}; 
class get_sqrt:public base{ 
int useless; 
public: 
virtual double calc(){cin>>number;return sqrt(number);} 
}get_sqrt; 

bây giờ chúng tôi tổ chức này trong một bản đồ, chúng ta sẽ chỉ sử dụng con trỏ của họ:

map<string,base*> func; 
func["sqrt"]=&get_sqrt; 

cũng có một phù thủy phương pháp chuyên ngành chỉ nhìn vào ký tự tiếp theo: peek();

char c=cin.peek(); 

bạn có thể loại bỏ công tắc bằng cách sử dụng 1 nếu và đặt! + - ...trong func; (Họ nên hoạt động trên left_param vì đơn giản

if (c>='0'&&c<='9') cin>>right_param; //get a number, you don't have to put the character back as it hasn't been removed 
else{string s; cin>>s;right_param=func[s]->calc();} 

Vì vậy, về cơ bản một số loại con trỏ chức năng nhưng không có sintax lộn xộn và phù thủy bạn có thể lưu trữ dữ liệu giữa các tính toán

chỉnh sửa: tôi nghĩ về vấn đề khoảng trắng;. nó có thể được thêm vào trước nó bắt đầu tính toán, tôi cũng nghĩ rằng có thể là một cách để thiết lập dải phân cách khác nhau, như số nhưng tôi không biết làm thế nào.

+0

Tuyệt. Tôi biết sẽ có một giải pháp OOP ở đâu đó! Nhưng ... các cin >> s sẽ không hoạt động vì biểu thức có thể không chứa khoảng trắng, tức là 5 + sqrt (144)/2. Vì vậy, vẫn cần phải đọc một char tại một thời điểm để kiểm tra tên chức năng như sqrt, tôi nghĩ. – PowerApp101

+0

Tôi nghĩ rằng nó nên được peek, không phải đỉnh cao! Tôi tự hỏi tại sao Stroustrup không sử dụng phương pháp này, nó có vẻ hợp lý hơn so với get() và putback(). – PowerApp101

+7

Tôi hạn chế sử dụng peek() để tránh giới thiệu một cơ sở mới vào đầu và (quan trọng hơn) bởi vì "luồng với putback()" là một ý tưởng rất chung có thể được sử dụng ở nhiều nơi - peek() liên quan đến người khác đang làm một số đệm cho bạn. Ngoài ra, hãy nghĩ đến khoảng trắng và xử lý lỗi - điều gì sẽ xảy ra nếu không có nhân vật tiếp theo nào để nhìn trộm? Tôi thấy peek() nhiều hơn như một "thủ thuật thông minh" hơn là một kỹ thuật chung. –

Các vấn đề liên quan