E. Макро зарлах

хугацааны хязгаарлалт 3 секунд

санах ойн хязгаарлалт 256 мегабайт

оролт стандарт оролт

гаралт стандарт гаралт

Ихэнх C/C++ програмчид #define-н олгож байгаа боломжуудыг мэддэг боловч буруу ашигласнаасаа болж асуудалд орох нь олонтаа.

Энэ бодлого нь #define-аар зарласан бичиглэл буюу макроны тухай юм. Макро болгонд нэр ба утга байна. Ерөнхий тохиолдолд макрог дараах байдлаар зарладаг:

#define macro_name macro_value

Макро зарлагдсан бол тухайн програм дахь macro_name нь macro_value-аар солигддог. (Гэхдээ зөвхөн тодорхой нөхцөлд л, жишээ нь macro_name нь хоёр талдаа зай юм уу үсгэн бус тэмдэгтээр хашигдсан байх үед гэх мэт). Уг бичиглэл дэх macro_value нь зөвхөн арифметик илэрхийлэл, арифметикийн дөрвөн үйлдэл, хаалт, мөн өмнө нь зарлагдсан өөр макроны нэр байж болдог. Макрог түүний утгаар сольж буй уг үйл явцыг орлуулалт гэж нэрлэдэг.

Макро ашиглахад үүсдэг үндсэн асуудлуудын нэг нь орлуулалтуудын дараа бид бодогдох дарааллын хувьд өөрчлөгдчихсөн арифметикийн илэрхийлэлтэй болдог буюу хаалттай болон хаалтгүй үед арифметик үйлдлүүдийн бодогдох дараалал өөр өөр болчихсон байдаг.

Нэгэн жишээг авч үзье. Бид доорх макрог зарласан ба

#define sum x + y

програмд 2 * sum гэсэн илэрхийлэл байсан гэе. Макро орлуулалтын дараа бид 2 * x + y гэсэн илэрхийлэлтэй болно. Гэвч бид 2 * (x + y) илэрхийллийг хүсч байгаа.

Хэрэв макро орлуулалтын дараа илэрхийллийн бодогдох дараалал өөрчлөгдөж, макроны мэдлээс давж байвал уг байдлыг "сэжигтэй" гэж нэрлэе. Ингээд таны даалгавар бол #define зарлагаа ба илэрхийлэл өгөгдсөн байхад эдгээр нь сэжигтэй эсэхийг тогтоох юм.

Илүү тодорхой өгүүлбэл, бид өгөгдсөн илэрхийлэл доторх хялбар макро орлуулалтыг биелүүлэх ёстой. Цаашлаад бид өгөгдсөн илэрхийлэл доторх макро орлуулалтыг "найдвартай" болгохын тулд макроны утга бүрийн гадуур хаалтаар хашиж өгнө. Үүний дараагаар арифметикийн хуулийг дагаж хаалт задлахын тулд бид зарим хаалтыг авч хаях хэрэг гарна. Хэрэв илэрхийллийг гаргаж авах боломжит арга байх юм бол уг хялбар орлуулалтын аргын үр дүн нь бодит илэрхийлэлтэй яг таарах болно (тэмдэгт бүрээрээ, хоосон зайг тооцохгүй). Энэ тохиолдолд тухайн макро болон илэрхийллийн системийг зөв, үгүй бол "сэжигтэй" гэж үзнэ.

"/" гэсэн тэмдэглэгээ нь C/C++ дээр байдаг шиг бүхлээр хуваах үйлдэл бус энгийн математик хуваалт гэж авч үзнэ. Яагаад гэвэл жишээ нь "a*(b/c)" илэрхийллийн хаалтыг авахад дараах илэрхийлэл бий болох юм: "a*b/c".

Оролт

Эхний мөрөнд зөвхөн $N$ ($0 ≤ N ≤ 100$) буюу #define зарлалтуудын тоо байна.

Дараагийн $N$ мөрөнд мөр бүрт нэг #define зарлалт байна.

#define name expression

  • name - макроны нэр
  • expression - өгөгдсөн макро сольж тавих илэрхийлэл. Илэрхийлэл нь хоосон бус, цифр, хувьсагчийн нэр, өмнө нь тодорхойлогдсон макроны нэр, дугуй хаалт болон үйлдлүүдийн тэмдэгт болох +-*/ зэргээс бүрдэнэ. Уг илэрхийлэл нь унари бус, үнэн зөв арифметик байна. Илэрхийлэлд агуулагдах тоонууд нь $10^{9}$-аас хэтрэхгүй ба сөрөг биш бүхэл тоо байна.

Бүх нэрүүд (макроны болон бусад ашиглагдах нэрнүүд) том жижиг нь ялгаатай латин үсгүүдээс бүрдэнэ. Мөн аль ч хувьсагчийн нэр нь аль ч #define зарлалтын нэртэй давхцахгүй гэж үзнэ.

Эцэст нь сүүлийн мөрөнд таны шалгах ёстой илэрхийлэл өгөгдөнө. Уг илэрхийлэл нь хоосон биш ба #define зарлалттай ижил хязгаарлалттай.

Оролтын мөрүүд нь хаана ч хамаагүй, хэдэн ч хоосон зай авсан байж магадгүй. Гэхдээ эдгээр хоосон зайнууд нь #define зарлалтын нэр, хувьсагчдын нэрийн дундуур орохгүй гэж үзнэ. Ялангуяа # тэмдэгтийн өмнө болон хойно талд нь хичнээн ч хоосон зай байж болно.

Оролтын файл дээрх мөр бүрийн урт нь 100-аас хэтрэхгүй.

Гаралт

Хэрвээ өгөгдсөн илэрхийлэл шалгууртай зөв таарч байвал "OK" үгүй бол "Suspicious" гэж гаргана.

Орчуулсан: gmunkhbaatarmn

Жишээ тэстүүд

Оролт
1
#define sum x + y
1 * sum
Гаралт
Suspicious
Оролт
1
#define sum  (x + y)
sum - sum
Гаралт
OK
Оролт
4
#define sum  x + y
#define mul  a * b
#define div  a / b
#define expr sum + mul * div * mul
expr
Гаралт
OK
Оролт
3
#define SumSafe   (a+b)
#define DivUnsafe  a/b
#define DenominatorUnsafe  a*b
((SumSafe) + DivUnsafe/DivUnsafe + x/DenominatorUnsafe)
Гаралт
Suspicious
Сэтгэгдлүүдийг ачааллаж байна...