چرا بیان C ++ برای ‘x3 – y’ اشتباه ارزیابی می شود؟

مقدمه
هنگام ارزیابی رشته عبارت x3 - y
در C ++ ، بسیاری از توسعه دهندگان با نتایج غیر منتظره روبرو می شوند. در مورد شما ، شما مشاهده می کنید که این عبارت ارزیابی می کند -1
چه زمانی باید بازده شود 2
، با توجه به آن x3
است ، 3
وت y
است ، 1
بشر در این مقاله به بررسی این موضوع می پردازیم که چرا این اختلاف رخ می دهد و چگونه می توان متغیرها را با استفاده از کتابخانه exprtk به درستی رسیدگی کرد.
درک مسئله
در ExprTk
کتابخانه امکان ارزیابی در زمان واقعی عبارات ریاضی در C ++ را فراهم می کند. در قطعه کد ارائه شده ، مقادیر را به درستی اختصاص می دهید x3
وت y
، با این حال عبارت نادرست ارزیابی می شود. جنبه مهم برای توجه در اینجا تفاوت بین است add_variable()
وت create_variable()
، که منجر به رفتار غیر منتظره در نحوه ذخیره متغیرها در جدول نماد می شود.
چرا خروجی نادرست است؟
سردرگمی اولیه از چگونگی add_variable()
وت create_variable()
مدیریت منابع متغیر را مدیریت کنید. با add_variable()
، شما به طور موثری مقدار را در جدول نماد در زمان افزودن کپی می کنید. در نتیجه ، هنگام ارزیابی عبارت ، هرگونه تغییر در متغیر ارجاع شده پس از افزودن آن منعکس نمی شود زیرا فقط مقدار اصلی تصویب شده در آن زمان را در خود جای داده است.
در مقابل ، create_variable()
مرجع متغیر واقعی را حفظ می کند. با استفاده از این روش ، هرگونه به روزرسانی در متغیر در ارزیابی های بیان منعکس می شود. از این رو ، خروجی دقیق و همانطور که انتظار می رود است.
توضیح کد مثال
بیایید کد فعلی خود را تجزیه کنیم تا مفاهیم را نشان دهیم:
void test() {
typedef exprtk::symbol_table symbol_table_t;
typedef exprtk::expression expression_t;
typedef exprtk::parser parser_t;
std::string expression_str = "x3 - y";
symbol_table_t symbol_table;
double y = 1;
std::vector xs;
for (int i = 0; i < 5; i++) {
xs.push_back(i);
// Use this line to give the correct output
// symbol_table.create_variable("x" + std::to_string(i), xs[i]);
symbol_table.add_variable("x" + std::to_string(i), xs[i]); // This causes issues
}
symbol_table.add_variable("y", y);
std::cout << symbol_table.get_variable("x3")->value() << " " << symbol_table.get_variable("y")->value() << std::endl; // x3 == 3, y == 1
expression_t expression;
expression.register_symbol_table(symbol_table);
parser_t tmp_parser;
tmp_parser.compile(expression_str, expression);
std::cout << expression.value(); // Output is -1
}
مراحل اصلاح کد
برای رفع مشکل ارزیابی ، جایگزین کنید add_variable()
روش با create_variable()
بشر بیایید ببینیم کد به روز شده چگونه به نظر می رسد:
کد مثال به روز شده
void test() {
typedef exprtk::symbol_table symbol_table_t;
typedef exprtk::expression expression_t;
typedef exprtk::parser parser_t;
std::string expression_str = "x3 - y";
symbol_table_t symbol_table;
double y = 1;
std::vector xs;
for (int i = 0; i < 5; i++) {
xs.push_back(i);
symbol_table.create_variable("x" + std::to_string(i), xs[i]); // Corrected line
}
symbol_table.add_variable("y", y);
std::cout << symbol_table.get_variable("x3")->value() << " " << symbol_table.get_variable("y")->value() << std::endl; // x3 == 3, y == 1
expression_t expression;
expression.register_symbol_table(symbol_table);
parser_t tmp_parser;
tmp_parser.compile(expression_str, expression);
std::cout << expression.value(); // Now output should be 2
}
در این نسخه اصلاح شده ، شما به طور موثری به آن متصل می شوید x
متغیرهای مقادیر مربوطه به صورت پویا ، اطمینان حاصل می کنند که هر به روزرسانی متغیر به طور مستقیم در ارزیابی های بیان منعکس می شود.
سوالات متداول
1. تفاوت بین چیست add_variable()
وت create_variable()
؟
add_variable()
مقدار را در زمان افزودنی کپی می کند ، در حالی که create_variable()
مرجع به متغیر اصلی را حفظ می کند ، و اطمینان می دهد که تغییرات در ارزیابی بیان منعکس می شود.
2. چرا بیان من همانطور که انتظار می رود ارزیابی نمی کند؟
اگر استفاده می کنید add_variable()
، این عبارت ممکن است از مقادیر منسوخ شده استفاده شود که در زمان افزودن به جای مقادیر فعلی کپی شده اند.
3. آیا می توانم استفاده کنم add_variable()
در هر سناریویی؟
بهتر است استفاده کنید add_variable()
برای ثابت یا مقادیری که در طول چرخه عمر ارزیابی بیان تغییر نمی کنند. برای متغیرهای پویا که تغییر می کنند ، ترجیح می دهند create_variable()
بشر
پایان
با تعویض از add_variable()
به create_variable()
، شما می توانید با استفاده از این پرونده به اختلاف در ارزیابی بیان در کد C ++ خود بپردازید ExprTk
کتابخانه این امر نه تنها صحت را تضمین می کند ، بلکه درک اساسی از کنترل متغیر در ارزیابی بیان پویا را نیز نشان می دهد. این رویکرد روشی واضح تر و مطمئن تر برای انجام محاسبات با مقادیر پویا در برنامه های شما فراهم می کند.