زنگ

کسانی هستند که این خبر را قبل از شما می خوانند.
برای دریافت آخرین مقالات مشترک شوید.
پست الکترونیک
نام
نام خانوادگی
چگونه می خواهید The Bell را بخوانید
بدون اسپم
رشته رشته ای از شخصیت های ASCII یا UNICODE است. رشته های Cهمانطور که در اکثر زبانهای برنامه نویسی سطح بالا نوعی جداگانه در سیستم انواع اساسی زبان در نظر گرفته می شود. از آنجا که زبان C به دلیل منشاء آن یک زبان برنامه نویسی سیستم است ، هیچ نوع داده رشته ای در آن به این صورت وجود ندارد و آرایه های شخصیت معمولی به عنوان رشته در C استفاده می شوند.
از نظر تاریخی ، دو بازنمایی از قالب رشته وجود داشته است:
1. قالب ANSI؛
2. رشته های تهی صفر (مورد استفاده در SI).

فرمت ANSI مشخص می کند که اولین موقعیت در یک رشته ، طول آن است ، و در ادامه کاراکترهای رشته وجود دارد. به عنوان مثال ، نمایش رشته "رشته من!" به شرح زیر خواهد بود:
11 ‘M '‘ o' ’I '' '' '' '' '' ''‘ to '' a '‘!'
در رشته های بدون تهی ، کاراکترهای مهم در رشته در موقعیت اول مشخص می شوند ، و ترمینال رشته صفر است. نمایش رشته قبلاً در نظر گرفته شده در این قالب:
‘M '‘ o' ‘I '' '' '' '' 'p'‘ o "‘ to "‘ a "0!" 0

اعلام رشته در SI


رشته ها با استفاده از آرایه های شخصیت پیاده سازی می شوند. بنابراین ، یک بیانیه رشته ASCII دارای نحوی زیر است:
نام کاراکتر [طول]؛ آگهی رشته ها در سی دارای همان نحوی است که یک عبارت آرایه شخصیتی یک بعدی دارد. طول رشته باید یک عدد صحیح باشد (در استاندارد C89 یک ثابت است ، در استاندارد C99 می تواند یک عبارت باشد). طول رشته با در نظر گرفتن یک کاراکتر برای ذخیره صفر خاتمه مشخص می شود ، بنابراین حداکثر تعداد کاراکترهای مهم در یک رشته یکی از طول آن کمتر است. به عنوان مثال ، یک رشته می تواند حداکثر بیست کاراکتر داشته باشد اگر اینگونه اعلام شود:
خیابان شارژ؛ اولیه سازی رشته در C زمانی انجام می شود که با استفاده از نحو زیر اعلام شود:
char str [length] \u003d رشته واقعی؛ literal literal رشته ای از شخصیت های ASCII است که به صورت مضاعف محصور شده اند. نمونه هایی از اعلام رشته ها با اولیه:
char str1 \u003d "یک مقدار وارد کنید:"، str2 \u003d ""؛ مثال:
const char message \u003d "پیام خطا!"؛

کار با رشته ها در SI


از آنجا که رشته های C آرایه ای از کاراکترها هستند ، می توانید به شاخص آن به هر کاراکتر موجود در رشته مراجعه کنید. برای این کار ، نحو دستیابی به یک عنصر آرایه استفاده می شود ، بنابراین اولین شخصیت موجود در رشته دارای شاخص صفر است. به عنوان مثال ، در قطعه کد زیر در خط str ، همه شخصیت های "a" با کاراکتر "A" جایگزین می شوند و بالعکس.
برای (int i \u003d 0؛ str [i]! \u003d 0؛ i ++)
  {
if (str [i] \u003d\u003d "a") str [i] \u003d "A"؛
دیگری اگر (str [i] \u003d\u003d "A") str [i] \u003d "a"؛
  }

آرایه های رشته ای


اعلام رشته های رشته ای در زبان C نیز ممکن است. برای این کار از آرایه های شخصیتی دو بعدی استفاده شده است که دارای نحو زیر است:
نام char [مقدار] [طول]؛ اندازه اول ماتریس تعداد ردیف های موجود در آرایه را نشان می دهد ، و دومین - حداکثر (با در نظر گرفتن خاتمه صفر) طول هر سطر. به عنوان مثال ، اعلان یک آرایه از پنج رشته با حداکثر طول 30 کاراکتر قابل توجه خواهد بود:
char strs؛ هنگام اعلام رشته های رشته ، اولیه سازی می تواند انجام شود:
نام char [مقدار] [طول] \u003d
(رشته واقعی شماره 1 ، ... رشته تحت اللفظی #N)؛
تعداد لامپهای رشته ای باید با تعداد رشته های موجود در آرایه کمتر یا مساوی باشد. اگر تعداد لیترهای رشته ای از اندازه آرایه کمتر باشد ، سپس تمام عناصر دیگر در رشته های خالی تنظیم می شوند. طول هر حرف رشته باید به شدت کمتر از مقدار طول رشته (برای نوشتن یک صفر خاتمه) باشد.
مثلا:
روزهای جذاب \u003d (
"ژانویه فوریه مارس آوریل ماه مه" ،
"ژوئن" ، "جولای" ، "اوت" ، "سپتامبر" ، "اکتبر" ،
"نوامبر دسامبر"
  };
در هنگام اعلام رشته های رشته ای با اولیه ، مجاز نیست تعداد رشته ها را در براکت های مربع مشخص کنید. در این حالت ، تعداد خطوط موجود در آرایه به طور خودکار با تعداد آغازگرهای رشته اولیه مشخص می شود.
به عنوان مثال ، آرایه ای از هفت خط:
روزهای جذاب \u003d (
"دوشنبه سه شنبه چهارشنبه پنجشنبه"،
"جمعه شنبه یکشنبه"
  };

توابع کار با رشته ها در SI


کلیه کارکردهای کتابخانه برای کار با رشته ها می تواند به سه گروه تقسیم شود:
1. ورودی و خروجی رشته ها.
2. تبدیل رشته ها؛
3. رشته های پردازش.

ورودی و خروجی رشته ها در SI


می توانید از توابع ورودی و خروجی فرمت شده (printf و scanf) برای اطلاعات رشته و ورودی اطلاعات رشته استفاده کنید. برای انجام این کار ، هنگام وارد کردن یا خارج کردن متغیر رشته ، باید مشخصات نوع٪ s را در رشته فرمت مشخص کنید. به عنوان مثال ، ورودی و خروجی بعدی متغیر رشته ای عبارتند از:
char str \u003d ""؛
printf ("رشته را وارد کنید:")؛
اسکن ("٪ 30" ، خیابان)؛
printf ("شما وارد کردید:٪ s" ، خیابان)؛
ضرر عملکرد scff هنگام وارد کردن داده های رشته ای این است که محدود کننده های این عملکرد عبارتند از:
خوراک 1. خط ،
2. جدول بندی؛
3. فضای
بنابراین ، با استفاده از این تابع غیر ممکن است یک رشته حاوی چندین کلمه جدا شده توسط فاصله ها یا زبانه ها غیرممکن باشد. به عنوان مثال ، اگر در برنامه قبلی کاربر وارد رشته شود: "پیام چند کلمه" ، فقط "پیام" روی صفحه نمایش داده می شود.
كتابخانه stdio.h شامل كاربردهاي تخصصي براي ورود و خروج رشته ها است.

تابع می شود برای وارد کردن رشته ها و عنوان زیر را دارد:
char * می شود (char * buffer)؛

تابع put برای خروجی رشته ها طراحی شده است و دارای عنوان زیر است:
int قرار می دهد (const char * string)؛ ساده ترین برنامه: ورودی و خروجی یک رشته با استفاده از توابع get و put قرار می گیرد:
char str \u003d ""؛
printf ("رشته را وارد کنید:")؛ می شود (خیابان)؛
printf ("شما وارد کردید:")؛
قرار می دهد (خیابان)؛
علاوه بر توابع ورودی و خروجی به جریانها ، کتابخانه stdio.h شامل توابع برای ورودی فرمت شده و خروجی به رشته ها است. تابع ورودی قالب بندی شده از رشته دارای عنوان زیر است:
int sscanf (const char * محدود کردن بافر ، const char * محدود کردن رشته ، ...)؛ خروجی قالب بندی شده برای توابع رشته دارای عنوانهای زیر است:
int sprintf (char * محدود کردن بافر ،

int snprintf (char * limit buffer، size_t حداکثر،
قالب const char * محدود کردن ، ...)؛

رشته ها را تغییر می دهد


در C برای تبدیل رشته های حاوی اعداد به مقادیر عددی در کتابخانه stdlib.h
مجموعه عملکردهای زیر ارائه شده است:
دو برابر (const char * string)؛ // تبدیل یک رشته به دو برابر
int atoi (const char * string)؛ // تبدیل یک رشته به تعدادی از نوع int
طوفان int int (const char * string)؛ // تبدیل یک رشته به int int
atoll int long long (const char * string)؛ // تبدیل یک رشته به تعدادی از نوع طولانی int int
بازنمایی صحیح یک عدد واقعی در یک متن باید از قالب زیر باشد:
[(+ | -)] [رقم] [. رقم] [(e | E) [(+ | -)] رقم]

پس از کاراکترهای E ، e ، ترتیب شماره نشان داده می شود. نمایش صحیح یک عدد صحیح در یک متن باید از قالب زیر باشد:
[(+ | -)] رقم

علاوه بر توابع فوق ، کتابخانه stdlib.h توابع زیر را برای تبدیل رشته ها به اعداد واقعی نیز فراهم می کند:
float strtof (const char * محدود کردن رشته ، char ** محدود کردن endptr)؛
double strtod (const char * محدود کردن رشته ، char ** محدود کردن endptr)؛
بلند دو برابر طولانی (const char * محدود کردن رشته ، char ** محدود کردن endptr)؛

توابع مشابه برای تبدیل رشته ها به مقادیر عدد صحیح وجود دارد:
طولانی int strtol (const char * محدود کردن رشته ،

strtoul طولانی امضا نشده (رشته const char * محدود ،
char ** محدود کردن endptr ، int int)؛
طولانی int strtoll (const char * محدود کردن رشته ،
char ** محدود کردن endptr ، int int)؛
strtoull طولانی طولانی امضا نشده (const char * محدود کردن رشته ، char ** محدود کردن endptr ، پایگاه int).

توابع تبدیل معکوس (مقادیر عددی به رشته ها) در کتابخانه stdlib.h وجود دارند ، اما طبق استاندارد تنظیم نشده اند و در نظر گرفته نمی شوند. توابع sprintf و snprintf برای تبدیل مقادیر عددی به رشته ها مناسب تر هستند.

پردازش رشته


کتابخانه string.h شامل توابع برای اقدامات مختلف روی رشته ها است.
تابع محاسبه طول رشته:
size_t strlen (const char * string)؛ مثال:
char str \u003d "1234"؛
int n \u003d strlen (str)؛ // n \u003d\u003d 4
توابع کپی رشته:
char * strcpy (char * limit dst، const char * limit src)؛
char * strncpy (char * limit dst، const char * limit src، size_t num)؛
توابع مقایسه رشته:
int strcmp (const char * string1، const char * string2)؛
int strncmp (const char * string1، const char * string2، size_t num)؛
توابع رشته ها را با حروف الفبا مقایسه می کنند و باز می گردند:
مقدار مثبت - اگر string1 بیشتر از string2 باشد؛
مقدار منفی - اگر string1 کمتر از string2 باشد؛
مقدار null - اگر string1 برابر با string2 باشد؛

توابع جمع بندی (جمع بندی) رشته ها:
char * strcat (char * limit dst، const char * limit src)؛
char * strncat (char * limit dst، const char * limit src، size_t num)؛

جستجوی توابع برای کاراکتر در یک رشته:
char * strchr (const char * string، int c)؛
char * strrchr (const char * string، int c)؛

تابع جستجو رشته در رشته:
char * strstr (const char * str، const char * substr)؛

مثال:
char str \u003d "رشته جستجو"؛
char * str1 \u003d strstr (str، "for")؛ // str1 \u003d\u003d "جستجو"

تابع جستجو برای اولین کاراکتر در یک رشته از مجموعه کاراکترهای داده شده:
size_t strcspn (const char * str، const char * charset)؛

توابع برای پیدا کردن شخصیت اول در یک رشته که متعلق به مجموعه کاراکترهای مشخصی نیست:
size_t strspn (const char * str، const char * charset)؛

توابع برای پیدا کردن اولین کاراکتر در یک رشته از مجموعه کاراکترهای خاص:
char * strpbrk (const char * str، const char * charset)؛

عملکرد جستجو برای حرف بعدی در رشته:
char * strtok (char * string string، const char * محدودیت charset)؛

کار با رشته ها. کلاس رشته. سازندگان کلاس وظایف اختصاص () ، پیوست () ، درج () ، جایگزین () ، پاک کردن () ، پیدا کردن () ، rfind () ، مقایسه () ، c_str (). نمونه هایی از

1. منظور از کلاس رشته در برنامه های C ++ چیست؟

کلاس رشته به گونه ای طراحی شده است که با رشته های نوع char * کار کند ، که رشته هایی با تهی هستند. کلاس رشته به عنوان جایگزینی برای کار با رشته های نوع char * معرفی شد. خط هایی که با یک شخصیت ختم می شوند ‘\0’ رشته های C نیز نامیده می شود. از آنجا که رشته یک کلاس است ، می توانید اشیاء این کلاس را اعلام کنید.

2- برای استفاده از قابلیت های کلاس رشته در MS Visual Studio C ++ چه ماژول هایی (کتابخانه ای) لازم است؟

برای استفاده از قابلیت های کلاس رشته در MS Visual Studio (C ++) ، باید این کتابخانه را درج کنید و نام نامهای std

#عبارتند از با استفاده از namespace std؛
3- متغیر رشته رشته چگونه اعلام می شود؟ نمونه هایی از

اعلام متغیر رشته رشته به همان روش متغیر معمولی انجام می شود. اعلامیه اولیه اولیه ممکن است.

// string string string s1؛ // متغیر به نام s1 رشته رشته string s2 \u003d "این یک متغیر رشته است"؛ // اعلامیه با اولیه سازی // استفاده از متغیر رشته رشته با اپراتور واگذاری s1 \u003d s2؛ // s1 \u003d "این یک متغیر رشته است" s2 \u003d "متن جدید"؛
4- مزایا و مضرات استفاده از کلاس رشته در مقابل char * چیست؟

ایجاد نوع رشته جدید به دلیل نواقص کار با رشته های شخصیت بود که نوع char * آن را نشان داد. در مقایسه با نوع char * ، نوع رشته مزایای اصلی زیر را دارد:

  • توانایی پردازش رشته ها با اپراتورهای استاندارد C ++ ( = , + , = = , <> و غیره.). همانطور که می دانید هنگام استفاده از نوع char * ، حتی ساده ترین عملیات رشته ای پیچیده و نیاز به نوشتن کد برنامه نویسی بیش از حد به نظر می رسید.
  • اطمینان از قابلیت اطمینان بهتر (امنیت) کد برنامه. به عنوان مثال ، هنگام کپی کردن رشته ها ، نوع رشته اقدامات مناسبی را ارائه می دهد که اگر رشته منبع بزرگتر از رشته مقصد باشد می تواند رخ دهد.
  • ارائه یک رشته به عنوان یک نوع داده مستقل. اعلان نوع رشته به عنوان یک رشته برای همه متغیرهای برنامه یکسان است ، که ثبات داده ها را تضمین می کند.

مهمترین نقطه ضعف نوع رشته در مقایسه با نوع char * سرعت پردازش کندتر داده است. دلیل این است که نوع رشته در واقع یک کلاس ظروف است. و کار با کلاس نیاز به اجرای اضافی کد برنامه دارد که به نوبه خود زمان بیشتری را نیز می طلبد.

5- با استفاده از اشیاء رشته ای از چه عملگرهایی می توان استفاده کرد؟

کلاس رشته به این راحتی امکان پذیر است که به شما امکان می دهد رشته ها را با استفاده از اپراتورهای استاندارد (اضافه بار) به راحتی دستکاری کنید.

عملگرهای زیر را می توان با اشیاء کلاس رشته استفاده کرد

  • = - وظیفه
  • + - پیوستگی (جمع شدن رشته)
  • += - تکلیف با جمع بندی
  • == - برابری
  • != - نابرابری
  • < - کوچکتر
  • <= - کمتر یا مساوی
  • > - بیشتر
  • >= - بیشتر یا مساوی
  • - نمایه سازی

مثال، که استفاده از اپراتورهای فوق را نشان می دهد

// نوع رشته ، عملیات روی رشته ها string s1 \u003d "s-1"؛ string s2 \u003d "s-2"؛ رشته s3؛ بول؛ // عملیات "\u003d" (انتساب رشته ها) s3 \u003d s1؛ // s3 \u003d "s-1" // عملیات "+" - جمع بندی رشته s3 \u003d s3 + s2؛ // s3 \u003d "s-1s-2" // عملیات "+ \u003d" - تکلیف با جمع بندی s3 \u003d "s-3"؛ s3 + \u003d "abc"؛ // s3 \u003d "s-3abc" // عملیات "\u003d\u003d" - مقایسه رشته b \u003d s2 \u003d\u003d s1؛ // b \u003d false b \u003d s2 \u003d\u003d "s-2"؛ // b \u003d درست است // عملیات "! \u003d" - مقایسه رشته (مساوی نیست) s1 \u003d "s1"؛ s2 \u003d "s2"؛ b \u003d s1! \u003d s2؛ // b \u003d درست است // عملیات "<" и ">"- مقایسه رشته s1 \u003d "abcd"؛ s2 \u003d "de"؛ b \u003d s1\u003e s2؛ // b \u003d false b \u003d s1< s2; // b = true // عملیات "<=" и ">\u003d "- مقایسه رشته (کمتر از یا مساوی ، بزرگتر یا مساوی) s1 \u003d "abcd"؛ s2 \u003d "ab"؛ b \u003d s1\u003e \u003d s2؛ // b \u003d true b \u003d s1<= s2; // b = false b = s2 >\u003d "ab"؛ // b \u003d درست است // عملیات - نمایه سازی char c؛ s1 \u003d "abcd"؛ c \u003d s1؛ // c \u003d "c" c \u003d s1؛ // c \u003d "a"
6. آیا کلاس رشته شامل سازنده است؟

مانند هر کلاس ، کلاس رشته تعدادی سازنده نیز دارد. موارد اصلی به شرح زیر است:

رشته ()؛ رشته (const char * str)؛ رشته (consting & str)؛

7. نمونه هایی از اولیه سازی با استفاده از سازنده ها

در زیر نمونه هایی از اولیه سازی متغیرهای رشته وجود دارد

string s1 ("سلام!")؛ string s2 \u003d "سلام!" ؛ // اولیه سازی - رشته سازنده (const char * str) char * ps \u003d "سلام"؛ string s3 (ps)؛ // رشته اولیه سازی s4 (s3)؛ // اولیه سازی - رشته سازنده (string string & str) string s5؛ // اولیه سازی - رشته سازنده ()

8- اختصاص رشته ها. تابع () را اختصاص دهید. نمونه هایی از

برای اختصاص یک رشته به رشته دیگر ، می توانید یکی از دو روش را استفاده کنید:

  • از اپراتور واگذاری استفاده کنید ‘=’ ;
  • از کلاس () رشته استفاده کنید.

تخصیص () چندین پیاده سازی اضافه بار دارد.

گزینه اول فراخوانی یک تابع بدون پارامتر است

رشته و انتساب (باطل)؛

در این حالت ، یک تکلیف ساده از یک رشته به رشته دیگر وجود دارد.

گزینه دوم به شما امکان می دهد تعداد مشخصی از کاراکترها را از یک رشته کپی کنید:

رشته و انتساب (consting & s، st size_type، size_type num)؛

  • s - جسمی که رشته منبع از آن گرفته می شود.
  • st - index (موقعیت) در رشته ای که از آن شروع به کپی کردن کاراکتر های num؛
  • num - تعداد کاراکترهای کپی از موقعیت st؛
  • size_type یک نوع داده معمولی است.

نوع سوم تابع اختصاص () کاراکترهای شماره اول رشته را به تماس گیرنده کپی می کند:

رشته و اختصاص (const char * s، size_type num)؛

  • s - رشته ای که با یک شخصیت خاتمه یافته است ‘\0’ ;
  • num تعداد کاراکترهایی است که در تماس گیرنده کپی می شوند. اولین کاراکترهای شماره از رشته کپی می شوند.

در زیر مثالی با پیاده سازی های مختلف عملکرد () تخصیص داده شده است.

مثال.

// اختصاص رشته ها ، تخصیص تابع () string s1 \u003d "site"؛ رشته s2؛ رشته s3؛ char * ps \u003d "سایت"؛ s3 \u003d s1؛ // s3 \u003d "سایت" s2.assign (s1)؛ // s2 \u003d "سایت" s2.assign (s1، 0، 4)؛ // s2 \u003d "بهترین" s2.assign (ps، 8)؛ // s2 \u003d "bestprog"
9. جمع کردن رشته ها. عملکرد () را اضافه کنید. مثال

تابع append () برای جمع کردن رشته ها استفاده می شود. همچنین می توانید از این عملیات برای اضافه کردن خط استفاده کنید ‘+’ ، به عنوان مثال:

رشته s1؛ رشته s2؛ s1 \u003d "abc"؛ s2 \u003d "def"؛ s1 \u003d s1 + s2؛ // s1 \u003d "abcdef"

با این وجود ، اگر لازم است بخشی از یک رشته را اضافه کنید ، عملکرد append () خوب است.

این تابع گزینه های اجرای زیر را دارد:

رشته و پیوست (consting & s ، شروع size_type)؛ رشته و پیوست (const char * s، size_type num)؛

در اولین اجرای ، تابع پیوندی را به یک شیء رشته دریافت می کند s که به تماس گیرنده اضافه می شود. در اجرای دوم ، تابع یک نشانگر به یک رشته const char * دریافت می کند ، که با کاراکتر '\\ 0' پایان می یابد.

مثال. تظاهرات عملکرد append ().

string s1 \u003d "abcdef"؛ s2 \u003d "1234567890"؛ ضمیمه (s2 ، \u200b\u200b3 ، 4)؛ // s1 \u003d "abcdef4567" char * ps \u003d "1234567890"؛ s1 \u003d "abcdef"؛ s1.append (ps، 3)؛ // s1 \u003d "abcdef123"

10. درج کاراکترها در یک خط. تابع () را وارد کنید. مثال

برای قرار دادن یک خط در یک موقعیت معین از خط دیگر ، باید از تابع insert () استفاده کنید که چندین گزینه پیاده سازی دارد.

نسخه اول این تابع به شما امکان می دهد که کل رشته ها را در موقعیت شروع خط تماس (هدف تماس) قرار دهید:

رشته و درج (شروع size_type ، رشته const & s)؛

نسخه دوم این تابع به شما امکان می دهد بخشی (پارامترهای پارامتر ، num) از رشته را در موقعیت آغازین رشته فراخوانی قرار دهید:

رشته و درج (شروع size_type ، رشته و & amp ؛ sst ، size_type insStart ، size_type num)؛

در توابع فوق:

  • s - رشته ای که باید در رشته فراخوانی درج شود.
  • start - موقعیت در خط تماس که از آن می توان رشته را وارد کرد.
  • insStart - موقعیت در رشته ای است که از آن می توانید وارد کنید.
  • num تعداد کاراکترهای رشته است که از موقعیت inStart درج شده اند.
string s1 \u003d "abcdef"؛ string s2 \u003d "1234567890"؛ s1.insert (3 ، s2)؛ // s1 \u003d "abc" + "1234567890" + "def" \u003d "abc1234567890def" s2.insert (2، s1، 1، 3)؛ // s2 \u003d "12bcd34567890"
11. تعویض کاراکترها در یک رشته. عملکرد () را جایگزین کنید. مثال

عملکرد () جایگزین () جایگزین کاراکترهای رشته تماس می شود. این تابع گزینه های اجرای زیر را دارد:

رشته و جایگزین (شروع size_type ، size_type num ، consting & s)؛ رشته و جایگزین (شروع size_type ، size_type num ، const رشته و ها ، size_type repStart ، size_type repNum)؛

در اولین اجرای ، رشته تماس با رشته s جایگزین می شود. می توان موقعیت (شروع) و تعداد کاراکترها (num) را در خط تماس تعیین کرد که باید با رشته s جایگزین شوند.

نسخه دوم عملکرد جایگزین () با نسخه اول متفاوت است زیرا به شما امکان می دهد رشته تماس را فقط با بخشی از رشته جایگزین کنید. در این حالت ، دو پارامتر اضافی ارائه می شود: موقعیت replStart و تعداد کاراکترهای موجود در رشته s که بستر را تشکیل می دهد که جایگزین رشته فراخوانی می شود.

مثال. تظاهرات عملکرد جایگزین ().

string s1 \u003d "abcdef"؛ string s2 \u003d "1234567890"؛ s2.replace (2 ، 4 ، s1)؛ // s2 \u003d "12abcdef7890" s2 \u003d "1234567890"؛ s2.replace (3 ، 2 ، s1)؛ // s2 \u003d "123abcdef67890" s2 \u003d "1234567890"؛ s2.replace (5 ، 1 ، s1)؛ // s2 \u003d "12345abcdef7890" // کاراکترها را جایگزین کنید ، عملکرد () را جایگزین کنید string s1 \u003d "abcdef"؛ string s2 \u003d "1234567890"؛ s2.replace (2 ، 4 ، s1)؛ // s2 \u003d "12abcdef7890" s2 \u003d "1234567890"؛ s2.replace (3 ، 2 ، s1)؛ // s2 \u003d "123abcdef67890" s2 \u003d "1234567890"؛ s2.replace (5 ، 1 ، s1)؛ // s2 \u003d "12345abcdef7890" s2 \u003d "1234567890"؛ s2.replace (5 ، 1 ، s1 ، 2 ، 3)؛ // s2 \u003d "12345cde7890" s2 \u003d "1234567890"؛ s2.replace (4 ، 2 ، s1 ، 0 ، 4)؛ // s2 \u003d "1234abcd7890"

12. حذف شماره مشخص شده از کاراکترها از رشته. عملکرد () را پاک کنید. مثال

برای حذف کاراکترها از رشته تماس ، از عملکرد پاک کردن () استفاده کنید:

رشته و پاک کردن (index_type index \u003d 0، size_type num \u003d npos)؛

  • index - index (موقعیت) ، از آنجا که می خواهید شخصیت های موجود در خط تماس را حذف کنید.
  • num تعداد کاراکترهایی است که باید حذف شود.

مثال.

String s \u003d "01234567890"؛ s.erase (3 ، 5)؛ // s \u003d "012890" s \u003d "01234567890"؛ s.erase ()؛ // s \u003d ""

13. جستجوی شخصیت در یک رشته. توابع () و rfind () را پیدا کنید. نمونه هایی از

در کلاس رشته ، جستجوی رشته در یک بستر می تواند از دو طریق انجام شود ، که در جهت جستجو متفاوت است:

  • با نگاه کردن به رشته از ابتدا تا انتها با استفاده از تابع find ()؛
  • با نگاه کردن رشته از انتهای شروع با rfind ().

نمونه اولیه تابع find () عبارت است از:

size_type find (consting & s، size_type start \u003d 0) const؛

  • s بستر موردنظر برای جستجوی رشته ای است که تابع داده شده را فراخوانی می کند. این تابع برای اولین بار از رشته ها جستجو می کند. اگر substring در رشته ای پیدا شود که به آن تابع داده شده گفته می شود ، موقعیت اولین بار برمی گردد. در غیر این صورت -1 بازگردانده می شود.

نمونه اولیه عملکرد rfind () عبارت است از:

size_type rfind (consting & s، size_type start \u003d npos) const؛

  • s بستر مورد نیاز برای جستجوی رشته فراخوان است. جستجوی بستر در یک رشته از انتها تا آغاز انجام می شود. اگر substring در رشته فراخوان یافت شود ، آنگاه عملکرد اولین موقعیت اول را برمی گرداند. در غیر این صورت ، تابع -1 برمی گردد.
  • npos - موقعیت آخرین شخصیت خط تماس؛
  • start - موقعیتی که جستجو از آن انجام می شود.

مثال 1 قطعه ای از کد که نتیجه عملکرد find () را نشان می دهد

// نوع رشته ، تابع find () را پیدا کنید string s1 \u003d "01234567890"؛ string s2 \u003d "345"؛ string s3 \u003d "abcd"؛ int pos؛ pos \u003d s1.find (s2)؛ // pos \u003d 3 pos \u003d s1.find (s2، 1)؛ // pos \u003d 3 pos \u003d s1.find ("jklmn" ، 0)؛ // pos \u003d -1 pos \u003d s1.find (s3)؛ // pos \u003d -1 pos \u003d s2.find (s1)؛ // pos \u003d -1

مثال 2 تظاهرات عملکرد rfind ().

// نوع رشته ، توابع find () و rfind () string s1 \u003d "01234567890"؛ string s2 \u003d "345"؛ string s3 \u003d "abcd"؛ string s4 \u003d "abcd --- abcd"؛ int pos؛ pos \u003d s1.rfind (s2)؛ // pos \u003d 3 pos \u003d s1.rfind (s2، 12)؛ // pos \u003d 3 pos \u003d s1.rfind (s2، 3)؛ // pos \u003d 3 pos \u003d s1.rfind (s2، 2)؛ // pos \u003d -1 pos \u003d s2.rfind (s1)؛ // pos \u003d -1 pos \u003d s1.rfind (s3، 0)؛ // pos \u003d -1 // تفاوت بین توابع find () و rfind () pos \u003d s4.rfind (s3)؛ // pos \u003d 7 pos \u003d s4.find (s3)؛ // pos \u003d 0
14. مقایسه قسمتهای رشته ها. عملکرد () را مقایسه کنید. مثال

از آنجا که نوع رشته یک کلاس است ، می توانید از این عملیات برای مقایسه دو رشته با یکدیگر استفاده کنید ‘= =’ ... اگر دو رشته یکسان باشند ، مقایسه آن صادق است. در غیر این صورت ، مقایسه نادرست خواهد بود.

اما اگر شما نیاز به مقایسه بخشی از یک رشته با رشته دیگر دارید ، عملکرد () () برای این کار فراهم شده است.

نمونه اولیه تابع مقایسه ():

int مقایسه (شروع size_type ، size_type num ، const رشته و بازدید کنندگان) const؛
  • s - رشته ای برای مقایسه با رشته فراخوان؛
  • start - Position (index) در رشته s ، از آن جهت مشاهده کاراکترهای رشته برای مقایسه
  • num تعداد کاراکترهای رشته است که در برابر رشته فراخوانی قرار دارد.

عملکرد به شرح زیر است. اگر رشته فراخوان کمتر از رشته باشد ، تابع -1 (مقدار منفی) برمی گردد. اگر رشته تماس بیشتر از رشته است ، عملکرد 1 (مقدار مثبت) برمی گردد. اگر دو رشته مساوی باشند ، عملکرد 0 برمی گردد.

مثال... تظاهرات تابع مقایسه ():

// نوع رشته ، تابع مقایسه () string s1 \u003d "012345"؛ string s2 \u003d "0123456789"؛ int res؛ res \u003d s1.compare (s2)؛ // res \u003d -1 res \u003d s1.compare ("33333")؛ // res \u003d -1 res \u003d s1.compare ("012345")؛ // res \u003d 0 res \u003d s1.compare ("345")؛ // res \u003d -1 res \u003d s1.compare (0، 5، s2)؛ // res \u003d -1 res \u003d s2.compare (0، 5، s1)؛ // res \u003d -1 res \u003d s1.compare (0، 5، "012345")؛ // res \u003d -1 res \u003d s2.compare (s1)؛ // res \u003d 1 res \u003d s2.compare ("456")؛ // res \u003d -1 res \u003d s2.compare ("000000")؛ // res \u003d 1
15. دریافت رشته با کاراکتر خط آخر '\\ 0' (کاراکتر *). عملکرد C_str (). مثال

برای بدست آوردن رشته ای که با یک کاراکتر تمام شود ‘\0’ تابع c_str () استفاده می شود.

نمونه اولیه عملکرد:

const char * c_str () const؛

عملکرد با اصلاح کننده const اعلام می شود. این بدان معنی است که عملکرد نمی تواند تماس گیرنده (رشته) را تغییر دهد.

مثال 1... تبدیل رشته به const char *.

string s \u003d "abcdef"؛ const char * ps؛ ps \u003d s.c_str ()؛ // ps \u003d "abcdef"

مثال 2

موارد زیر تبدیل رشته از رشته به System :: نوع رشته را نشان می دهد تا آن را در یک کنترل برچسب برای برنامه های کاربردی Windows Forms Application نمایش دهد.

// نوع رشته ، عملکرد c_str () string s \u003d "abcdef"؛ ss string؛ ss \u003d gcnew String (s.c_str ())؛ // تبدیل label1-\u003e متن \u003d s؛ // نمایش روی فرم

حبرا ، سلام!

چندی پیش ، یک واقعه نسبتاً جالب را تجربه کردم که در آن یکی از معلمان یک کالج علوم کامپیوتر درگیر شد.

گفتگو در مورد برنامه نویسی لینوکس به آهستگی به جایی منتقل شد که این شخص اظهار داشت که پیچیدگی برنامه نویسی سیستم ها در واقع بسیار اغراق آمیز است. اینکه زبان C به همان اندازه یک مسابقه ساده باشد ، در واقع مانند هسته لینوکس (به تعبیر او).

من یک لپ تاپ لینوکس با من با مجموعه آقایان ابزارهای توسعه C (gcc، vim، make، valgrind، gdb) همراه خود داشتم. من به یاد نمی آورم آن موقع چه هدفی را برای خودمان تعیین کردیم ، اما بعد از چند دقیقه حریف من پشت این لپ تاپ قرار گرفت ، کاملاً آماده برای حل مشکل.

و به معنای واقعی کلمه در همان خطوط اول ، هنگام تخصیص حافظه برای ... خط خطایی جدی مرتکب شد.

Char * str \u003d (char *) malloc (sizeof (char) * strlen (بافر))؛
buffer یک متغیر پشته است که در آن داده های صفحه کلید نوشته شده است.

من فکر می کنم قطعاً افرادی خواهند بود که سؤال خواهند کرد: "آیا ممکن است در اینجا چیزی اشتباه باشد؟"
باور کنید ، می تواند.

و دقیقاً چه چیزی - برش را بخوانید.

یک نظریه کوچک - نوعی FaceBez.

اگر می دانید ، به سربرگ بعدی بروید.

رشته در C مجموعه ای از کاراکترهاست که به صورت دوستانه همیشه باید با "0 0" - کاراکتر پایان خط پایان یابد. رشته های روی پشته (استاتیک) به شرح زیر اعلام می شوند:

خیابان کار [n] \u003d (0)؛
n اندازه آرایه کاراکتر است ، همان طول رشته.

تکلیف (0) - "nulling" رشته (اختیاری است ، می توانید بدون آن اعلام کنید). نتیجه همان کارکردهای memet (str، 0، sizeof (str)) و bzoo (str، sizeof (str)) است. برای جلوگیری از زباله در متغیرهای ناشناخته استفاده می شود.

همچنین در پشته ، می توانید بلافاصله خط را آغاز کنید:

Char buf \u003d "متن بافر پیش فرض \\ n"؛
علاوه بر این ، یک رشته را می توان یک نشانگر اعلام کرد و حافظه را بر روی پشته برای آن اختصاص داد:

Char * str \u003d malloc (اندازه)؛
اندازه - تعداد بایتهایی که ما برای رشته اختصاص می دهیم. این رشته ها پویا نامیده می شوند (با توجه به اینکه اندازه مورد نیاز به صورت پویا محاسبه می شود + اندازه حافظه اختصاص داده شده را می توان در هر زمان با استفاده از عملکرد realloc () افزایش داد).

در مورد متغیر stack ، از نماد n برای تعیین اندازه آرایه استفاده کردم ، در مورد متغیر روی پشته ، از اندازه نماد استفاده کردم. و این کاملاً بیانگر ذات واقعی تفاوت بین بیانیه روی پشته و اظهارنامه با تخصیص حافظه در پشته است ، زیرا معمولاً n هنگام صحبت کردن در مورد تعداد عناصر ، از n استفاده می شود. و اندازه داستانی کاملاً متفاوت است ...

والگریند به ما کمک می کند

در مقاله قبلی خود نیز به آن اشاره کردم. Valgrind (، دو مورد کمی چگونگی چگونگی است) یک برنامه بسیار مفید است که به برنامه نویس کمک می کند تا نشت حافظه و خطاهای متن را تشخیص دهد - فقط نوع کارهایی است که بیشتر در هنگام کار با رشته ها اتفاق می افتد.

بیایید به یک لیست کوچک ، که چیزی مشابه برنامه ای که من اشاره کردم ، پیاده سازی کند ، و آن را از طریق valgrind اجرا کنیم:

#عبارتند از #عبارتند از #عبارتند از #define HELLO_STRING "سلام ، هابر! ، خیابان) ؛ رایگان (خیابان) ؛)
و ، در واقع ، نتیجه برنامه:

$ gcc main.c $ ./a.out -\u003e سلام ، هابر!
هیچ چیز غیر معمول تا کنون. حالا بیایید این برنامه را با valgrind اجرا کنیم!

$ valgrind --tool \u003d memcheck ./a.out \u003d\u003d 3892 \u003d\u003d Memcheck ، یک آشکارساز خطای حافظه \u003d\u003d 3892 \u003d\u003d کپی رایت (C) 2002-2015 ، و GNU GPL "d ، توسط جولیان سیوارد و همکاران \u003d\u003d 3892 \u003d\u003d با استفاده از Valgrind-3.12.0 و LibVEX؛ دوباره با -h برای اطلاعات مربوط به حق نسخه برداری \u003d\u003d 3892 \u003d\u003d دستور: ./a.out \u003d\u003d 3892 \u003d\u003d \u003d\u003d 3892 \u003d\u003d نوشتن نامعتبر از اندازه 2 \u003d\u003d 3892 \u003d \u003d در 0x4005B4: main (in /home/indever/prg/C/public/a.out) \u003d\u003d 3892 \u003d\u003d آدرس 0x520004c 12 بایت است که داخل یک بلوک به اندازه 13 اختصاص داده شده است "d \u003d\u003d 3892 \u003d\u003d در 0x4C2DB9D: malloc (vg_replace_malloc.c: 299) \u003d\u003d 3892 \u003d\u003d توسط 0x400597: اصلی (در /home/indever/prg/C/public/a.out) \u003d\u003d 3892 \u003d\u003d \u003d\u003d 3892 \u003d\u003d خواندن نامعتبر اندازه 1 \u003d\u003d 3892 \u003d\u003d در 0x4C30BC4: strlen (vg_replace_strmem.c: 454) \u003d\u003d 3892 \u003d\u003d توسط 0x4E89AD0: vfprintf (در /usr/lib64/libc-2.24.so) \u003d\u003d 3892 \u003d\u003d توسط 0x4E90718: printf (in / usr / lib64 / libc-2.24.so) \u003d\u003d 3892 \u003d\u003d توسط 0x4005CF: اصلی (در /home/indever/prg/C/public/a.out) \u003d\u003d 3892 \u003d\u003d آدرس 0x520004d 0 بایت بعد از بلوک اندازه 13 است اختصاص "d \u003d\u003d 3892 \u003d\u003d در 0x4C2DB9D: malloc (vg_replace_malloc.c: 299) \u003d\u003d 3892 \u003d\u003d توسط 0x400597: اصلی (در / خانه / indever / prg / C / عمومی / a.out) \u003d\u003d 3892 \u003d\u003d -\u003e سلام سلام! \u003d\u003d 3892 \u003d\u003d \u003d\u003d 3892 \u003d\u003d خلاصه HEAP: \u003d\u003d 3892 \u003d\u003d در هنگام استفاده: 0 بایت در 0 بلوک \u003d\u003d 3892 \u003d\u003d کل استفاده از پشته: 2 تخصیص ، 2 آزاد ، 1.037 بایت اختصاص داده شده \u003d\u003d 3892 \u003d \u003d \u003d\u003d 3892 \u003d\u003d همه بلوک های پشته آزاد شد - هیچ گونه نشتی امکان پذیر نیست \u003d\u003d 3892 \u003d\u003d \u003d\u003d 3892 \u003d\u003d برای شمارش خطاهای شناسایی و سرکوب شده ، با: -v \u003d\u003d 3892 \u003d\u003d ERROR خلاصه: 3 خطا از 2 زمینه (سرکوب شده: 0 از 0)
\u003d\u003d 3892 \u003d\u003d همه بلوک های پشته آزاد شد - هیچ گونه نشتی امکان پذیر نیست - هیچ نشتی وجود ندارد ، و خوشحال می شود. اما ارزش آن است که چشمان خود را کمی پایین بیاورید (اگرچه ، من می خواهم توجه داشته باشم ، این فقط یک خلاصه است ، اطلاعات اولیه کمی در جای دیگر است):

\u003d\u003d 3892 \u003d\u003d خلاصه خطا: 3 خطا از 2 زمینه (سرکوب شده: 0 از 0)
3 اشتباه در 2 متن. در چنین برنامه ساده چگونه!؟

خیلی ساده است. کل "ترفند" این است که تابع strlen شخصیت انتهای خط را در نظر نمی گیرد - "\\ 0". حتی اگر صریحاً آن را در خط ورودی مشخص کنید (# تعریف HELLO_STRING "سلام ، هابر! \\ n \\ 0") ، نادیده گرفته می شود.

کمی بالاتر از نتیجه اجرای برنامه ، خطوط -\u003e سلام ، هابر! گزارشی مفصل در مورد آنچه والد گرانقدر ما دوست ندارد و در کجا وجود دارد ، وجود دارد. پیشنهاد می کنم خودتان به این خطوط نگاه کنید و نتیجه گیری کنید.

در واقع ، نسخه صحیح برنامه مانند این است:

#عبارتند از #عبارتند از #عبارتند از #define HELLO_STRING "سلام ، هابر! \\ n" اصلی را باطل () (char * str \u003d malloc (sizeof (char) *) (strlen (HELLO_STRING) + 1))؛ بیایید از طریق valgrind فرار کنیم:
{!LANG-4b2ee5de0e69e468c3855f7e241415cc!}

$ valgrind --tool \u003d memcheck ./a.out -\u003e سلام ، هابر! \u003d\u003d 3435 \u003d\u003d \u003d\u003d 3435 \u003d\u003d خلاصه HEAP: \u003d\u003d 3435 \u003d\u003d در هنگام استفاده: 0 بایت در 0 بلوک \u003d\u003d 3435 \u003d\u003d کل استفاده از پشته: 2 تخصیص ، 2 آزاد ، 1،038 بایت اختصاص داده شده \u003d\u003d 3435 \u003d \u003d \u003d\u003d 3435 \u003d\u003d همه بلوک های پشته آزاد شد - هیچ گونه نشتی امکان پذیر نیست \u003d\u003d 3435 \u003d\u003d \u003d\u003d 3435 \u003d\u003d برای شمارش خطاهای شناسایی شده و سرکوب شده ، با: -v \u003d\u003d 3435 \u003d\u003d ERROR خلاصه: 0 خطا از 0 زمینه (سرکوب شده: 0 از 0)
خوب. خطایی وجود ندارد ، 1 بایت حافظه اختصاص داده شده به حل مشکل کمک می کند.

جالب اینجاست که در بیشتر موارد ، هر دو برنامه اول و دوم به طور یکسان عمل می کنند ، اما اگر حافظه اختصاص داده شده برای خط ، که در آن نویسه نهایی قرار نمی گیرد ، خالی نباشد ، تابع printf () هنگام خروج چنین خطی ، تمام زباله ها را نیز نمایش می دهد. از این خط - همه چیز نمایش داده می شود تا زمانی که شخصیت پایان خط در مسیر printf () ظاهر شود.

با این حال ، می دانید ، (strlen (str) + 1) چنین راه حلی است. ما با 2 مشکل روبرو هستیم:

  1. اما اگر بخواهیم حافظه را برای رشته ای که با استفاده از مثال (s) printf (..) ایجاد شده است ، اختصاص دهیم؟ ما از استدلال پشتیبانی نمی کنیم.
  2. ظاهر. خط اعلام متغیر بسیار وحشتناک به نظر می رسد. برخی از بچه ها همچنین موفق به پیچ خوردن (char *) به malloc می شوند ، انگار که زیر پلاوس ها می نویسند. در برنامه ای که به طور مرتب نیاز به پردازش رشته ها دارید ، پیدا کردن یک راه حل زیبا تر منطقی است.
بیایید راه حلی ارائه دهیم که هم ما و هم جسارت را برآورده کند.

snprintf ()

int snprintf (کاراکتر * خیابان ، اندازه size_t ، قالب const char * ، ...)؛ - function - extint sprintf ، که یک رشته را تشکیل می دهد و آن را به نشانگر منتقل شده به عنوان اولین آرگومان می نویسد. با sprintf تفاوت دارد () در این خیابان تعداد بیشتری بایت از اندازه نخواهد بود.

این تابع یک ویژگی جالب دارد - به هر حال اندازه رشته تولید شده را باز می گرداند (به استثناء شخصیت پایان خط). اگر رشته خالی باشد ، 0 باز می گردد.

یکی از مشکلی که من با استفاده از strlen توضیح دادم مربوط به توابع sprintf () و snprintf () است. فرض کنید لازم است چیزی بنویسیم تا به خیابان برسیم. رشته نهایی شامل مقادیر متغیرهای دیگر است. ورود ما باید چیزی شبیه به این باشد:

Char * str \u003d / * حافظه را در اینجا اختصاص دهید * /؛ sprintf (خیابان ، "سلام ،٪ s \\ n" ، "حبر!")؛
این سؤال پیش می آید: چگونه می توان میزان حافظه را برای رشته رشته مشخص کرد؟

Char * str \u003d malloc (sizeof (char) * (strlen (خیابان ، "سلام ،٪ s \\ n" ، "Habr!") + 1))؛ - نمیخواد بره نمونه اولیه تابع strlen () به شرح زیر است:

#عبارتند از size_t strlen (const char * s)؛
const char * نشان نمی دهد که رشته منتقل شده به s می تواند یک رشته فرمت با تعداد متغیر آرگومان باشد.

اینجاست که ویژگی مفید تابع snprintf () که در بالا به آن اشاره کردم ، به ما کمک می کند. بیایید نگاهی به کد برنامه زیر بیندازیم:

#عبارتند از #عبارتند از #عبارتند از void main () (/ * از آنجا که snprintf () شخصیت انتهای خط را در نظر نمی گیرد ، اندازه آن را به نتیجه اضافه کنید * / size_t need_mem \u003d snprintf (NULL ، 0 ، "سلام ،٪ s! \\ n" ، "حبر") + sizeof ("\\ 0")؛ char * str \u003d malloc (need_mem)؛ snprintf (str، need_mem، "سلام،٪ s! \\ n"، "Habr")؛ printf ("-\u003e \\ t٪ s"، str)؛ رایگان (خیابان)؛)
برنامه را در valgrind اجرا کنید:

$ valgrind --tool \u003d memcheck ./a.out -\u003e سلام ، هابر! \u003d\u003d 4132 \u003d\u003d \u003d\u003d 4132 \u003d\u003d خلاصه HEAP: \u003d\u003d 4132 \u003d\u003d در هنگام استفاده: 0 بایت در 0 بلوک \u003d\u003d 4132 \u003d\u003d کل استفاده از پشته: 2 تخصیص ، 2 آزاد ، 1،041 بایت اختصاص داده شده \u003d\u003d 4132 \u003d \u003d \u003d\u003d 4132 \u003d\u003d همه بلوک های پشته آزاد شد - هیچ گونه نشتی امکان پذیر نیست \u003d\u003d 4132 \u003d\u003d \u003d\u003d 4132 \u003d\u003d برای شمارش خطاهای شناسایی شده و سرکوب شده ، با استفاده از: -v \u003d\u003d 4132 \u003d\u003d ERROR خلاصه: 0 خطا از 0 زمینه (سرکوب شده: 0 از 0) $
خوب. ما از استدلال پشتیبانی می کنیم. با توجه به اینکه صفر را به عنوان دومین آرگومان به عملکرد snprintf () منتقل می کنیم ، نوشتن توسط یک اشاره گر تهی هرگز به Seagfault منجر نمی شود. با این وجود ، با وجود این ، عملکرد هنوز اندازه مورد نیاز رشته را برمی گرداند.

اما از طرف دیگر ، ما مجبور شدیم یک متغیر اضافی ، و ساخت را اضافه کنیم

size_t need_mem \u003d snprintf (NULL ، 0 ، "سلام ،٪ s! \\ N" ، "Habr") + sizeof ("\\ 0")؛
حتی بدتر از strlen () به نظر می رسد.

به طور کلی ، می توان + sizeof ("\\ 0") را با مشخص کردن صریح "\\ 0" در انتهای رشته فرمت حذف کرد (size_t need_mem \u003d snprintf (NULL ، 0 ، "سلام ،٪ s! \\ n \0 "،" Habr ")؛) ، اما این به هیچ وجه همیشه ممکن نیست (بسته به مکانیسم پردازش خط ، ما می توانیم یک بایت اضافی نیز اختصاص دهیم).

باید کاری کرد. کمی فکر کردم و تصمیم گرفتم که اکنون ساعت آن فرا رسیده است که به خرد باستان متوسل شود. بیایید یک کارکرد کلان را توصیف کنیم که snprintf () را با یک اشاره گر تهی به عنوان اولین استدلال ، و صفر به عنوان دوم توصیف می کند. و بیایید پایان خط را فراموش نکنیم!

#define strsize (args ...) snprintf (NULL ، 0 ، استدلال) + sizeof ("\\ 0")
بله ، ممکن است برای کسی خبر باشد ، اما ماکروها در C تعداد زیادی از آرگومان ها را پشتیبانی می کنند ، و بیضی به پیش پردازنده می گوید که آرگومان مشخص شده از عملکرد کلان (در مورد ما ، استدلال می کند) با چندین آرگومان واقعی مطابقت دارد.

بیایید راه حل خود را در عمل بررسی کنیم:

#عبارتند از #عبارتند از #عبارتند از #define strsize (args ...) snprintf (NULL ، 0 ، args) + sizeof ("\\ 0") void main () (char * str \u003d malloc (strsize ("سلام ،٪ s \\ n" ، "Habr! ")) ؛ sprintf (خیابان ،" سلام ،٪ s \\ n "،" Habr! ")؛ printf (" -\u003e \\ t٪ s "، خیابان) ؛ رایگان (str)؛)
اجرای با valgrund:

$ valgrind --tool \u003d memcheck ./a.out -\u003e سلام ، هابر! \u003d\u003d 6432 \u003d\u003d \u003d\u003d 6432 \u003d\u003d خلاصه HEAP: \u003d\u003d 6432 \u003d\u003d در هنگام استفاده: 0 بایت در 0 بلوک \u003d\u003d 6432 \u003d\u003d کل استفاده از پشته: 2 تخصیص ، 2 آزاد ، 1،041 بایت اختصاص داده شده \u003d\u003d 6432 \u003d \u003d \u003d\u003d 6432 \u003d\u003d همه بلوک های پشته آزاد شد - هیچ گونه نشتی امکان پذیر نیست \u003d\u003d 6432 \u003d\u003d \u003d\u003d 6432 \u003d\u003d برای شمارش خطاهای شناسایی شده و سرکوب شده ، با: -v \u003d\u003d 6432 \u003d\u003d ERROR خلاصه: 0 خطا از 0 زمینه (سرکوب شده: 0 از 0)
بله ، هیچ اشتباهی وجود ندارد. همه چیز درست است. و والگر خوشحال است و برنامه نویس بالاخره می تواند به خواب برود.

اما بالاخره یک چیز دیگر را خواهم گفت. در صورت نیاز به اختصاص حافظه برای هر رشته (حتی با استدلال) از قبل وجود دارد به طور کامل کار راه حل کلید.

در مورد عملکرد asprintf است:

# تعریف_GNU_SOURCE / * به ویژگی_تست_ماکروس (7) * مراجعه کنید int asprintf (char ** strp، const char * fmt، ...)؛
به عنوان اولین استدلال ، یک اشاره گر را به یک رشته (** strp) می برد و حافظه را در اشاره گر مرجع اختصاص می دهد.

برنامه ما که با استفاده از asprintf () نوشته شده است به شرح زیر است:

#عبارتند از #عبارتند از #عبارتند از void main () (char * str؛ asprintf (& str، "Hello،٪ s! \\ n"، "Habr")؛ printf ("-\u003e \\ t٪ s"، str)؛ free (str)؛)
و ، در واقع ، در valgrind:

$ valgrind --tool \u003d memcheck ./a.out -\u003e سلام ، هابر! \u003d\u003d 6674 \u003d\u003d \u003d\u003d 6674 \u003d\u003d خلاصه HEAP: \u003d\u003d 6674 \u003d\u003d در هنگام استفاده: 0 بایت در 0 بلوک \u003d\u003d 6674 \u003d\u003d کل استفاده از پشته: 3 تخصیص ، 3 بار آزاد ، 1،138 بایت اختصاص داده شده \u003d\u003d 6674 \u003d \u003d \u003d\u003d 6674 \u003d\u003d همه بلوک های پشته آزاد شد - هیچ گونه نشتی امکان پذیر نیست \u003d\u003d 6674 \u003d\u003d \u003d\u003d 6674 \u003d\u003d برای شمارش خطاهای تشخیص داده شده و سرکوب شده ، با: -v \u003d\u003d 6674 \u003d\u003d ERROR خلاصه: 0 خطا از 0 زمینه (سرکوب شده: 0 از 0)
همه چیز خوب است ، اما ، همانطور که می بینید ، در کل حافظه بیشتری اختصاص داده شده است ، و اکنون سه تخصیص وجود دارد ، نه دو. در سیستم های تعبیه شده ضعیف ، این عملکرد نامطلوب است.
علاوه بر این ، اگر man asprintf را در کنسول بنویسیم ، خواهیم دید:

سازگار با این توابع ، برنامه های افزودنی GNU است ، نه در C یا POSIX. آنها همچنین در زیر * BSD در دسترس هستند. اجرای FreeBSD خطای خط را روی NULL قرار می دهد.

از این روشن است که این ویژگی فقط در منبع GNU موجود است.

نتیجه

در خاتمه ، می خواهم بگویم که کار کردن با رشته ها در C یک موضوع بسیار پیچیده است که دارای چندین تفاوت است. برای مثال ، برای نوشتن کد "ایمن" برای تخصیص حافظه پویا ، هنوز هم توصیه می شود به جای malloc () از تابع calloc () استفاده کنید - calloc حافظه اختصاص داده شده را با صفر می بندد. خوب ، یا بعد از تخصیص حافظه ، از عملکرد ممتد () استفاده کنید. در غیر این صورت ، زباله هایی که در اصل در منطقه حافظه اختصاص داده شده قرار دارند ، می توانند در حین اشکال زدایی و در بعضی مواقع هنگام کار با یک رشته ، سؤالاتی ایجاد کنند.

بیش از نیمی از برنامه نویسان همکار من (که اکثر آنها مبتدی هستند) که به درخواست من مشکل تخصیص حافظه برای رشته ها را حل کردند ، این کار را به گونه ای انجام دادند که در نهایت منجر به خطاهای متن شد. در یک مورد - حتی به یک نشت حافظه (خوب ، یک شخص فراموش کرده است که (رایگان) را آزاد کند (کسی که اتفاق نمی افتد). در حقیقت ، این باعث شد تا من این خلاقیت را ایجاد کنید ، که شما فقط خوانده اید.

امیدوارم کسی این مقاله را مفید پیدا کند. چرا این همه چانه زدم - هیچ زبانی ساده نیست. همه جا ظرافت های خاص خود را دارد. و هرچه ظرافت بیشتری از زبانی که می دانید ، کد شما بهتر خواهد بود.

من معتقدم که بعد از خواندن این مقاله ، کد شما کمی بهتر خواهد شد :)
موفق باشید هابر!

کتابخانه عملکرد C و C ++ شامل مجموعه ای غنی از توابع کار با رشته و کاراکتر است. توابع رشته بر روی آرایه های کاراکتر خاتمه یافته کار می کنند. در زبان C برای استفاده از توابع رشته ، باید یک فایل هدر در ابتدای ماژول برنامه درج کنید ، و برای پرونده هدر نمادین ... C ++ از هدرها برای کار با توابع رشته و کاراکترها استفاده می کند و به ترتیب. در این فصل از نامهای C-header برای سادگی استفاده شده است.

از آنجا که زبانهای C و C ++ به طور خودکار نقض مرزهای خود را هنگام انجام عملیات با آرایه ها کنترل نمی کنند ، کل مسئولیت سرریز آرایه ها بر دوش برنامه نویس قرار می گیرد. غفلت از این ظرافت ها می تواند باعث خرابی برنامه شود.

در C و C ++ ، کاراکترهای قابل چاپ آنهایی هستند که در ترمینال نمایش داده می شوند. در محیط های ASCII ، آنها بین یک فضا (0x20) و یک تایل (OxFE) قرار دارند. شخصیت های کنترل مقادیر بین صفر و Ox1F دارند. این همچنین شامل نماد DEL (Ox7F) است.

از نظر تاریخی ، آرگومانهای مربوط به توابع نمادین مقادیر عدد صحیحی هستند که از حداقل حداقل بایت مهم استفاده شده است. عملکردهای سمبولیک به طور خودکار استدلالهای خود را به کاراکتر بدون علامت تبدیل می کنند. البته ، شما می توانید این توابع را با آرگومان های نمادین فراخوانی کنید ، زیرا در هنگام فراخوانی تابع ، نمادها به طور خودکار به رتبه اعداد صحیح بالا می روند.

در عنوان نوع size_t تعریف شده است که نتیجه عملگر sizeof است و نوعی عدد صحیح علامتدار است.

C99 صلاحیت محدود کننده را به پارامترهای مختلفی از توابع که در ابتدا در C89 تعریف شده بودند افزوده است. هر یک از این عملکردها با نمونه اولیه آن مورد استفاده در محیط C89 (و همچنین در محیط C ++) مورد بحث قرار خواهد گرفت و پارامترهایی با ویژگی محدود کننده در توضیحات این تابع ذکر خواهند شد.

لیست ویژگی ها

تعلق را بررسی کنید

isalnum - بررسی کنید آیا یک شخصیت الفبایی است یا خیر
isalpha - بررسی کنید که آیا یک شخصیت به حروف تعلق دارد یا خیر
isblank - یک شخصیت خالی را بررسی کنید
iscntrl - بررسی کنید که آیا یک نماد متعلق به کنترل است
isdigit - بررسی کنید که آیا یک شخصیت دیجیتالی است یا خیر
isgraph - بررسی کنید که آیا یک کاراکتر قابل چاپ است اما یک فضا ندارد
islower - بررسی کنید که آیا یک شخصیت کوچک است یا خیر
isprint - بررسی کنید که آیا یک شخصیت قابل چاپ است یا خیر
ispunct - بررسی کنید که آیا یک شخصیت به علائم نگارشی تعلق دارد یا خیر
isspace - بررسی کنید که آیا شخصیت یک فضای سفید است یا خیر
isupper - بررسی کنید که آیا یک شخصیت بزرگ است یا خیر
isxdigit - بررسی کنید که آیا یک شخصیت شش ضلعی است یا خیر

کار با آرایه های شخصیت

memchr - حلقه را از طریق آرایه برای پیدا کردن اولین وقوع یک شخصیت
memcmp - تعداد مشخصی از شخصیت ها را در دو آرایه مقایسه می کند
memcpy - کپی کاراکترها از یک آرایه به دیگری
memmove - با در نظر گرفتن آرایه های همپوشان ، کاراکترها را از یک آرایه به دیگری کپی می کند
ممتاز - تعداد مشخصی از کاراکترها را در یک آرایه با ذکر شده پر می کند

دستکاری رشته

strcat - یک کپی از یک رشته را به داده اضافه کنید
strchr - یک اشاره گر را به اولین وقوع کمترین میزان اهمیت بایت پارامتر داده شده برمی گرداند
strcmp - از نظر واژگانی دو رشته را مقایسه می کند
strcoll - یک رشته را با توجه به setlocale رشته دیگر را مقایسه می کند
strcpy - کپی محتویات یک رشته به رشته دیگر
strcspn - رشته ای را بدون کاراکتر مشخص برمی گرداند
strerror - یک اشاره گر را به رشته حاوی پیام خطای سیستم برمی گرداند
strlen - طول یک رشته بدون خاتمه را برمی گرداند

زنگ

کسانی هستند که این خبر را قبل از شما می خوانند.
برای دریافت آخرین مقالات مشترک شوید.
پست الکترونیک
نام
نام خانوادگی
چگونه می خواهید The Bell را بخوانید
بدون اسپم