Xu Hướng 3/2024 # Algorithm – Chuyển Biểu Thức Trung Tố Sang Tiền Tố Và Hậu Tố Bằng Stack # Top 6 Xem Nhiều

Bạn đang xem bài viết Algorithm – Chuyển Biểu Thức Trung Tố Sang Tiền Tố Và Hậu Tố Bằng Stack được cập nhật mới nhất tháng 3 năm 2024 trên website 2atlantic.edu.vn. Hy vọng những thông tin mà chúng tôi đã chia sẻ là hữu ích với bạn. Nếu nội dung hay, ý nghĩa bạn hãy chia sẻ với bạn bè của mình và luôn theo dõi, ủng hộ chúng tôi để cập nhật những thông tin mới nhất.

Các biểu thức đại số được sử dụng hằng ngày đều được biểu diễn dưới dạng trung tố (infix). Cách biểu diễn này rất dễ hiểu với con người vì hầu hết các toán tử (+, -, *, /) đều là toán tử hai ngôi và chúng phân cách giữa hai toán hạng với nhau. Tuy nhiên đối với máy tính, để tính được giá trị của một biểu thức đại số theo dạng này không đơn giản như ta vẫn làm. Để khắc phục điều đó, máy tính cần chuyển cách biểu diễn các biểu thức đại số từ trung tố sang một dạng khác là tiền tố hoặc hậu tố. Trong bài này tôi sẽ giới thiệu kĩ thuật để giúp máy tính thực hiện điều này thông qua ngôn ngữ minh họa C#.

Thế nào là biểu thức tiền tố, trung tố và hậu tố

Trong đoạn giới thiệu trên có lẽ bạn cũng hình dung được thế nào là biểu thức trung tố, hiểu đơn giản tức là toán tử sẽ được đặt giữa hai toán hạng, dĩ nhiên đây phải là toán tử hai ngôi. Vậy dựa vào vị trí của của toán tử, liệu ta có thể biểu diễn biểu thức đại số dưới dạng khác? Câu trả lời là được, và như đã nói, ta có ba cách là biểu thức tiền tố (prefix), trung tố (infix) và hậu tố (postfix). Hãy xem một chút giới thiệu về cách biểu diễn biểu thức tiền tố và hậu tố để hiểu rõ hơn về chúng.

–       Prefix: Biểu thức tiền tố được biểu diễn bằng cách đặt toán tử lên trước các toán hạng. Cách biểu diễn này còn được biết đến với tên gọi “ký pháp Ba Lan” do nhà toán học Ba Lan Jan Łukasiewicz phát minh năm 1920. Với cách biểu diễn này, thay vì viết x+y như dạng trung tố, ta sẽ viết +xy. Tùy theo độ ưu tiên của toán tử mà chúng sẽ được sắp xếp khác nhau, bạn có thể xem một số ví dụ ở phía sau phần giới thiệu này.

–       Postfix: Ngược lại với cách Prefix, tức là các toán tử sẽ được đặt sau các toán hạng. Cách biểu diễn này được gọi là “ký pháp nghịch đảo Ba Lan” hoặc được viết tắt là RPN (Reverse Polish notation), được phát minh vào khoảng giữa thập kỷ 1950 bởi một triết học gia và nhà khoa học máy tính Charles Hamblin người Úc.

Một số ví dụ:

Infix Prefix Postfix

x+y +xy xy+

x+y-z -+xyz xy+z –

x+y*z +x*yz xyz*+

x+(y-z) +x-yz xyz-+

Phương pháp chuyển từ biểu thức trung tố sang tiền tố và hậu tố

Có hai cách để chuyển một biểu thức từ trung tố sang hai loại còn lại đó là dùng:

–       Stack

–       Expression Tree (cây biểu thức)

Việc dùng Stack phổ biến hơn có ưu điểm là dễ cài đặt, đơn giản còn dùng Expression Tree sẽ giúp việc chuyển đổi được dễ hiểu và trực quan hơn tuy nhiên lại mất thời gian cài đặt. Trong bài viết này tôi sẽ chỉ trình bày kĩ thuật sử dụng Stack, kĩ thuật dùng Expression Tree sẽ được giới thiệu trong bài viết sau.

Việc cài đặt các thuật toán chuyển đổi này bằng C# có một lợi điểm là C# hỗ trợ sẵn các collection, ngoài ra chúng còn có khả năng truy vấn và lọc dữ liệu nếu như bạn dùng C# 3 trở lên. Bên cạnh đó kĩ thuật Regular Expression cũng được sử dụng để làm giảm các câu lệnh so sánh và thao tác chuỗi.

Độ ưu tiên của các toán tử

Một trong những điều quan trọng trước khi bắt đầu là phải tính toán được độ ưu tiên của các toán tử trong biểu thức nhập vào. Để đơn giản ta chỉ xét các toán tử hai ngôi và thường dùng bao gồm: multiply (+),subtract (-), multiply (*), divide (/), Modulo (%). Theo đó các toán tử “*, /, %” có cùng độ ưu tiên và cao hơn hai toán tử “+, -”. Như vậy ta có phương thức lấy độ ưu tiên toán tử như sau:

public static int GetPriority(string op) { return 2; return 1; return 0; }

Định dạng lại biểu thức Infix trước khi chuyển đổi

Các biểu thức Infix khi nhập vào có thể dư thừa các khoảng trắng, các kí tự không phù hợp hoặc viết sai cú pháp. Phần kiểm tra cú pháp bạn có thể làm riêng hoặc để luôn trong các thuật toán chuyển đổi. Trong phần này tôi chỉ trình bày việc định dạng để các phần tử của biểu thức (toán tử, toán hạng) phải được phân cách với nhau bằng một khoảng trắng. Các phần tử này tôi sẽ gọi là một token.

public static void FormatExpression(ref string expression) { expression = expression.Replace(" ", ""); { return " " + match.Value + " "; }); expression = expression.Replace(" ", " "); expression = expression.Trim(); }

Như bạn thấy tôi đầu tiên tôi loại bỏ hết khoảng trắng khỏi chuỗi expression sau đó sử dụng phương thức Replace của Regular expression để tìm kiếm các toán tử và các dấu ngoặc đơn để thêm khoảng trắng vào hai đầu mỗi kí tự tìm thấy.

Phương thức Replace() tôi sử dụng trên có tham số thứ 3 là một delegate kiểu MatchEvaluator để xử lý các kết quả tìm được trong chuỗi. Cách viết trên tôi sử dụng kĩ thuật anonymous method, bạn có thể dùng lambda expression để viết và sử dụng phương thức Format() của lớp String để mã lệnh ngắn gọn hơn như sau:

String.Format(" {0} ", match.Value) );

Hai dòng sau dùng để cắt các khoảng trắng nằm sát nhau và các khoảng trắng nằm ở hai đầu chuỗi. Nguyên nhân có các khoảng trắng liền nhau là do trong biểu thức có thể sẽ xuất hiện các toán tử và dấu ngoặc đơn nằm sát nhau.

Các phương thức kiểm tra toán tử và toán hạng

Trong thuật toán chuyển đổi này ta cần có các phương thức kiểm tra xem một thành phần của chuỗi có phải là toán tử hoặc toán hạng không. Thay vì sử dụng các cấu trúc if hoặc switch dài dòng và bất tiện khi phát triển, ta sẽ dùng Regex để kiểm tra.

Ngoài ra vì chuỗi nhập vào là một biểu thức đại số, nên các toán hạng ta sẽ xét không chỉ là các chữ số mà còn có chữ cái từ a-z và A-Z.

Có một quy tắc nữa là khi dùng chữ cái thì chỉ cho phép duy nhất một chữ cái đại diện cho một toán hạng, còn khi dùng chữ số thì có thể nhiều chữ số ghép thành một toán hạng.

private static bool IsOperator(string str) { } public static bool IsOperand(string str) { }

Chuyển biểu thức Infix sang Postfix

Lý do tôi trình bày thuật toán chuyển sang postfix trước vì thuật toán này phổ biến và dễ cài đặt hơn, bạn cũng sẽ thấy sự tương đồng của thuật toán này với thuật toán chuyển từ infix sang prefix khi tôi trình bày ở phần sau.

Thuật toán để chuyển một biểu thức Infix sang dạn Prefix:

Đọc từng token trong biểu thức infix từ trái qua phải, với mỗi token ta thực hiện các bước sau:

–       Nếu là toán hạng: cho ra output.

–       Nếu là dấu mở ngoặc “(“: cho vào stack

–       Nếu là dấu đóng ngoặc “)”: lấy các toán tử trong stack ra và cho vào output cho đến khi gặp dấu mở ngoặc “(“. (Dấu mở ngoặc cũng phải được đưa ra khỏi stack)

–       Nếu là toán tử:

Chừng nào ở đỉnh stack là toán tử và toán tử đó có độ ưu tiên lớn hơn hoặc bằng toán tử hiện tại thì lấy toán tử đó ra khỏi stack và cho ra output.

Đưa toán tử hiện tại vào stack

Sau khi duyệt hết biểu thức infix, nếu trong stack còn phần tử thì lấy các token trong đó ra và cho lần lượt vào output.

Hãy xem ví dụ sau để hiểu rõ hơn thuật toán này.

Chúng ta sẽ chuyển biểu thức A*B+C*((D-E)+F)/G từ dạng Infix sang dạng Postfix:

Token Stack Output

A {Empty} A

* * A

B * A B

+ + A B *

C + A B * C

* + * A B * C

( + * ( A B * C

( + * ( ( A B * C

D + * ( ( A B * C D

– + * ( ( – A B * C D

E + * ( ( – A B * C D E

) + * ( A B * C D E –

+ + * ( + A B * C D E –

F + * ( + A B * C D E – F

) + * A B * C D E – F +

/ + / A B * C D E – F + *

G + / A B * C D E – F + * G

{Empty} A B * C D E – F + * G / +

Dựa theo thuật toán trên, ta cài đặt một phương thức tương ứng trên C#.

public static string Infix2Postfix(string infix) { FormatExpression(ref infix); StringBuilder postfix = new StringBuilder(); foreach (string s in str) { if (IsOperand(s)) postfix.Append(s).Append(" "); else if (s == "(") stack.Push(s); else if (s == ")") { string x = stack.Pop(); while (x != "(") { postfix.Append(x).Append(" "); x = stack.Pop(); } } else// IsOperator(s) { postfix.Append(stack.Pop()).Append(" "); stack.Push(s); } } postfix.Append(stack.Pop()).Append(" "); return postfix.ToString(); }

Chuyển biểu thức Infix sang Prefix

Không có nhiều sự khác biệt giữa việc chuyển từ Infix sang Prefix với Infix sang Postfix, chủ yếu là sự thay đổi thứ tự duyệt từ phải sang trái thay vì từ trái sang phải. Và thay vì duyệt theo hướng ngược lại như thế bạn có thể thực hiện một chuyển đổi nhỏ để đảo ngược biểu thức nhập vào.

Chú ý là tôi sử dụng “đảo ngược biểu thức” thay vì ”đảo ngược chuỗi”, việc đảo ngược này phải giữ nguyên được giá trị của các toán hạng, ví dụ bạn không thể đảo ngược 12 thành 21 được. Hơn nữa vì chuỗi đã đảo ngược nên các dấu ngoặc đơn cũng phải được hiểu ngược lại. Cụ thể ta có ví dụ sau:

Chuyển biểu thức Infix A*B+C*((D-E)+F)/G sang dạng Prefix

Đầu tiên ta đảo ngược biểu thức trên thành G/)F+)E-D((*C+B*A, sau đó ta thực hiện các bước trong thuật toán sau:

Đọc từng token trong biểu thức infix từ trái qua phải, với mỗi token ta thực hiện các bước sau:

–       Nếu là toán hạng: cho ra output.

–       Nếu là dấu đóng ngoặc “)“: cho vào stack

–       Nếu là dấu mở ngoặc “(”: lấy các toán tử trong stack ra và cho vào output cho đến khi gặp dấu đóng ngoặc “)“. (Dấu đóng ngoặc cũng phải được đưa ra khỏi stack)

–       Nếu là toán tử:

Chừng nào ở đỉnh stack là toán tử và toán tử đó có độ ưu tiên lớn hơn toán tử hiện tại thì lấy toán tử đó ra khỏi stack và cho ra output.

Đưa toán tử hiện tại vào stack

Sau khi duyệt hết biểu thức infix, nếu trong stack còn phần tử thì lấy các token trong đó ra và cho lần lượt vào output. Cuối cùng là đảo ngược biểu thức một lần nữa và ta sẽ thu được kết quả.

public static string Infix2Prefix(string infix) { FormatExpression(ref infix); foreach (string s in enumer) { if (IsOperand(s)) prefix.Add(s); else if (s == ")") stack.Push(s); else if (s == "(") { string x = stack.Pop(); while (x != ")") { prefix.Add(x); x = stack.Pop(); } } else// if (IsOperator(s)) { prefix.Add(stack.Pop()); stack.Push(s); } } prefix.Add(stack.Pop()); StringBuilder str = new StringBuilder(); { str.Append(prefix[i]).Append(" "); } return str.ToString(); }

Ngoài cách viết lại nguyên một phương thức chuyển đổi như trên, ta có thể sử dụng lại phương thức Infix2Postfix() để chuyển đổi sau khi đảo ngược biểu thức infix, đồng thời đảo ngược hai kí tự “(“ và “)” cho nhau.

Một số điểm lưu ý

Một số biểu thức prefix và postfix có thể được tạo ra khác nhau nhưng thực chất giá trị của chúng là bằng nhau và biểu thức infix ban đầu cũng là tương đương nhau. Nguyên nhân là một biểu thức đại số có nhiều cách để để tính giá trị khi độ ưu tiên của các toán tử là bằng nhau:

Ví dụ bạn có thể tính x+y-z bằng cách nhóm chúng lại thành

(x+y)-z (1)

hoặc

x+(y-z) (2)

Thông thường chúng ta ưu tiên cách tính số (1) từ trái qua.

Điểm tạo nên sự khác biệt là cách chúng ta so sánh độ ưu tiên của các toán tử, ví dụ thay vì viết dấu “<” trong đoạn mã này, ta có thể sửa thành “<=”, giá trị của chúng vẫn không thay đổi:

//…

prefix.Add(stack.Pop());

stack.Push(s);

//…

Kiểm tra kết quả

Ngoài ra bạn cũng có thể dùng chương trình Y2 Expression Converter Demo của tôi viết để minh họa việc chuyển đổi từ infix sang prefix và postfix.

https://yinyangit.wordpress.com

Bình chọn

Share this:

In

Thư điện tử

Twitter

Facebook

Like this:

Số lượt thích

Đang tải…

Chuyển Biểu Thức Trung Tố Sang Tiền Tố Và Hậu Tố Bằng Stack

Các biểu thức đại số được sử dụng hằng ngày đều được biểu diễn dưới dạng trung tố (infix). Cách biểu diễn này rất dễ hiểu với con người vì hầu hết các toán tử (+, -, *, /) đều là toán tử hai ngôi và chúng phân cách giữa hai toán hạng với nhau. Tuy nhiên đối với máy tính, để tính được giá trị của một biểu thức đại số theo dạng này không đơn giản như ta vẫn làm. Để khắc phục điều đó, máy tính cần chuyển cách biểu diễn các biểu thức đại số từ trung tố sang một dạng khác là tiền tố hoặc hậu tố.

Thế nào là biểu thức tiền tố, trung tố và hậu tố

Trong đoạn giới thiệu trên có lẽ bạn cũng hình dung được thế nào là biểu thức trung tố, hiểu đơn giản tức là toán tử sẽ được đặt giữa hai toán hạng, dĩ nhiên đây phải là toán tử hai ngôi. Vậy dựa vào vị trí của của toán tử, liệu ta có thể biểu diễn biểu thức đại số dưới dạng khác? Câu trả lời là được, và như đã nói, ta có ba cách là biểu thức tiền tố (prefix), trung tố (infix) và hậu tố (postfix). Hãy xem một chút giới thiệu về cách biểu diễn biểu thức tiền tố và hậu tố để hiểu rõ hơn về chúng.

-       Prefix: Biểu thức tiền tố được biểu diễn bằng cách đặt toán tử lên trước các toán hạng. Cách biểu diễn này còn được biết đến với tên gọi “ký pháp Ba Lan” do nhà toán học Ba Lan Jan Łukasiewicz phát minh năm 1920. Với cách biểu diễn này, thay vì viết x+y như dạng trung tố, ta sẽ viết +xy. Tùy theo độ ưu tiên của toán tử mà chúng sẽ được sắp xếp khác nhau, bạn có thể xem một số ví dụ ở phía sau phần giới thiệu này.

-       Postfix: Ngược lại với cách Prefix, tức là các toán tử sẽ được đặt sau các toán hạng. Cách biểu diễn này được gọi là “ký pháp nghịch đảo Ba Lan” hoặc được viết tắt là RPN (Reverse Polish notation), được phát minh vào khoảng giữa thập kỷ 1950 bởi một triết học gia và nhà khoa học máy tính Charles Hamblin người Úc.

Một số ví dụ:

Infix

Prefix

Postfix

x+y

+xy

xy+

x+y-z

-+xyz

xy+z –

x+y*z

+x*yz

xyz*+

x+(y-z)

+x-yz

xyz-+

Độ ưu tiên của các toán tử

Một trong những điều quan trọng trước khi bắt đầu là phải tính toán được độ ưu tiên của các toán tử trong biểu thức nhập vào. Để đơn giản ta chỉ xét các toán tử hai ngôi và thường dùng bao gồm: multiply (+),subtract (-), multiply (*), divide (/), Modulo (%). Theo đó các toán tử “*, /, %” có cùng độ ưu tiên và cao hơn hai toán tử “+, -”.

Các phương thức kiểm tra toán tử và toán hạng

Trong thuật toán chuyển đổi này ta cần có các phương thức kiểm tra xem một thành phần của chuỗi có phải là toán tử hoặc toán hạng không. Thay vì sử dụng các cấu trúc if hoặc switch dài dòng và bất tiện khi phát triển, ta sẽ dùng Regex để kiểm tra.

Ngoài ra vì chuỗi nhập vào là một biểu thức đại số, nên các toán hạng ta sẽ xét không chỉ là các chữ số mà còn có chữ cái từ a-z và A-Z.

Có một quy tắc nữa là khi dùng chữ cái thì chỉ cho phép duy nhất một chữ cái đại diện cho một toán hạng, còn khi dùng chữ số thì có thể nhiều chữ số ghép thành một toán hạng.

Chuyển biểu thức Infix sang Postfix

Lý do tôi trình bày thuật toán chuyển sang postfix trước vì thuật toán này phổ biến và dễ cài đặt hơn, bạn cũng sẽ thấy sự tương đồng của thuật toán này với thuật toán chuyển từ infix sang prefix khi tôi trình bày ở phần sau.

Thuật toán để chuyển một biểu thức Infix sang dạn Prefix:

Đọc từng token trong biểu thức infix từ trái qua phải, với mỗi token ta thực hiện các bước sau:

-       Nếu là toán hạng: cho ra output.

-       Nếu là dấu mở ngoặc “(“: cho vào stack

-       Nếu là dấu đóng ngoặc “)”: lấy các toán tử trong stack ra và cho vào output cho đến khi gặp dấu mở ngoặc “(“. (Dấu mở ngoặc cũng phải được đưa ra khỏi stack)

-       Nếu là toán tử:

Chừng nào ở đỉnh stack là toán tử và toán tử đó có độ ưu tiên lớn hơn hoặc bằng toán tử hiện tại thì lấy toán tử đó ra khỏi stack và cho ra output.

Đưa toán tử hiện tại vào stack

Sau khi duyệt hết biểu thức infix, nếu trong stack còn phần tử thì lấy các token trong đó ra và cho lần lượt vào output.

Hãy xem ví dụ sau để hiểu rõ hơn thuật toán này.

Chúng ta sẽ chuyển biểu thức A*B+C*((D-E)+F)/G từ dạng Infix sang dạng Postfix:

Token

Stack

Output

A

{Empty}

A

*

*

A

B

*

A B

+

+

A B *

C

+

A B * C

*

+ *

A B * C

(

+ * (

A B * C

(

+ * ( (

A B * C

D

+ * ( (

A B * C D

+ * ( ( –

A B * C D

E

+ * ( ( –

A B * C D E

)

+ * (

A B * C D E –

+

+ * ( +

A B * C D E –

F

+ * ( +

A B * C D E – F

)

+ *

A B * C D E – F +

/

+ /

A B * C D E – F + *

G

+ /

A B * C D E – F + * G

{Empty}

A B * C D E – F + * G / +

Chuyển biểu thức Infix sang Prefix

Không có nhiều sự khác biệt giữa việc chuyển từ Infix sang Prefix với Infix sang Postfix, chủ yếu là sự thay đổi thứ tự duyệt từ phải sang trái thay vì từ trái sang phải. Và thay vì duyệt theo hướng ngược lại như thế bạn có thể thực hiện một chuyển đổi nhỏ để đảo ngược biểu thức nhập vào.

Chú ý là tôi sử dụng “đảo ngược biểu thức” thay vì ”đảo ngược chuỗi”, việc đảo ngược này phải giữ nguyên được giá trị của các toán hạng, ví dụ bạn không thể đảo ngược 12 thành 21 được. Hơn nữa vì chuỗi đã đảo ngược nên các dấu ngoặc đơn cũng phải được hiểu ngược lại. Cụ thể ta có ví dụ sau:

Chuyển biểu thức Infix A*B+C*((D-E)+F)/G sang dạng Prefix

Đầu tiên ta đảo ngược biểu thức trên thành G/)F+)E-D((*C+B*A, sau đó ta thực hiện các bước trong thuật toán sau:

Đọc từng token trong biểu thức infix từ trái qua phải, với mỗi token ta thực hiện các bước sau: -       Nếu là toán hạng: cho ra output. -       Nếu là dấu đóng ngoặc “)“: cho vào stack -       Nếu là dấu mở ngoặc “(”: lấy các toán tử trong stack ra và cho vào output cho đến khi gặp dấu đóng ngoặc “)“. (Dấu đóng ngoặc cũng phải được đưa ra khỏi stack) -       Nếu là toán tử: * Chừng nào ở đỉnh stack là toán tử và toán tử đó có độ ưu tiên lớn hơn toán tử hiện tại thì lấy toán tử đó ra khỏi stack và cho ra output. * Đưa toán tử hiện tại vào stack.

Sau khi duyệt hết biểu thức infix, nếu trong stack còn phần tử thì lấy các token trong đó ra và cho lần lượt vào output. Cuối cùng là đảo ngược biểu thức một lần nữa và ta sẽ thu được kết quả.

Các bạn có thể tham khảo sourse code trong C++ giải bài toán chuyển biểu thức trung tố sang tiền tố:

int tiento(char a[])

{

char b[100],c[100];

int top=-1,n=-1;

{

if(‘0′<=a[i]&&a[i]<=’9’)

{

n++;

b[n]=a[i];

}

if(a[i]==’)’)

{

top++;

c[top]=a[i];

}

if(a[i]=='(‘) 

{

do

{

n++;

//neu la ‘(‘ thi lan luot cho nhung toan tu trong c vao b cho den khi gap ‘)’

b[n]=c[top]; 

top–;

}while(c[top]!=’)’);

top–;

}

{

{//if (toan tu cuoi cung trong c co do uu tien lon hon hoac bang toan tu dang duyet

n++;

b[n]=c[top];

top–;

}

top++;

c[top]=a[i];

}

}

{

n++;

b[n]=c[i];

}

}

}

Giải Thuật Và Lập Trình: §7. Ký Pháp Tiền Tố, Trung Tố Và Hậu Tố

BIỂU THỨC DƯỚI DẠNG CÂY NHỊ PHÂN

Chúng ta có thể biểu diễn các biểu thức số học gồm các phép toán cộng, trừ, nhân, chia bằng một cây nhị phân, trong đó các nút lá biểu thị các hằng hay các biến (các toán hạng), các nút không phải là lá biểu thị các toán tử (phép toán số học chẳng hạn). Mỗi phép toán trong một nút sẽ tác động lên hai biểu thức con nằm ở cây con bên trái và cây con bên phải của nút đó.

Ví dụ: Cây biểu diễn biểu thức (6 / 2 + 3) * (7 – 4) như sau:

Biểu thức dưới dạng cây nhị phân

CÁC KÝ PHÁP CHO CÙNG MỘT BIỂU THỨC

Với cây nhị phân biểu diễn biểu thức trong hình trên thì:

Nếu duyệt theo thứ tự trước, ta sẽ được * + / 6 2 3 – 7 4, đây là dạng tiền tố (prefix) của biểu thức. Trong ký pháp này, toán tử được viết trước hai toán hạng tương ứng, người ta còn gọi ký pháp này là ký pháp Ba Lan.

Nếu duyệt theo thứ tự giữa, ta sẽ được 6 / 2 + 3 * 7 – 4. Ký pháp này hơi mập mờ vì thiếu dấu ngoặc. Nếu thêm vào thủ tục duyệt inorder việc bổ sung các cặp dấu ngoặc vào mỗi biểu thức con sẽ thu được biểu thức (((6 / 2) + 3) * (7 – 4)). Ký pháp này gọi là dạng trung tố (infix) của một biểu thức (Thực ra chỉ cần thêm các dấu ngoặc đủ để tránh sự mập mờ mà thôi, không nhất thiết phải thêm vào đầy đủ các cặp dấu ngoặc).

Nếu duyệt theo thứ tự sau, ta sẽ được 6 2 / 3 + 7 4 – *, đây là dạng hậu tố (postfix) của biểu thức. Trong ký pháp này toán tử được viết sau hai toán hạng, người ta còn gọi ký pháp này là ký pháp nghịch đảo Balan (Reverse Polish Notation – RPN)

Chỉ có dạng trung tố mới cần có dấu ngoặc, dạng tiền tố và hậu tố không cần phải có dấu ngoặc.

CÁCH TÍNH GIÁ TRỊ BIỂU THỨC

Có một vấn đề cần lưu ý là khi máy tính giá trị một biểu thức số học gồm các toán tử hai ngôi (toán tử gồm hai toán hạng như +, -, *, /) thì máy chỉ thực hiện được phép toán đó với hai toán hạng. Nếu biểu thức phức tạp thì máy phải chia nhỏ và tính riêng từng biểu thức trung gian, sau đó mới lấy giá trị tìm được để tính tiếp. Ví dụ như biểu thức 1 + 2 + 4 máy sẽ phải tính 1 + 2 trước được kết quả là 3 sau đó mới đem 3 cộng với 4 chứ không thể thực hiện phép cộng một lúc ba số được.

Khi lưu trữ biểu thức dưới dạng cây nhị phân thì ta có thể coi mỗi nhánh con của cây đó mô tả một biểu thức trung gian mà máy cần tính khi xử lý biểu thức lớn. Như ví dụ trên, máy sẽ phải tính hai biểu thức 6 / 2 + 3 và 7 – 4 trước khi làm phép tính nhân cuối cùng. Để tính biểu thức 6 / 2 + 3 thì máy lại phải tính biểu thức 6 / 2 trước khi đem cộng với 3.

Vậy để tính một biểu thức lưu trữ trong một nhánh cây nhị phân gốc ở nút n, máy sẽ tính gần giống như hàm đệ quy sau:

function Calculate(n): Value; {Tính biểu thức con trong nhánh cây gốc n}

begin

else {Nút n chứa một toán tử R}

begin

x := Calculate(nút con trái của n);

y := Calculate(nút con phải của n);

Calculate := x R y;

end;

end.

(Trong trường hợp lập trình trên các hệ thống song song, việc tính giá trị biểu thức ở cây con trái và cây con phải có thể tiến hành đồng thời làm giảm đáng kể thời gian tính toán biểu thức).

Để ý rằng khi tính toán biểu thức, máy sẽ phải quan tâm tới việc tính biểu thức ở hai nhánh con trước, rồi mới xét đến toán tử ở nút gốc. Điều đó làm ta nghĩ tới phép cây theo thứ tự sau và ký pháp hậu tố. Trong những năm đầu 1950, nhà lô-gic học người Balan Jan Lukasiewicz đã chứng minh rằng biểu thức hậu tố không cần phải có dấu ngoặc vẫn có thể tính được một cách đúng đắn bằng cách đọc lần lượt biểu thức từ trái qua phải và dùng một Stack để lưu các kết quả trung gian:

Bước 1: Khởi động một Stack rỗng

Bước 2: Đọc lần lượt các phần tử của biểu thức RPN từ trái qua phải (phần tử này có thể là hằng, biến hay toán tử) với mỗi phần tử đó, ta kiểm tra:

– Nếu phần tử này là một toán hạng thì đẩy giá trị của nó vào Stack.

– Nếu phần tử này là một toán tử ®, ta lấy từ Stack ra hai giá trị (y và x) sau đó áp dụng toán tử ® đó vào hai giá trị vừa lấy ra, đẩy kết quả tìm được (x ® y) vào Stack (ra hai vào một).

Bước 3: Sau khi kết thúc bước 2 thì toàn bộ biểu thức đã được đọc xong, trong Stack chỉ còn duy nhất một phần tử, phần tử đó chính là giá trị của biểu thức.

Ví dụ: Tính biểu thức 10 2 / 3 + 7 4 – * (tương ứng với biểu thức (10 / 2 + 3) * (7 – 4).

Ta được kết quả là 24.

Quy định khuôn dạng bắt buộc là hai số liền nhau trong biểu thức RPN phải viết cách nhau ít nhất một dấu cách. Để quá trình đọc một phần tử trong biểu thức RPN được dễ dàng hơn, sau bước nhập liệu, ta có thể hiệu chỉnh đôi chút biểu thức RPN về khuôn dạng dễ đọc nhất. Chẳng hạn như thêm và bớt một số dấu cách trong Input để mỗi phần tử (toán hạng, toán tử) đều cách nhau đúng một dấu cách, thêm một dấu cách vào cuối biểu thức RPN. Khi đó quá trình đọc lần lượt các phần tử trong biểu thức RPN có thể làm như sau:

T := ”;

for p := 1 to Length(RPN) do {Xét các ký tự trong biểu thức RPN từ trái qua phải}

if RPN[p] # ‘ ‘ then T := T + RPN[p] {Nếu RPN[p] không phải dấu cách thì nối ký tự đó vào T}

else {Nếu RPN[p] là dấu cách thì phần tử đang đọc đã đọc xong, tiếp theo sẽ là phần tử khác}

begin

T := ”; {Chuẩn bị đọc phần tử mới}

end;

Để đơn giản, chương trình không kiểm tra lỗi viết sai biểu thức RPN, việc đó chỉ là thao tác tỉ mỉ chứ không phức tạp lắm, chỉ cần xem lại thuật toán và cài thêm các mô-đun bắt lỗi tại mỗi bước.

Ví dụ về Input / Output của chương trình:

Nhập vào biểu thức RPN: 10 2/3 + 4 7 -* 10 2 / 3 + 4 7 – * = 24.0000

{$N+,E+}

Ta có chương trình như sau:

program CalculateRPNExpression;

const

Opt = [‘+’, ‘-‘, ‘*’, ‘/’];

var

T, RPN: String;

Stack: array[1..255] of Extended;

p, Last: Integer;

{Các thao tác đối với Stack}

procedure StackInit;

begin

Last := 0;

end;

procedure Push(V: Extended);

begin

Inc(Last); Stack[Last] := V;

end;

function Pop: Extended;

begin

Pop := Stack[Last]; Dec(Last);

end;

procedure Refine(var S: String); {Hiệu chỉnh biểu thức RPN về khuôn dạng dễ đọc nhất}

var

i: Integer;

begin

S := S + ‘ ‘;

for i := Length(S) – 1 downto 1 do {Thêm những dấu cách giữa toán hạng và toán tử}

if (S[i] in Opt) or (S[i + 1] in Opt) then Insert(‘ ‘, S, i + 1);

for i := Length(S) – 1 downto 1 do {Xoá những dấu cách thừa}

if (S[i] = ‘ ‘) and (S[i + 1] = ‘ ‘) then Delete(S, i + 1, 1);

end;

procedure Process(T: String); {Xử lý phần tử T đọc được từ biểu thức RPN}

var

x, y: Extended;

e: Integer;

begin

if not (T[1] in Opt) then {T là toán hạng}

begin

Val(T, x, e);

Push(x); {Đổi T thành số và đẩy giá trị đó vào Stack}

end

else {T là toán tử}

begin

y := Pop;

x := Pop; {Ra hai}

case T[1] of

‘+’: x := x + y;

‘-‘: x := x – y;

‘*’: x := x * y;

‘/’: x := x / y;

end;

Push(x); {Vào một}

end;

end;

begin

Write(‘Enter RPN Expression: ‘); ReadLn(RPN);

Refine(RPN);

StackInit; T := ”;

for p := 1 to Length(RPN) do {Xét các ký tự của biểu thức RPN từ trái qua phải}

else {Nếu gặp dấu cách}

begin

Process(T); {Xử lý phần tử vừa đọc xong}

T := ”; {Đặt lại T để chuẩn bị đọc phần tử mới}

end;

WriteLn(RPN, ‘ = ‘, Pop:0:4); {In giá trị biểu thức RPN được lưu trong Stack}

end.

CHUYỂN TỪ DẠNG TRUNG TỐ SANG DẠNG HẬU TỐ

Thuật toán sử dụng một Stack để chứa các toán tử và dấu ngoặc mở. Thủ tục Push(V) để đẩy một phần tử vào Stack, hàm Pop để lấy ra một phần tử từ Stack, hàm Get để đọc giá trị phần tử nằm ở đỉnh Stack mà không lấy phần tử đó ra. Ngoài ra mức độ ưu tiên của các toán tử được quy định bằng hàm Priority như sau: Ưu tiên cao nhất là dấu “*” và “/” với Priority là 2, tiếp theo là dấu “+” và “-” với Priority là 1, ưu tiên thấp nhất là dấu ngoặc mở “(” với Priority là 0.

Stack := ø;

{T có thể là hằng, biến, toán tử hoặc dấu ngoặc được đọc từ biểu thức infix theo thứ tự từ trái qua phải}

case T of

‘(‘: Push(T); ‘)’:

repeat

x := Pop;

if x # ‘(‘ then Output(x);

until x = ‘(‘;

‘+’, ‘-‘, ‘*’, ‘/’:

begin

while (Stack # ø) and (Priority(T) ≤ Priority(Get)) do Output(Pop);

Push(T);

end;

else Output(T);

end;

while (Stack # ø) do Output(Pop);

Ví dụ với biểu thức trung tố (2 * 3 + 7 / 8) * (5 – 1) ta có như sau:

Ví dụ về Input / Output của chương trình:

Infix: (10*3 + 7 /8) * (5-1) Refined: ( 10 * 3 + 7 / 8 ) * ( 5 – 1 ) RPN: 10 3 * 7 8 / + 5 1 – *

P_2_07_2.PAS * Chuyển biểu thức trung tố sang dạng RPN

program ConvertInfixToRPN; const

Opt = [‘(‘, ‘)’, ‘+’, ‘-‘, ‘*’, ‘/’];

var

T, Infix, Stack: String; {Stack dùng để chứa toán tử và dấu ngoặc mở nên dùng String cho tiện}

p: Integer;

{Các thao tác đối với Stack}

procedure StackInit; begin

Stack := ”;

end;

procedure Push(V: Char);

begin

Stack := Stack + V;

end;

function Pop: Char;

begin

Pop := Stack[Length(Stack)];

Dec(Stack[0]);

end;

function Get: Char;

begin

Get := Stack[Length(Stack)];

end;

procedure Refine(var S: String); {Hiệu chỉnh biểu thức trung tố về khuôn dạng dễ đọc nhất}

var

i: Integer;

begin

S := S + ‘ ‘;

for i := Length(S) – 1 downto 1 do {Thêm những dấu cách trước và sau mỗi toán tử và dấu ngoặc}

if (S[i] in Opt) or (S[i + 1] in Opt) then Insert(‘ ‘, S, i + 1);

for i := Length(S) – 1 downto 1 do {Xoá những dấu cách thừa}

if (S[i] = ‘ ‘) and (S[i + 1] = ‘ ‘) then Delete(S, i + 1, 1);

end;

function Priority(Ch: Char): Integer; {Hàm lấy mức độ ưu tiên của Ch}

begin

case ch of

‘*’, ‘/’: Priority := 2;

‘+’, ‘-‘: Priority := 1;

‘(‘: Priority := 0;

end;

end;

procedure Process(T: String); {Xử lý một phần tử đọc được từ biểu thức trung tố}

var

c, x: Char;

begin

c := T[1];

if not (c in Opt) then Write(T, ‘ ‘)

else

case c of

‘(‘: Push(c); ‘)’: repeat

x := Pop;

until x = ‘(‘;

‘+’, ‘-‘, ‘*’, ‘/’:

begin

Push(c);

end;

end;

end;

begin

Write(‘Infix = ‘); ReadLn(Infix);

Refine(Infix);

WriteLn(‘Refined: ‘, Infix);

Write(‘RPN: ‘);

T := ”;

for p := 1 to Length(Infix) do

else

begin

Process(T); T := ”;

end;

WriteLn;

end.

XÂY DỰNG CÂY NHỊ PHÂN BIỂU DIỄN BIỂU THỨC

Ngay trong phần đầu tiên, chúng ta đã biết rằng các dạng biểu thức trung tố, tiền tố và hậu tố đều có thể được hình thành bằng cách duyệt cây nhị phân biểu diễn biểu thức đó theo các trật tự khác nhau. Vậy tại sao không xây dựng ngay cây nhị phân biểu diễn biểu thức đó rồi thực hiện các công việc tính toán ngay trên cây?. Khó khăn gặp phải chính là thuật toán xây dựng cây nhị phân trực tiếp từ dạng trung tố có thể kém hiệu quả, trong khi đó từ dạng hậu tố lại có thể khôi phục lại cây nhị phân biểu diễn biểu thức một cách rất đơn giản, gần giống như quá trình tính toán biểu thức hậu tố:

Bước 1: Khởi tạo một Stack rỗng dùng để chứa các nút trên cây

Bước 2: Đọc lần lượt các phần tử của biểu thức RPN từ trái qua phải (phần tử này có thể là hằng, biến hay toán tử) với mỗi phần tử đó:

Tạo ra một nút mới N chứa phần tử mới đọc được

Nếu phần tử này là một toán tử, lấy từ Stack ra hai nút (theo thứ tự là y và x), sau đó đem liên kết trái của N trỏ đến x, đem liên kết phải của N trỏ đến y.

Đẩy nút N vào Stack

Bước 3: Sau khi kết thúc bước 2 thì toàn bộ biểu thức đã được đọc xong, trong Stack chỉ còn duy nhất một phần tử, phần tử đó chính là gốc của cây nhị phân biểu diễn biểu thức.

Bài tập Bài 1

Viết chương trình chuyển biểu thức trung tố sang dạng RPN, biểu thức trung tố có cả những phép toán một ngôi: Phép lấy số đối (-x), phép luỹ thừa xy (x^y), lời gọi hàm số học (sqrt, exp, abs v.v…)

Bài 2

Viết chương trình chuyển biểu thức logic dạng trung tố sang dạng RPN. Ví dụ: Chuyển: a and b or c and d thành: a b and c d and or

Bài 3

Chuyển các biểu thức sau đây ra dạng RPN:

Viết chương trình tính biểu thức logic dạng RPN với các toán tử and, or, not và các toán hạng là TRUE hay FALSE.

Bài 5

Viết chương trình hoàn chỉnh tính giá trị biểu thức trung tố.

Khái Niệm Tố Cáo, Phân Biệt Tố Cáo Và Tố Giác Tội Phạm

1. Khái niện tố cáo: Hiểu tố cáo là gì? Nhất định bạn phải nắm rõ khái niệm thế nào là tố cáo:

Theo Điều 2 của Luật tố cáo có quy định về khái niệm tố cáo như sau:

“Tố cáo là việc công dân theo thủ tục do Luật này quy định báo cho cơ quan, tổ chức, cá nhân có thẩm quyền biết về hành vi vi phạm pháp luật của bất cứ cơ quan, tổ chức, cá nhân nào gây thiệt hại hoặc đe dọa gây thiệt hại lợi ích của Nhà nước, quyền, lợi ích hợp pháp của công dân, cơ quan, tổ chức”

Như vậy, bản chất của tố cáo sẽ được xem xét dựa vào nhiều khía cạnh khác nhau. Bao gồm:

Thứ nhất, đó chính là chủ thể tố cáo chỉ là một người công dân bình thường. Điều này có giá trị nhằm cá thể hóa đối với trách nhiệm đối với người tố cáo, nếu như họ cố tình tố cáo không đúng sự thật thì tùy vào các tính chất cũng như mức độ đến từ hành vi này sẽ bị xử lý theo quy định của pháp luật.

Thứ hai, khi đối tượng của tố cáo chính là những hành vi vi phạm pháp luật tại các cơ quan, tổ chức hoặc từ các cá nhân gây ra những thiệt hại, sự đe dọa đến lợi ích của Nhà nước và quyền lợi của công dân, của tổ chức nào đó.

Trong luật tố cáo, có hai loại hành vi được coi là vi phạm pháp luật và sẽ bị tố cáo đó chính là:

Hành vi trái pháp luật của người cán bộ, công nhân viên chức khi thực hiện nhiệm vụ Hành vi trái pháp luật về việc quản lý nhà nước ở trong tất cả các lĩnh vực.

Thứ ba, những cơ quan có thẩm quyền giải quyết việc tố cáo chính là cơ quan nhà nước có thẩm quyền. Những người tố cáo có thể tố cáo các hành vi vi phạm pháp luật lên cơ quan có thẩm quyền của nhà nước. Nếu như việc tố cáo được thực hiện bằng đơn tố cáo nhưng lại gửi đơn đến cho các cơ quan không thuộc thẩm quyền giải quyết sự việc tố cáo thì cơ quan đó sẽ phải chuyển đơn tố cáo lên những cơ quan, cá nhân có thẩm quyền.

Thứ tư, về trình tự và các thủ tục giải quyết việc tố cáo được quy định cụ thể như sau:+ Tiếp nhận và xử lý thông tin tố cáo+ Xác minh lại nội dung tố cáo+ Kết luận nội dung tố cáo+ Xử lý tố cáo+ Công khai kết luận của nội dung tố cáo, đưa ra quyết định xử lý các hành vi vi phạm pháp luật.

Thứ năm, kết quả tố cáo mang bản chất như sau: Trong trường hợp cá nhân nào đó bị tố cáo là vi phạm pháp luật thì sẽ bị áp dụng những biện pháp xử lý dựa trên kiến nghị, thẩm quyền của cơ quan, tổ chức và cá nhân có thẩm quyền giải quyết theo đúng như quy định mà pháp luật ban hành. Nếu như hành vi vi phạm pháp luật này có dấu hiệu phạm tội thì vụ việc sẽ được chuyển lên các cơ quan chức năng điều tra, hoặc đưa lên Viện kiểm sát để giải quyết việc tố cáo.

Trong trường hợp khác, nếu người bị tố cáo không vi phạm pháp luật thì cơ quan nhà nước có thẩm quyền cần phải gửi tới cho họ thông báo văn bản về việc khôi phục những quyền và lợi ích hợp pháp. Đồng thời, cơ quan chức năng phải thực hiện việc xử lý người cố ý tố cáo không đúng sự thật.

– Các mối quan hệ pháp luật phát sinh trong quá trình tố cáo

Khi người công dân tố cáo một hành vi vi phạm pháp luật nào đó thì sẽ có những mối quan hệ pháp luật phát sinh bao gồm:

Người tố cáo:

Họ là những người công dân chủ động thực hiện quyền tố cáo của mình. Khi tố cáo, họ cần phải đảm bảo tuyệt đối về tính chất trung thực, chính xác của vụ việc được tố cáo. Đồng thời còn phải chịu trách nhiệm đối với những thông tin đã cung cấp trong đơn tố cáo là gì.

Khi người tố cáo cố tình thực hiện hành vi tố cáo sai sự thật thì có thể họ sẽ bị truy cứu trách nhiệm hình sự, phải gánh tội vu khống theo những quy định của pháp luật tại Điều 122 của Bộ luật Hình sự ban hành năm 1999.

Người bị tố cáo:

Các đối tượng bị tố cáo có thể là các cơ quan, tổ chức, các cá nhân có hành vi tố cáo. Họ chính là những người được coi là đã thực hiện những hành vi vi phạm pháp luật và đã gây ra những đe dọa, những sự thiệt hại nhất định nào đó tới lợi ích của Nhà Nước, đến quyền lợi và lợi ích hợp pháp của cơ quan, tổ chức hay của công dân khác.

Người giải quyết tố cáo:

Giải quyết tố cáo chính là các cá nhân, cơ quan, tổ chức có thẩm quyền trong việc giải quyết các tố cáo từ người tố cáo dựa vào những hoạt động giải quyết tố cáo thiết thực, bao gồm: Tiếp nhận, xác minh, kết luận nội dung tố cáo, xử lý tố cáo.

– Những nội dung thường xuất hiện trong đơn tố cáo

Nếu như bạn đã hiểu được đơn tố cáo là gì thì sẽ không khó để biết được nội dung tố cáo sẽ thường là những nội dung gì. Trong cuộc sống, có ti tỉ những vấn đề mâu thuẫn có thể xảy ra và gây ảnh hưởng trực tiếp đến quyền và lợi ích của cơ quan, tổ chức, công dân. Nếu như liệt kê ra thì có lẽ không giấy mực nào diễn tả hết.

Tố cáo việc làm vi phạm pháp luật của người cán bộ, công chức làm việc ở trong bộ máy nhà nước trong quá trình thực hiện nhiệm vụ

Tố cáo các sai phạm trong công tác điều hành, quản lý của cơ quan, bao gồm cơ quan quản lý hành chính nhà nước

Tố cáo các hành vi vi phạm đạo đức, lối sống của những cán bộ, công chức

Có rất nhiều sự việc có thể tố cáo. Tuy nhiên khi thực hiện quyền tố cáo, nếu không chú ý cẩn thận thì người tố cáo có thể sẽ gặp phải một vài rủi ro nhất định. Họ có thể bị đe dọa, bị hành hung, trả thù từ những đối tượng bị tố cáo. Chính vì vậy mà người công dân cần phải thực hiện cả quyền yêu cầu các cơ quan tổ chức có thẩm quyền bảo vệ cho mình.

Ngoài ra, nếu thực hiện hành vi tố cáo góp phần xây dựng nên những điều tốt đẹp thì công dân còn được khuyến khích, được khen thưởng. Điều này đã được quy định tại Nghị định số 7/2012/NĐ – CP.

2. Phân biệt tố cáo và tố giác

Có rất nhiều người nhầm lẫn khái niệm tố cáo và tố giác vì có vẻ các phát âm của chúng tương tự nhau và giá trị của chúng cũng chẳng khác nhau nhiều. Thế nhưng, nếu bạn nhầm lẫn hai khái niệm này thì việc thực hiện quyền pháp luật của mình sẽ gặp phải những khó khăn, rắc rối nào đó không mong muốn và còn mang đến những khó khăn cho các cơ quan Nhà nước trong quá trình giải quyết đơn tố cáo và đơn tố giác.

Giữa tố cáo và tố giác đương nhiên sẽ được phân biệt với nhau bởi những điểm khác nhau cơ bản nhất. Khi phân biệt rõ hai loại hành vi này từ người thực hiện quyền pháp luật thì sẽ giúp cho cơ quan chức năng có thẩm quyền có thể xác định được đúng bản chất vấn đề, từ đó có thể giải quyết thuận lợi công việc, mang đến sự hiệu quả và chính xác về kết quả và thủ tục.

4.1. Sự khác nhau về khái niệm tố cáo và tố giác

Khái niệm tố cáo và tố giác đã được định nghĩa rõ ràng ở trong các văn bản chuẩn mực được ban hành dưới sự phê duyệt của Nhà Nước. Theo đó, chúng ta có thể dễ dàng tìm hiểu khái niệm và từ đó nhận diện chính xác thế nào là tố cáo và tố giác.

Về khái niệm tố cáo

Trong từ điển tiếng Việt có nêu rõ như sau: tố cáo là “báo cho mọi người hoặc cơ quan có thẩm quyền biết người hoặc hành động phạm pháp nào đó” , là “vạch trần hành động xấu xa, phạm pháp hay tội ác trước cơ quan có thẩm quyền hoặc trước dư luận”.

Không chỉ dựa vào từ điện, tại Bộ luật Tố cáo cũng chỉ rõ rằng: tố cáo là “việc cá nhân theo thủ tục quy định của Luật này báo cho cơ quan, tổ chức, cá nhân có thẩm quyền biết về hành vi vi phạm pháp luật của bất kỳ cơ quan, tổ chức, cá nhân nào gây thiệt hại hoặc đe dọa gây thiệt hại đến lợi ích của Nhà nước, quyền và lợi ích hợp pháp của cơ quan, tổ chức, cá nhân” (Điều 2, Luật Tố cáo 2024)

Về khái niệm tố giác

Cũng tương tự như tố cáo, khái niệm tố giác được định nghĩa cụ thể trong các văn bản quy phạm, gồm có:

Theo từ điển Tiếng Việt, tố giác được hiểu như sau: “Báo cho cơ quan chính quyền biết người hoặc hành động phạm pháp nào đó”.

Còn trong văn bản pháp luật, tại điều 144 Bộ luật Tố tụng hình sự 2024 cho hay: “Tố giác về tội phạm là việc cá nhân phát hiện và tố cáo hành vi có dấu hiệu tội phạm với cơ quan có thẩm quyền”. Khi thực hiện tố giác, báo tin về tội phạm thì người tố giác có thể thực hiện bằng văn bản hoặc bằng lời nói.

Nếu như cố ý tố giác hoặc báo tin sai sự thật thì tùy vào mức độ, tính chất vi phạm cá nhân đó sẽ bị xử lý, xử phạt về hành chính, nghiêm trọng hơn là bị truy cứu trách nhiệm hình sự theo những gì pháp luật đã quy định. Điều này được quy định rõ tại Khoản 4, Điều 5 của Bộ luật tố tụng 2024.

Như vậy, thông qua các khái niệm có thể hiểu đơn giản về sự khác biệt giữa tố cáo và tố giác như sau:

Tố cáo là: hành vi vi phạm pháp luật không có sự phân biệt về mức độ và tính chất vi phạm, còn tố giác chỉ gồm hành vi vi phạm pháp luật có thể cấu thành tội phạm.

Tố giác là: việc tố cáo hành vi trái pháp luật.

Ở một khía cạnh khác, tố cáo chính là quyền của công dân; còn tố giác vừa là quyền lại vừa là nghĩa vụ của người công dân. Chỉ khi nào công dân thực hiện quyền tố cáo của mình thì mới phát sinh các quan hệ pháp luật, còn với tố giác, các mối quan hệ pháp luật sẽ phát sinh ngay khi người công dân đó biết về kẻ vi phạm.

4.2. Những điểm khác biệt về chủ thể của tố cáo và tố giác

Tố cáo có chủ thế là các cá nhân có tên tuổi và địa chỉ cụ thể, chi tiết trong khi chủ thể của tố giác là một cá nhân, mà cá nhân này cho rằng có một hành vi vi phạm pháp luật đã xảy ra hoặc có thể xảy ra và có dấu hiệu tội phạm. Vì không phải là nguồn tin chắc chắn cho nên việc tố giác chỉ được xem là một hình thức cung cấp thông tin, nêu ra những dấu hiệu, sự việc vi phạm pháp luật cho cơ quan xem xét và điều tra làm rõ.

4.3. Đối tượng của tố cáo khác tố giác như thế nào?

Tố cáo có đối tượng là các hành vi vi phạm pháp luật ở trong tất cả các lĩnh vực, các đối tượng đó không bị phân biệt về tính chất cũng như mức độ của sự vi phạm. Còn đối tượng của tố giác chỉ là những hành vi vi phạm có thể cấu thành tội phạm, chỉ mang dấu hiệu có thể vi phạm pháp luật và chưa được xác thực tại thời điểm tố giác.

Cuối cùng, thông qua bài viết này, hy vọng các bạn có thể hiểu được tố cáo là gì? Đơn tố cáo là gì? Từ đây bạn cần hiểu rõ rằng, quyền tố cáo của người công dân chính là cách chúng ta đang thể hiện quyền làm chủ của chính mình đối với việc quản lý và củng cố bộ máy nhà nước thêm vững chắc. Tố cáo đồng thời là cách để bạn có thể bảo vệ những quyền lợi và lợi ích hợp pháp cho chính mình, cho những công dân khác và cho các cơ quan nhà nước.

” Hình thức tố cáo theo Luật Tố cáo 2024

” Tố cáo sai sự thật xử lý như thế nào?

Yếu Tố Biểu Cảm Trong Văn Nghị Luận

1. Các biểu hiện

Yếu tố biểu cảm trong văn nghị luận được biểu hiện dưới các dạng thức như sau:

– Tính khẳng định hay phủ định.

– Biểu lộ các cảm xúc như yêu, ghét, căm giận, quý mến, khen, chê, lo âu, tin tưởng…

– Giọng văn.

2. Ví dụ

a. “Đồng bào Nam Bộ là dân nước Việt Nam. Sông có thể cạn, núi có thể mòn, song chân lí đó không bao giờ thay đổi!”.

(Thư gửi đồng bào Nam Bộ – Hồ Chí Minh)

b. “Các em là đội cảm tử. Các em cảm tử để cho Tổ quốc quyết sinh. Các em là đại biểu cái tinh thần tự tôn tự lập của dân tộc ta mấy nghìn năm để lại, cái tinh thần quật cường đó đã kinh qua Hai Bà Trưng, Lý Thường Kiệt, Trần Hưng Đạo, Lê Lợi, Quang Trung, Phan Đình Phùng, Hoàng Hoa Thám, truyền lại cho các em.

Nay các em gan góc tiếp tục cái tinh thần bất diệt đó, để truyền lại cho nòi giống Việt Nam muôn đời mai sau”.

Hà Nội, ngày 27.1.1947 (Thư gửi các chiến sĩ quyết tử quân thủ đô – Hồ Chí Minh)

c. “Thơ Người (Bác Hồ) nói ít mà gợi nhiều, là loại thơ có màu sắc thanh đạm, có âm thanh trầm lặng, không phô diễn mà như cố khép lại trong đường nét để cho người đọc tự thưởng thức lấy cái phần ý ở ngoài lời. Phải yên lặng một mình ngồi đọc thơ Người, phải thỉnh thoảng ngừng lại để suy nghĩ mới cảm thấy hết những âm vang của nó, và nghe những âm vang của nó, và nghe những âm vang ây cứ ngân dài mãi”

(Rô-giê Đơ-nuy – Pháp)

d. “Thấy cuộc đời luôn luôn thay đổi, lúc thịnh lúc suy, khi trị khi loạn, tang thương biến cố vô cùng, người xưa chi biết ngưỡng mặt lên trời mà hỏi một câu rất đau đớn “than ôi, ai đã làm ra chuyện ấy?”.

Ngày nay, giờ mỗi trang lịch sử loài người là ta thấy mỗi trang biến động, nào cách mệnh, nào chiến tranh, chế độ cũ đổ, chế độ mới thay vào, xương chất thành núi, máu chảy thành sông, cuộc tiến hóa cứ lôi kéo loài người đi tới trên những quãng đường gập ghểnh, khuất khúc; mà sự xài phí về nhân mạng giống chừng không ai đếm xỉa tới.

Ta tuy không như người xưa chỉ ngưỡng mặt lên trời, nhưng ta cũng nên bình tâm mà hỏi thử: “Cái gì đã thúc giục, đã xúc sử những biến động ấy?”.

(Văn học và sinh hoạt xã hội – Hải Triều)

e… “Một dân tộc đã gan góc chống ách nô lệ của Pháp hơn 80 mươi năm nay, một dân tộc đã gan góc đứng về phe Đồng minh chống phát xít mấy năm nay, dân tộc đó phải được tự do! Dân tộc đó phải được độc lập!”.

Hồ Chí Minh (Tuyên ngôn Độc lập 2-9-1945)

chúng tôi

Tiền Tố Blob Là Gì: Http:

Tôi đang sử dụng safari và không chắc nó có hoạt động trong các trình duyệt khác không, nhưng khi tôi đăng ký tài khoản đường dẫn bão, tôi thấy URL sau

blob:https://api.stormpath.com/1be95204-93d6-4GUID HERE

Tiền tố blob: mới đối với tôi và tôi muốn biết liệu nó có hoạt động trên tất cả các trình duyệt hay không và những tiền tố nào khác có thể tồn tại.

Blob URI / URL được tạo bởi JavaScript, đề cập đến dữ liệu mà trình duyệt của bạn hiện có trong bộ nhớ (chỉ trong trang hiện tại) và không đề cập đến dữ liệu tồn tại trên máy chủ.

Để biết thêm thông tin để sử dụng, hãy xem: https://www.npmjs.com/package/blob-util

Bắt đầu một URL cho đến dấu hai chấm đầu tiên được gọi là “lược đồ URI” (hoặc “lược đồ URL”). Googling đã blob URI schemetiết lộ những nỗ lực API tệp của W3C .

Hầu hết các lược đồ URI không có các quy định chuẩn để chứa toàn bộ URI khác, vì vậy bạn sẽ không nghĩ chúng là tiền tố cho toàn bộ URI khác. Bên cạnh http: và https:, một số lược đồ URI phổ biến bao gồm:

…và nhiều cái khác. Tôi chắc chắn rằng tôi đang bỏ qua yêu thích của mọi người. 🙂

Tôi sao chép và dán câu trả lời từ StackOverflow vì thông tin cơ bản về blob trong chuỗi URL.

Blob Không thể chuyển đổi URL được tạo từ JavaScript thành URL “bình thường”.

Trả lời blob: URL không đề cập đến dữ liệu tồn tại trên máy chủ, nó đề cập đến dữ liệu mà trình duyệt của bạn hiện có trong bộ nhớ, cho trang hiện tại. Nó sẽ không có sẵn trên các trang khác, nó sẽ không có sẵn trong các trình duyệt khác và nó sẽ không có sẵn từ các máy tính khác.

Do đó, nói chung, không có ý nghĩa gì khi chuyển đổi URL Blob thành URL “bình thường”. Nếu bạn muốn một URL thông thường, bạn sẽ phải gửi dữ liệu từ trình duyệt đến máy chủ và yêu cầu máy chủ cung cấp nó như một tệp thông thường.

Có thể chuyển đổi một blob: URL thành dữ liệu: URL, ít nhất là trong Chrome. Bạn có thể sử dụng yêu cầu AJAX để “tìm nạp” dữ liệu từ blob: URL (mặc dù nó thực sự chỉ lấy nó ra khỏi bộ nhớ của trình duyệt, không tạo yêu cầu HTTP).

MDN là một nguồn tốt để hiểu mọi thứ bằng ngôn ngữ đơn giản. Tôi cũng sẽ đề xuất https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL là một tài nguyên tốt. Họ cũng hiển thị thông số kỹ thuật W3C ở cuối trang của họ, giống như thông số của Spiff được cung cấp, nhưng thông số kỹ thuật ban đầu có thể dài dòng và khó đọc. Tôi muốn nói Spiff là chính xác nhất để liên kết bạn với các tài liệu W3C.

Tôi không nghĩ rằng liên kết đến npmjs mà Masoud cung cấp là rất hữu ích. Nó hướng bạn đến một thư viện Javascript trên npmjs của thư viện. Thư viện blob-produc được sử dụng để bao bọc API tiêu chuẩn trong trình duyệt để hoạt động với các đốm màu và nó đơn giản hóa mã viết cho những thứ này, nhưng nó không phải là một tài liệu tham khảo tốt để hiểu các URL blob và chúng là gì.

Cập nhật thông tin chi tiết về Algorithm – Chuyển Biểu Thức Trung Tố Sang Tiền Tố Và Hậu Tố Bằng Stack trên website 2atlantic.edu.vn. Hy vọng nội dung bài viết sẽ đáp ứng được nhu cầu của bạn, chúng tôi sẽ thường xuyên cập nhật mới nội dung để bạn nhận được thông tin nhanh chóng và chính xác nhất. Chúc bạn một ngày tốt lành!