تحويل int إلى string باستخدام std::format في وقت التجميع
تُعتبر التحويلات بين الأنواع المختلفة في البرمجة من الوظائف الأساسية التي يحتاجها المطورون. في لغة C++، قد يكون من الضروري أحيانًا تحويل عدد صحيح (int) إلى سلسلة نصية (string) بطريقة فعالة. مع تحديثات C++23، أصبح لدينا أدوات جديدة تتيح لنا تنفيذ هذه المهام بطريقة تختلف عن الأساليب التقليدية. في هذا المقال، سنستعرض كيفية تحويل int إلى string باستخدام std::format
في وقت البناء.
فهم الأساليب التقليدية لتحويل الأعداد إلى سلاسل نصية
قبل توضيح كيفية استخدام std::format
في C++23، من المهم أن نفهم بعض الطرق التقليدية التي وُجدت سابقًا. يقوم بعض المطورين باستخدام وحدات الماكرو للتعامل مع الأعداد وتحويلها إلى نصوص كما هي، باستخدام التعليمات البرمجية مثل:
#define STRINGIFY_HELP(x) #x
#define STRINGIFY(x) STRINGIFY_HELP(x)
static_assert(STRINGIFY(012)[0] == '0');
static_assert(STRINGIFY(012)[1] == '1');
static_assert(STRINGIFY(012)[2] == '2');
static_assert(STRINGIFY(012)[3] == '#define STRINGIFY_HELP(x) #x
#define STRINGIFY(x) STRINGIFY_HELP(x)
static_assert(STRINGIFY(012)[0] == '0');
static_assert(STRINGIFY(012)[1] == '1');
static_assert(STRINGIFY(012)[2] == '2');
static_assert(STRINGIFY(012)[3] == '\0');
');
هنا، تُستخدم وحدات الماكرو لالتقاط التمثيل النصي الدقيق للرقم. لكن يتطلب هذا الحل مراعاة القوانين الخاصة بالأعداد في C++، مثل تفسير الأعداد ذات الصفر المبدئي كقيمة ثمانية.
استخدام القوالب والتحويل إلى نصوص
بدلاً من الأسلوب السابق، يمكن استخدام القوالب لتعريف دالة تقوم بتحويل الأعداد إلى نصوص. ولكن هذا الأسلوب يأتي مع بعض التحديات، حيث قد يؤدي إدخال عدد مثل 0123 إلى نتيجة غير متوقعة، إذ سيتم اعتباره عددًا ثمانيًا. إليك نموذجًا عن كيفية استخدام القوالب:
#include <string_view>
#include <array>
using namespace std;
constexpr size_t count_digits(unsigned int ui) {
size_t digits = 1;
while (ui >= 10) {
ui /= 10;
++digits;
}
return digits;
}
template<unsigned int UI>
constexpr auto ui_to_array() {
constexpr size_t digits = count_digits(UI);
array<char, digits + 1> arr{};
unsigned int ui = UI;
for (size_t i = digits; i-- > 0; ) {
arr[i] = '0' + (ui % 10);
ui /= 10;
}
arr[digits] = '#include <string_view>
#include <array>
using namespace std;
constexpr size_t count_digits(unsigned int ui) {
size_t digits = 1;
while (ui >= 10) {
ui /= 10;
++digits;
}
return digits;
}
template<unsigned int UI>
constexpr auto ui_to_array() {
constexpr size_t digits = count_digits(UI);
array<char, digits + 1> arr{};
unsigned int ui = UI;
for (size_t i = digits; i-- > 0; ) {
arr[i] = '0' + (ui % 10);
ui /= 10;
}
arr[digits] = '\0';
return arr;
}
constexpr auto array_to_string_view(const auto& A) {
return string_view(A.data(), A.size());
}
template<unsigned int UI>
constexpr auto ui_to_string_view() {
return array_to_string_view(ui_to_array<UI>());
}
int main() {
{
constexpr auto r = ui_to_string_view<123>();
static_assert(r[0] == '1');
static_assert(r[1] == '2');
static_assert(r[2] == '3');
static_assert(r[3] == '\0');
}
{
constexpr auto r = ui_to_string_view<0>();
static_assert(r[0] == '0');
static_assert(r[1] == '\0');
}
return 0;
}
';
return arr;
}
constexpr auto array_to_string_view(const auto& A) {
return string_view(A.data(), A.size());
}
template<unsigned int UI>
constexpr auto ui_to_string_view() {
return array_to_string_view(ui_to_array<UI>());
}
int main() {
{
constexpr auto r = ui_to_string_view<123>();
static_assert(r[0] == '1');
static_assert(r[1] == '2');
static_assert(r[2] == '3');
static_assert(r[3] == '#include <string_view>
#include <array>
using namespace std;
constexpr size_t count_digits(unsigned int ui) {
size_t digits = 1;
while (ui >= 10) {
ui /= 10;
++digits;
}
return digits;
}
template<unsigned int UI>
constexpr auto ui_to_array() {
constexpr size_t digits = count_digits(UI);
array<char, digits + 1> arr{};
unsigned int ui = UI;
for (size_t i = digits; i-- > 0; ) {
arr[i] = '0' + (ui % 10);
ui /= 10;
}
arr[digits] = '\0';
return arr;
}
constexpr auto array_to_string_view(const auto& A) {
return string_view(A.data(), A.size());
}
template<unsigned int UI>
constexpr auto ui_to_string_view() {
return array_to_string_view(ui_to_array<UI>());
}
int main() {
{
constexpr auto r = ui_to_string_view<123>();
static_assert(r[0] == '1');
static_assert(r[1] == '2');
static_assert(r[2] == '3');
static_assert(r[3] == '\0');
}
{
constexpr auto r = ui_to_string_view<0>();
static_assert(r[0] == '0');
static_assert(r[1] == '\0');
}
return 0;
}
');
}
{
constexpr auto r = ui_to_string_view<0>();
static_assert(r[0] == '0');
static_assert(r[1] == '#include <string_view>
#include <array>
using namespace std;
constexpr size_t count_digits(unsigned int ui) {
size_t digits = 1;
while (ui >= 10) {
ui /= 10;
++digits;
}
return digits;
}
template<unsigned int UI>
constexpr auto ui_to_array() {
constexpr size_t digits = count_digits(UI);
array<char, digits + 1> arr{};
unsigned int ui = UI;
for (size_t i = digits; i-- > 0; ) {
arr[i] = '0' + (ui % 10);
ui /= 10;
}
arr[digits] = '\0';
return arr;
}
constexpr auto array_to_string_view(const auto& A) {
return string_view(A.data(), A.size());
}
template<unsigned int UI>
constexpr auto ui_to_string_view() {
return array_to_string_view(ui_to_array<UI>());
}
int main() {
{
constexpr auto r = ui_to_string_view<123>();
static_assert(r[0] == '1');
static_assert(r[1] == '2');
static_assert(r[2] == '3');
static_assert(r[3] == '\0');
}
{
constexpr auto r = ui_to_string_view<0>();
static_assert(r[0] == '0');
static_assert(r[1] == '\0');
}
return 0;
}
');
}
return 0;
}
هذه الشيفرة توضح كيفية احتساب عدد الأرقام في العدد المدخل، وتحويله لاحقًا إلى سلسلة نصية. من خلال الدوال القابلة للتنفيذ في وقت البناء، يمكنك إجراء عمليات التحقق في زمن الترجمة.
استخدام std::format في C++23
مع تقدم لغة C++، يقدم C++23 تحسينات مهمة، بما في ذلك وظيفة std::format
. تتيح لك هذه الوظيفة استخدام تنسيق النصوص بطريقة مرنة وسهلة، حيث يمكنك تمرير الأعداد بصورة مباشرة لتحصل على السلاسل النصية المطلوبة. يعد استخدام std::format
بديلاً ممتازًا للأساليب السابقة، إذ يمكنك كتابة الكود بوضوح وسهولة.
خاتمة
باختصار، يمتلك مطورو C++ خيارات متعددة لتحويل الأعداد إلى سلاسل نصية، سواء كانت تقليدية أو جديدة باستخدام C++23 وstd::format
. يساعد فهم هذه الخيارات في تحسين كفاءة الكود وجعل تطبيقاتك أكثر مرونة وسهولة في القراءة. باستخدام الطرق الموضحة هنا، يمكنك التعامل مع التحويلات الرقمية بطرق فعالة تناسب احتياجات برامجك. لذا، إذا كنت تسعى لتحسين معرفتك بلغة C++، فإن التعرف على كيفية تحويل int إلى string باستخدام std::format
في وقت البناء يعد خطوة هامة تستحق استكشافها.