ویکیکتاب
fawikibooks
https://fa.wikibooks.org/wiki/%D8%B5%D9%81%D8%AD%D9%87%D9%94_%D8%A7%D8%B5%D9%84%DB%8C
MediaWiki 1.47.0-wmf.12
first-letter
مدیا
ویژه
بحث
کاربر
بحث کاربر
ویکیکتاب
بحث ویکیکتاب
پرونده
بحث پرونده
مدیاویکی
بحث مدیاویکی
الگو
بحث الگو
راهنما
بحث راهنما
رده
بحث رده
کتابآشپزی
بحث کتابآشپزی
ویکیکودک
بحث ویکیکودک
موضوع
بحث موضوع
TimedText
TimedText talk
پودمان
بحث پودمان
Event
Event talk
زبان برنامه نویسی سی/stdio
0
33083
134490
134447
2026-07-25T04:58:42Z
HadiLovelorn
23337
134490
wikitext
text/x-wiki
{{سرص|زبان برنامه نویسی سی/مقدمهای بر فایلهای سرآیند|زبان برنامه نویسی سی/stdlib}}
با این فایل سرآیند تا حدودی آشنایی دارید و در طول کتاب بارها به آن اشاره شده است . stdio.h یک فایل سرآیند ( Header ) استاندارد زبان سی می باشد که مخفف Standard Input/Output یا Standard Input & Output است به معنی ورودیها و خروجیهای استاندارد . ما از تابع printf و scanf به وفور در کتاب استفاده نمودهایم که در فایل سرآیند stdio تعریف شدهاند اما پیش از نوشتن توابع بهتر است با تعیینکنندههای فرمت در این توابع استاندارد آشنا شوید.
حتماً به یاد دارید که در کتاب وقتی می نوشتیم ;printf("This is a %s", str) و اگر str یک رشته می بود که داخل آن وارد می کردیم string در خروجی خطدستوری با جمله This is a string مواجه می شدیم. تعیین کنندههای فرمت ، متغیرهایی هستند که داخل دو دابل کوت نوشته می شوند تا بعداً توسط آرگومانهای فرستاده شده ( پاس داده شده ) جایگزین گردند.
{{چپچین}}
%[parameter][flags][width][.precision][length]type
{{پایان چپچین}}
<br><br>
ابتدا پارامتر تعیین کننده نوشته می شود ، سپس پرچمها و سپس عرض و پهنا و سپس میزان دقت و بعد طول و در نهایت نوع داده آرگومان
==انواع داده آرگومان==
انواع داده آرگومان عبارتند از :
{{چپچین}}
d, i
{{پایان چپچین}}
که اعداد دهدهی هستند با این تفاوت که در تابع scanf تعیین کننده نوع i اگر در ابتدای آرگومان نوشته شود 0x آن را هگزادسیمال ( شانزدهشانزدهی ) دریافت می کند و اگر در ابتدای آرگومان نوشته شود 0 آن را اوکتال ( هشتهشتی ) دریافت خواهد نمود
{{چپچین}}
u
{{پایان چپچین}}
که اعداد دهدهی بدون علامت را تعیین می کند unsigned decimal که همان unsigned int می باشد
{{چپچین}}
ld , li
{{پایان چپچین}}
که اعداد صحیح بلند را تعیین می کند long int
{{چپچین}}
lld , lli
{{پایان چپچین}}
که اعداد صحیح خیلی بلند را تعیین می کند long long int
{{چپچین}}
lu
{{پایان چپچین}}
که اعداد صحیح بلند بدون علامت را تعیین می کند unsigned long
{{چپچین}}
llu
{{پایان چپچین}}
که اعداد صحیح خیلی بلند بدون علامت را تعیین می کند unsigned long long int
{{چپچین}}
f, F
{{پایان چپچین}}
برای اعداد اعشاری با این تفاوت که f برای بینهایت inf یا infininty و برای تعریفنشدهها nan را باز می گرداند و F برای بینهایت INF یا INFINITY و برای تعریفنشدهها NAN را باز می گرداند
{{چپچین}}
lf
{{پایان چپچین}}
که اعداد اعشاری با دقت دو برابر را تعیین می کند double
{{چپچین}}
Lf
{{پایان چپچین}}
برای تعیین اعداد اعشاری با دقت بسیار زیاد به کار می رود long double
{{چپچین}}
e, E
{{پایان چپچین}}
برای اعداد اعشاری به صورت توان برای ۱۰ که به صورت d.ddde±dd مقدار را می فرستد یا دریافت می کند که شامل مقدار صحیح است و یک نقطه و مقادیر اعشاری و علامت E برای E و e برای e و سپس نما و توان که دست کم دو رقم هستند . دقت کنید که در ویندوز ارقام توان به صورت پیش فرض سه تا هستند . مثال : 1.5e03 یعنی ۱٫۵ ضربدر ۱۰ به توان ۳
{{چپچین}}
g, G
{{پایان چپچین}}
برای اعداد که اگر کامل ( صحیح ) باشند شامل نقطه و ممیز نخواهد شد و اگر اعشاری باشند ممکن است آن را به صورت معمولی بنویسد یا به صورت توان ۱۰ که همان e و E می باشند که البته می تواند دریافت نیز بکند ( مثلاً در تابع scanf ) و خود کامپایلر تشخیص می دهد که کدام بهتر است و با این تفاوت که پشت سر نما 0 نمی گذارد . مثال : 21.965 یا 2.5e4
{{چپچین}}
x, X
{{پایان چپچین}}
برای اعداد هگزادسیمال که صحیح بدون علامت هستند که x برای حروف کوچک است مثل x5f و X برای حروف بزرگ مثل X5F
{{چپچین}}
o
{{پایان چپچین}}
برای اعداد اوکتال که صحیح بدون علامت هستند
{{چپچین}}
s
{{پایان چپچین}}
برای رشتههایی که با NULL پایان می یابند ( اگر به یاد داشته باشید ، رشته ، مجموعهای از کاراکترهاست ) مثل رشتههایی که با آرایه می سازیم و ذخیره می نمائیم یعنی رشتهای مثل : monkeys are cute
{{چپچین}}
c
{{پایان چپچین}}
برای یک کاراکتر که به خروجی فرستاده می شود یا از ورودی دریافت می شود
{{چپچین}}
p
{{پایان چپچین}}
برای اشارهگرها که آدرسشان به رابط خطدستوری فرستاده شود یا از آنجا دریافت شود . طبق استاندارد می تواند و باید از نوع پوچ باشد void ولی این مورد یعنی برای p وابسته به نویسنده پیادهساز می باشد و هر کامپایلر به دلخواه خود عمل می کند ( مراجعه کنید به راهنمای کامپایلر خود )
{{چپچین}}
a, A
{{پایان چپچین}}
برای اعداد اعشاری با دقت دو برابر ( double ) که در مبنای شانزده ( هگزادسیمال ) نوشته می شود و 0x و بقیه ارقام و حروف ( کوچک ) برای a و 0X و بقیه ارقام و حروف ( بزرگ ) برای A ( دقت کنید که این استاندارد است ولی هر کامپایلر به دلخواه خود قابلیتهای آن را ممکن است افزایش داده باشد )
{{چپچین}}
n
{{پایان چپچین}}
مقداری را در خروجی خطدستوری چاپ نمی کند اما به آرگومان اشارهگر متناظر خود ، تعداد کاراکترهای داخل تابع خود را باز می گرداند
<br><br>
همچنین با استفاده از ماکروی wchar_t که در فایل سرآیند wchar.h تعریف شده است ما می توانیم کاراکترهای اضافهتر از ازکی را که در UTF-8 و UTF-16 و UTF-32 تعریف شدهاند در تابع printf یا scanf و بقیه توابع این فایل سرآیند به عنوان تعیین کننده نوع آرگومان تعیین کنیم تا کاراکترهای مذکور را در رابط خطدستوری چاپ نمائیم یا دریافت کنیم که این تعیین کنندهها شامل :
{{چپچین}}
lc or C
{{پایان چپچین}}
lc و یا C ( بزرگ ) برای یک کاراکتر UTF و
{{چپچین}}
ls or S
{{پایان چپچین}}
ls یا S ( بزرگ ) برای یک رشته انکدینگ UTF
می شود . اما کاراکترهای UTF-8 را می توان در متن منبع نیز نوشت و آن را در خروجی خطدستوری چاپ نمود . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
printf("ญ");
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
که پس از کامپایل و اجرا ، در خروجی کاراکتر ญ از حروف زبان تایلندی را مشاهده خواهید نمود . اما برای کار با حروف یونیکد Unicode مثل UTF-8 باید از توابع و ماکروهای فایل سرآیند wchar.h استفاده نمائید که در مبحث مربوطه نوشته خواهد شد
{{چپچین}}
zu
{{پایان چپچین}}
برای تعیین نوع فرمت داده از نوع size_t که هنوز به آن نرسیدهایم و در ادامه خواهم نوشت اما فقط برای استانداردهای جدید تعریف شده است و در استانداردهای قدیمی مثل C89 همان ul% را می نویسیم
'''پارامترِ تعیین کننده شماره آرگومان''' ، جزء استاندارد سی نیست و فقط در پازیکس ( POSIX رابط کاربری قابل حمل برای سیستم عاملهای محیطهای پنجرهای ایکس ) تعریف شده است که یک عدد را می نویسیم و در مقابل آن یک علامت دلار یا همان پسو $ را می گذاریم . با این کار حتی می توانیم کاری کنیم تا یک آرگومان چند بار چاپ یا دریافت شود و البته اگر از آن استفاده کنیم باید در مورد تمام تعیین کنندههای آرگومانهای دیگر نیز استفاده کنیم . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main()
{
int a = 15;
printf("%1$d %1$d", a);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در اینجا printf دو بار a را چاپ می کند و در مثال زیر :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main()
{
int a = 15, b = 17;
printf("%2$d %1$d", a, b);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
با اینکه ابتدا آرگومان a و سپس b فرستاده شدهاند ، اما چون شماره تعیین اول 2 و شماره تعیین دوم 1 می باشد ابتدا b و سپس a چاپ می شود
در صورتی که بخواهید علامت درصد % را در خروجی خط دستوری چاپ کنید باید دو بار آن را بنویسید مثل %%
'''و پرچمها عبارتند از :'''
{{چپچین}}
-
{{پایان چپچین}}
این پرچم متن خروجی خطدستوری را در تعیینکننده فرمت خود چپچین می کند . به صورت پیشفرض تمام متون چپچین هستند اما اگر پیش از تعیین کننده نوع آرگومان عددی را بنویسید ( که کمی جلوتر آن را خواهیم نوشت ) به همان اندازه خروجی دارای فضای سفید ( space ) خواهد بود که آرگومان را جلو می برد اما اگر در تعیینکننده فرمت یک علامت منفی ( مایناس - ) بگذارید آن را به سمت چپ انتقال خواهد داد
{{چپچین}}
+
{{پایان چپچین}}
این پرچم ، تضمین می کند که علامت عدد در خروجی خطدستوری نوشته خواهد شد یعنی - برای اعداد منفی ( negative ) و + برای اعداد مثبت ( positive ) که به صورت پیشفرض فقط برای اعداد منفی نوشته می شود و برای اعداد مثبت علامتی گذاشته نمی شود
{{چپچین}}
فضای سپید یا همان اسپیس
{{پایان چپچین}}
این پرچم یعنی space که بازگردان آن می شود فضای سپید یا فضای خالی برای اعداد مثبت جای خالی می گذارد و برای اعداد منفی علامت منفی ( مایناس - ) که اگر همراه با علامت مثبت ( + ) نوشته شود فضای سپید نادیده گرفته می شود
{{چپچین}}
0
{{پایان چپچین}}
عدد صفر به انگلیسی 0 ( زیرو ) هنگامی که برای آرگومان پهنا و عرضی در نظر گرفته شود ( که در ادامه می نویسیم ) که یک عدد است به جای فضای خالی پشت عدد ، صفر می گذارد که البته بستگی به تعداد ارقام عدد نیز دارد ؛ یعنی اگر عدد 352 باشد و ما پهنای آن را ۸ تا تعیین کرده باشیم ۵ تا فضای خالی قرار می گیرد ؛ اگر از این پرچم استفاده کنیم در خروجی خطدستوری چاپ می شود : 00000352
{{چپچین}}
#
{{پایان چپچین}}
پرچم هاش یا شارپ چندین کار را می تواند انجام بدهد :
۱ − برای تعیینکنندههای فرمت g و G در صورتی که قسمت اعشار نداشته باشند 0 های مقابل آن را ( در قسمت اعشاری ) حذف نمی کند
۲ − برای فرمتکنندههای a و A و e و E و f و F و g و G یک علامت اعشار ( ممیز که در انگلیسی نقطه است ) را حتماً اضافه می کند تا مشخص شود عدد اعشاری است حتی در صورتی که قسمت اعشار 0 باشد
۳ − برای تعیینکنندههای فرمت اوکتال o و هگزادسیمال کوچک x و هگزادسیمال بزرگ X برای هر عددی جز 0 قبل از آن علائم 0 و 0x و 0X را به ترتیب می نویسد و پیش از مقدار چاپ شده در خروجی خطدستوری قرار می دهد
۴ − برای تعیینکنندههای فرمت ls یا S باعث می شود تا سایز متن به تعداد کاراکترهای خروجی باشد و نه به اندازه ( size ) کاراکترهای موجود که ممکن است چند بایتی و عریض باشند که در UFT-8 یا uTF-16 یا UTF-32 تعریف شدهاند
۵ − برای تعیینکنندههای فرمت p که برای چاپ آدرس اشارهگر است آن را به مقدار هگزادسیمال تبدیل می کند که قابل برگشت نیست ( یعنی عکس همین عمل ) مگر اینکه در محیطهای ترا اسپیس ( teraspace ) که شامل برخی سیستم عاملها نظیر لینوکس می شود با دستور مستقیم به کامپایلر آن را مهیا نمائیم
{{چپچین}}
'
{{پایان چپچین}}
آپوستروف با علامت ' ( که همان سینگل کوت می باشد ) باعث می شود تا هر سه رفم با یک ممیز ( علامت نقطه در انگلیسی . ) از یکدیگر جدا شوند که البته برای این کار باید فایل سرآیند locale.h را به برنامه خود ضمیمه نمائید مثل :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
#include <locale.h>
int main()
{
setlocale(LC_NUMERIC, "");
int a = 1564952413;
printf("%'d", a);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
که در اینجا برنامه چاپ می کند : 1.564.952.413
مطالب پرچمها کاملاً روشن هستند و نیازی به مثال ندارد اما به عنوان نمونه یک مثال برای پرچم مایناس ( علامت منفی ) می نویسیم :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main()
{
int a = 47;
printf("%-6d", a);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در این مثال اگر علامت منفی را بر داریم عدد 47 با ۶ فاصله که نوشتهایم 6 چاپ می شود اما چون علامت منفی گذاشتهایم چپچین شده و در ابتدای رابط خطدستوری قرار می گیرد
<br><br>
'''عرض و پهنا'''
در عرض و پهنا ، پس از علامت درصد یک شماره می نویسیم که ورودی یا خروجی را به جلو می راند و به هیچ وجه باعث از بین رفتن مقدار نمی شود . این کار باعث می شود تا بتوانیم در رابط خطدستوری شکل و جدول خاصی را ایجاد کنیم . به علاوه اگر پس از علامت درصد علامت استریسک ( ستاره ) را بنویسیم بتوانیم به صورت پویا ، مقداری را به عنوان آرگومان بنویسیم تا به همان اندازه کاراکترهای ما به جلو رانده شوند . مثال عدد را در مثال پیشین نوشتیم ، اما برای مثال استریسک :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main()
{
int a = 8, b = 94;
printf("%*d", a, b);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در مثال بالا مقدار a مقدار ۸ می باشد و b مقدار ۹۴ که مقدار 94 را در خروجی خطدستوری چاپ نمودهایم اما به مقدار a یعنی ۸ تا فاصله و فضای سپید و خالی پیش از آن قرار دادهایم که عدد به جلو رانده می شود
'''دقت کنید :'''
اگر در قسمت تعیینکننده فرمت یک نقطه بگذارید و پس از آن یک عدد بنویسید ، برای اعداد اعشاری دقت اعشار همان عدد است و مابقی گرد شده و نادیده گرفته می شوند . برای رشتهها نیز تعداد کاراکترها را معین می کند که اگر از عدد نوشته شده بیشتر باشد ، کاراکترهای بعدی نادیده گرفته می شوند . همچنین می توانید بعد از علامت نقطه ، یک استریسک بگذارید و در قسمت آرگومانها مقدار مورد نظر را به تابع بفرستید تا دقت را معین کنید . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main()
{
char ch[] = "whatthehell";
printf("%.3s", ch);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main()
{
printf("%.*s", 3, "abcdef");
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در مثال اول رشته whatthehell فقط سه کاراکتر اولش چاپ می شود و در مثال دوم فقط abc . برای اعداد اعشاری نیز یک مثال می نویسیم :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main()
{
float f = 2.564;
printf("%.2f", f);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در مثال بالا مقدار ۲٫۵۶۴ عدد ۴ ـش نادیده گرفته می شود ( چون کوچکتر از ۵ است اگر گرد شود می شود 0 که فاقد مقداری در ارزش مکانی است و نادیده گرفته می شود )
'''تعیین کنندههای طول :'''
{{چپچین}}
hh
{{پایان چپچین}}
برای اعداد صحیح که به صورت کاراکتر تعریف شدهاند و دیگر نیازی به نقش ایفا کردن و کستکردن ندارد . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main()
{
char a = 12;
printf("%hhd", a);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در مثال بالا a یک کاراکتر است ، اما ما تعیین کننده نوع آرگومان را d و decimal تعریف کردهایم . اما با این حال ( به خاطر استفاده از hh ) برنامه بدون هیچ اشکالی مقدار 12 را در خروجی خطدستوری نمایش می دهد ( دقت کنید که حجم یک کاراکتر ۱ بایت است و تنها می تواند تا مقدار ۱۲۷ و یا بدون علامت تا ۲۵۵ را در خود ذخیره کند )
{{چپچین}}
h
{{پایان چپچین}}
برای اعداد صحیح در مبنای ۱۰ و یا اوکتال و یا هگزادسیمال که به صورت short ( کوتاه ) تعریف شدهاند ( دقت کنید که نوع داده کوتاه یک یا نهایتاً دو بایت است و مقادیر بزرگتر از ظیف خود باعث ایجاد خطا می شود )
مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main()
{
unsigned short a = 300;
printf("%hd", a);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در مثال بالا a یک کوتاه بدون علامت است که با تعیین کننده نوع صحیح و پیشوند h به خروجی خطدستوری ارسال می شود
{{چپچین}}
l
{{پایان چپچین}}
برای نوع اعداد صحیح بلند ؛ البته شما می توانید اعداد اوکتال یا هگزادسیمال را نیز با طول بلند و تعیینکننده فرمت صحیح به مبنای ده برگردانده و در رابط خطدستوری از آن استفاده کنید . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main()
{
long a = 0xff;
printf("%ld", a);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در مثال بالا نوع داده a بلند است و در آن ff را به شکلی که نوشته شده ( و باید بشود ) ذخیره نمودهایم . در هنگام چاپ با مقدار ۲۵۵ رو به رو خواهیم شد ( دقت کنید که ff در مبنای ۱۰ می شود ۲۵۶ ولی چون ۰ نیز یک مقدار است می شود ۲۵۵ )
{{چپچین}}
ll
{{پایان چپچین}}
برای تعیین طول داده صحیح خیلی بلند
{{چپچین}}
L
{{پایان چپچین}}
برای تعیین طول داده اعشاری خیلی بلند که می شود Lf یا LF یا Lg یا LG
{{چپچین}}
z
{{پایان چپچین}}
برای تعیین طول داده از نوع size_t که در فایل سرآیند stfdef تعریف شده است
{{چپچین}}
j
{{پایان چپچین}}
برای تعیین طول داده از نوع intmax_t که در فایل سرآیند inttypes تعریف شده است
{{چپچین}}
t
{{پایان چپچین}}
برای تعیین طول داده از نوع ptrdiff_t که در قایل سرآیند stddef تعریف شده است
{{چپچین}}
H
{{پایان چپچین}}
به عنوان پیشوند برای A و a و E و e و f و F و G و g که قسمت اعشاری را ۳۲ بیت در نظر می گیرد Decimal32_
{{چپچین}}
D
{{پایان چپچین}}
به عنوان پیشوند برای A و a و E و e و f و F و G و g که قسمت اعشاری را ۶۴ بیت در نظر می گیرد Decimal64_
{{چپچین}}
DD
{{پایان چپچین}}
به عنوان پیشوند برای A و a و E و e و f و F و G و g که قسمت اعشاری را ۱۲۸ بیت در نظر می گیرد Decimal128_
برخی از تعیین کنندههای طول آرگومان در استاندراد باید خارج از دو دابل کوت نوشته شوند و البته باید فایل سرآیند inttypes.h را ضمیمه برنامه خود نمائید
{{چپچین}}
PRId32
PRId64
PRIi32
PRIi64
PRIu32
PRIu64
PRIx32
PRIx64
{{پایان چپچین}}
اولی برای اعداد صحیح ۳۲ بیت و دومی برای صحیح ۶۴ بیت و بعدی برای اعداد صحیح ( منفی و مثبت ) ۳۲ بیت و بعدی مانند قبلی ولی ۶۴ بیت ، بعدی برای اعداد صحیح بدون علامت ۳۲ بیتی و بعدی همان برای ۶۴ بیتی و بعدی برای اعداد هگزادسیمال ۳۲ بیت و بعدی همان برای ۶۴ بیتی . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
#include <inttypes.h>
int main()
{
int a = 45;
printf("%" PRId64 "\n", a);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در مثال بالا متغیر از نوع صحیح a با مقدار ۴۵ تعریف شده است و تابع کتاخانهای printf از PRId64 برای تعیینکننده فرمت و تعیین کننده نوع آرگومان استفاده شده و آرگومان a به آن فرستاده شده است که پس از کامپایل و اجرا در خروجی عدد 45 را نمایش می دهد
== امنیت زنجیرهای ==
پیش از آغاز نوشتن تابعها و ماکروها لازم است مطلبی کلی را بدانید که در دانش رایانه و برنامهنویسی ( و حتی الکترونیک که اینجا به آن نمی پردازیم ) دانستن آن ضروری است . در دانش رایانه ، زنجیره یا ریسمان به کوچکترین مجموعه دستور العملهای یک برنامه می گویند که توسط پردازنده مرکزی ( واحد پردازشگر مرکزی / سیپییو CPU ) قابل اجرا است . اما در دانش برنامهنویسی در زبانهایی که تابعگرا هستند ،امنیت زنجیرهپردازه یا امنیت زنجیرهای بدین مفهوم است که تابع اگر در هنگام فراخوانی ، توسط چند سند برنامه ( متن برنامه Source Code File ) باعث رفتار تعریفنشده ، ویرانی دادهها یا شرایط رقابتی نشود از نظر زنجیرهای یا ریسمانی ، امن است و در غیر این صورت ، غیر ایمن . بدین مفهوم که اگر تابع در چند زنجیره سند منبع ( سند برنامه ) فراخوانده شود باعث تداخل آنها با هم نمی شود تا : ۱ - رفتار تعریفنشدهای رخ ندهد ۲ - مقادیر و موجودی متغیرها ( که میتوانند ماکرو یا تابع باشند ) دستخوش تغییر یا نابودی نشود ۳ - طبق استاندارد و زبان ، در سندها و فایلهایی که مجاز به اشتراک و استفاده چندباره آن در سندها نیستیم از آنها استفاده نکنیم و یا آنها را مستقل تعریف کنیم ( نظیر استفاده از کلیدواژه static برای تابعها که پیشتر در مبحث کلاسهای ذخیره مطرح کردیم ) دقت کنید که اگر شرایط رقابتی ، پیش بیاید رفتارهای پیشبینی نشده و ناخوشایند برای برنامهنویس پیش می آیند که برنامه نوشته شده را دچار خطا و باگ Bug می کند
در این کتاب ، فقط توابع و ماکروهایی که از نظر امنیت زنجیرهای ، امن نیستند می نویسیم امن نیست ( از نظر امنیت زنجیرهای ) و در مورد مابقی آن را نمی نویسیم ( معلوم است که امن است )
== تابع printf ==
نمای کلی تابع کتابخانهای printf و تابعهای مشابه آن بدین شکل است :
{{چپچین}}
printf(const char * format-string, argument-list);
{{پایان چپچین}}
تابع printf مخفف print formatted و به معنی پرینت فرمت شده می باشد که یک یا چند رشته را دریافت می نماید که داخل آنها تعیینکنندههای فرمت و تعیین کنندههای مختلف می توانند همان طور که تا بدینجا نوشته شد آن را آماده پذیرش آرگومان یا آرگومانها نموده که آرگومان(ها) را به آن می فرستیم ( که حتی می توانند مقدار باشند ) تا جایگزین تعیینکنندههای فرمت شود( شوند )
اگر تعداد آرگومانهای فرستاده شده از تعیینکنندههای فرمت بیشتر باشند ، آنهایی که اضافه هستند نادیده گرفته می شوند اما اگر تعیینکنندههای فرمت بیشتر از آرگومانهای فرستاده شده باشند ، نتیجه تعریف نشده است ( مطابق با استاندارد سی ) . اگر تابع printf با موفقیت بتواند به اتمام برسد یک مقدار مثبت را که تعداد کاراکترهای دریافت شده می باشد را باز می گرداند ( دقت کنید که حتی اعداد و دنبالههای فرار نیز کاراکتر حساب می شوند ) ولی اگر ناموفق باشد یک مقدار منفی را باز می گرداند . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main()
{
printf("%d", printf("This is a string\n"));
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
مثال بالا ابتدا printf داخلی را ارزیابی کرده که یک رشته است و آن را چاپ می کند و سپس بیرونی و اولی را که ۱۷ کاراکتر در رشته ما ( به همراه دنباله فرار خط شکسته ) وجود دارد و آن را در رابط خطدستوری نمایش می دهد
'''دقت کنید :'''
همان طور که گفته شد اگر تعداد تعیینکنندههای فرمت بیشتر از آرگومانها باشد ، نتیجه تعریفنشده است ( در استاندارد سی ) ولی کامپایلر قدرتمندی همچون GCC به شما هشدار خواهد داد ؛ اما برنامه کامپایل شده و اجرا می شود ولی دارای رخنهپذیری امنیتی خواهد بود که هکرها میتوانند از روش حمله رشته فرمت شده استفاده کرده و به دادههای برنامه شما و سیستم عامل دسترسی پیدا کنند . جهت اطلاعات بیشتر صفحه زیر را مطالعه کنید :
[https://en.wikipedia.org/wiki/Uncontrolled_format_string Format string attack]
همچنین نوشتن تعیینکننده فرمت n به صورت n% که در همین مبحث نوشته شد می تواند باعث حمله رشته فرمت شده بشود . که باید بسیار مراقب استفاده آن به صورت صحیح باشید . از طرفی این تعیینکننده فرمت باعث ایجاد کامل شدن تورینگ می شود . جهت اطلاعات بیشتر به صفحه زیر مراجعه کنید :
[https://en.wikipedia.org/wiki/Turing-complete Turing-complete ]
== تابع scanf ==
نمای کلی تابع کتابخانهای scanf و تابعهای مشابه آن به شکل زیر است :
{{چپچین}}
scanf(const char *format-string, argument-list);
{{پایان چپچین}}
تابع scanf مخفف scan formatted به معنی اسکن فرمت شده قادر است تا از ورودی استاندارد ( معمولاً صفحهکلید Keyboard ) مقادیری را دریافت نموده و در متغیرها و آرگومانهای خود جای بدهد و آنها را مقداردهی نماید . شکل کلی رشته فرمتشده دریافت کنندههایی مثل scanf و تابعهای مشابه آن به شرح زیر است :
{{چپچین}}
%[parameter]*[width][length]type
{{پایان چپچین}}
پارامتر در scanf همانند printf می باشد . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main()
{
int a, b;
scanf("%2$d%1$d", &a, &b);
printf("%d & %d",a , b);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
همان طور که می بینید با نوشتن شماره و علامت دلار ابتدا b دریافت می شود و سپس a ولی در خروجی ابتدا a چاپ می شود و سپس b . '''دقت کنید''' که تابع scanf برای دریافت و وارد کردن مقدار داخل متغیر از علامت آدرسدهی استفاده می کند و علت آن نحوه تعریف آن در فایل سرآیند stdio می باشد که با اشارهگرها نوشته می شود
برای اینکه پهنا و عرض یک آرگومان را جهت دریافت تعیین کنید باید بعد از علامت درصد ( % percent ) یک عدد را بنویسید که به همان تعداد کاراکتر ( چه حرفی و چه عددی ) دریافت خواهد شد و نه بیشتر . '''دقت کنید''' که علامت ستاره ( استریسک * ) در تابع scanf پهنا را تعیین نمی کند بلکه باعث می شود تا تابع scanf یک یا چند کاراکتر را نادیده گرفته و در آرگومانهای فرستاده شده ذخیره نکند
پس با نوشتن مقدار پس از علامت درضد تعیین می کنیم که تابع ، چند کاراکتر ( عددی یا حرفی ) را دریافت کند . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
int i;
printf("Enter a number :\n");
scanf("%2d", &i);
printf("Your number is : %d\n", i);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در مثال بالا شما می توانید به عنوان مثال یک عدد ۵ رقمی را وارد کنید ولی فقط ۲ رقم اول آن دریافت می شود
در تابع scanf و تابعهای مشابه آن می توان از scanset ها استفاده نمود . یک جفت کروشه باز و بسته می توانند تعیین کنند که تابع scanf و تابعهای مشابه آن فقط کاراکترهای خاصی را دریافت نمایند و یا کاراکترهایی را از قلم بیاندازند . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
char str[128];
printf("Enter a string: ");
scanf("%[A-Z]s", str);
printf("You entered: %s\n", str);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در مثال بالا فقط تا زمانی که تابع scanf به کاراکترهای A تا Z برسد آنها را اسکن می کند و در رشته str ذخیره می کند و اگر به کاراکتر دیگری برسد متوقف می شود . '''دقت کنید''' که اگر اولین کاراکتر ورودی شما یک حرف کوچک باشد ( به عنوان مثال ) همان جا عمل اسکن متوقف می شود . دقت کنید که تابع scanf توسط اشارهگرها تعریف شده است و توسط عملگر آدرسدهی مقدار و موجودی را دریافت نموده و در آرگومان متناظر ذخیره می کند بنابراین برای رشته که یک اشارهگر است از عملگر آدرسدهی استفاده نمی کنیم ( حتی اگر از کاراکتر آرایهای استفاده کنیم ؛ چون می دانید که آرایهها توسط اشارهگرها تعریف می شوند )
همچنین باید بدانید که اگر داخل جفت کروشه باز و بسته ، پیش از کاراکتر یا کاراکترها از علامت کرات ^ استفاده کنید تا زمانی که تابع scanf به آن نرسیده باشد دادهها را دریافت کرده و در آرگومان متناظر خود ذخیره می کند . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
char str[100];
printf("Enter a string: \n");
scanf("%[^p]s", str);
printf("You entered: %s\n", str);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در مثال بالا می توانید متن مقابل را وارد کنید : C is more powerful than python ولی با جمله C is more powerful than مواجه خواهید شد چرا که scanf به کاراکتر p رسیده است
ضمناً '''دقت کنید''' که در اسکن کردن متونی که دارای فضای سپید ( مثل اسپیس Space ) هستند استفاده از scanset ها ضروری است . چرا که تابع scanf و تابعهای مشابه آن فضای سفید را به صورت پیشفرض دریافت نمی کنند . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
char a[100];
scanf("%[^\n]s", a);
printf("Your text is : %s\n", a);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در مثال بالا اگر از scanset ـی که نوشته شده [n\^] استفاده نکنید نمی توانید از اسپیس استفاده کنید و با اولین اسپیس رشته شما شکسته می شود و scanf دیگر اسکن نمی کند
'''نکته :''' علامت هایفن یا همان خط تیره ( که به اشتباه به آن دش dash نیز می گویند ) برای بیان یک طیف است اما اگر بخواهید خود آن را برای اسکن شدن یا نشدن تعیین کنید هر کامپایلر از روش خاص خود استفاده می کند و باید به راهنمای کامپایلر خود مراجعه کنید
'''دقت کنید''' که فضای سپید مثل اسپیس space یا جدول افقی Tab در تابع scanf و تابعهای مشابه آن باعث می شود تا تابع از ورودی بخواند اما آن را در آرگومانی ذخیره نکند . از این تکنیک می توانید در قسمتهایی از کد خود که خط شکسته دارند استفاده کنید ( چون خط شکسته باعث می شود تا scanf و تابعهای مشابه آن ، خط شکسته را به عنوان یک کاراکتر دریافت کرده و دیگر متن شما را دریافت نکنند )
'''نکته :''' علامت استریسک باعث می شود تا کاراکتر یا کاراکترهایی نادیده گرفته شوند و در آرگومانها ذخیره نشوند
مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
char a, b;
printf("enter a character\n");
scanf("%c", &a);
printf("enter another character\n");
scanf(" %c%*[^\n]",&b);
printf("Your characters were %c and %c\n", a, b);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در مثال بالا کاراکتر a بدون هیچ مشکلی دریافت می شود اما چون Enter را می زنید و تابع printf نیز خط را می شکند کاراکتر b باید با ترفند دریافت شود که ابتدا یک اسپیس وارد می کنیم و سپس خط شکسته را نادیده گرفته و کاراکتر b را دریافت می نمائیم تا در خروجی خطدستوری نمایش داده شود
مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
char a[100], b[100];
printf("Enter a text :\n");
scanf("%[^\n]s", a);
printf("Your first text is : %s\n", a);
printf("Enter second text :\n");
scanf(" %[^\n]s", b);
printf("Yurt second text is : %s\n", b);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
مثال بالا نیز همانند مثال قبل است با این تفاوت که رشتهها را به جای کاراکترها ذخیره می کنیم . در رشته اول scanf تا زمانی که به خط شکسته نرسیده باشد تابع scanf اسکن می کند و در رشته دوم ابتدا یک اسپیس نوشتهایم تا خط شکسته قبلی ذخیره نگردد و خط شکسته را نادیده گرفتهایم
'''دقت کنید :''' که تابع scanf باید به تعداد و اندازه تعریف شده مقدار عددی یا حرفی و رشتهای بپذیرد ؛ در غیر این صورت ذخیره ساز میانی ( بافر Buffer ) سرریز می شود که هم باعث اشغال شدن حافظه می گردد و برنامه شما دچار شکست و توقف می شود و هم اینکه یک رخنه پذیری محسوب می شود . مخصوصاً در مورد رشتهها اگر تعداد تعیین شده کمتر از تعداد کاراکترهای وارد شده باشد بافر سرریز می شود که برای این کار ترفندهای مختلفی وجود دارد که سادهترین آن تعیین پهنا و عرض رشته است که کافی نیست ولی برای تعیین آن باید از تابعهای کتابخانهای دیگری استفاده کرد که در مبحث فعلی موجود نیستند و در مباحث فایلهای سرآیند دیگر موجودند . ضمن اینکه اگر به درستی از تابع scanf استفاده نکنید امکان حمله رشته فرمت شده وجود دارد ( همانند printf که در آنجا آدرسش را گذاشتیم یعنی هکرها با وارد کردن کاراکترهایی خاص به حافظه برنامه یا سیستم عامل و سیستم دسترسی پیدا می کنند )
== تابع sprintf ==
تابع sprintf سرنام string print formatted به معنی چاپ رشته فرمتشده همانند تابع printf می باشد به غیر از اینکه متنی را در خروجی خطدستوری نمایش نمی دهد بلکه آن را ذخیره می کند که می توان با تابع printf ( به عنوان مثال ) آن را چاپ نمود . نمای کلی تابع sprintf به شکل زیر می باشد :
{{چپچین}}
sprintf(char *buffer, const char *format, arguments)
{{پایان چپچین}}
ابتدا نام رشتهای که قرار است به عنوان بافر ، دادهها را بگیرد می نویسیم ، سپس رشته خودمان را به همراه تعیینکنندههای فرمت ( در صورت لزوم ) می نویسیم و سپس آرگومانها را که خود می توانند حتی مقدار باشند می نویسیم که در نهایت در بافر ذخیره می شود . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main()
{
char buff[50];
char str[] = "string";
sprintf(buff, "This is a %s", str);
printf("%s", buff);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
ابتدا یک رشته به نام buff مخفف buffer اعلان نمودیم . سپس یک رشته به نام str مخفف string و به معنی رشته با مقدار string تعریف نمودیم . سپس توسط تابع کتابخانهای sprintf رشته This is a را به همراه تعیینکننده فرمت رشته که آرگومان آن str است در buff ذخیره کردیم ( که می شود This is a string یعنی این یک رشته است ) و سپس توسط تابع کتابخانهای printf مقدار buff را در خروجی خطدستوری چاپ نمودیم . از تمام تعیینکنندههای فرمت در printf در sprintf نیز می توانید استفاده کنید
== تابع sscanf ==
تابع sscanf سرنام string scan formatted به معنی اسکن رشته فرمتشده ، رشته موجود در متن منبع برنامه ( source code ) را دریافت می نماید و قسمتهای مختلف آن را اسکن می کند و در آرگومانها ذخیره می کند . نمای کلی تابع کتابخانهای sscanf به شکل زیر است :
{{چپچین}}
sscanf(const char *buffer, const char *format, arguments-list);
{{پایان چپچین}}
مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main()
{
char str[] = "This is a string with 2 numbers : 5 and 9";
char str2[10], str3[10], str4[10], str5[10], str6[10], str7[10];
char c1, c2;
int i1, i2, i3;
sscanf(str, "%s %s %c %s %s %d %s %c %d %s %d", str2, str3, &c1, str4, str5, &i1, str6, &c2, &i2, str7, &i3);
printf("%s %s %c %s %s %d %s %c %d %s %d", str2, str3, c1, str4, str5, i1, str6, c2, i2, str7, i3);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در مثال بالا یک رشته به نام str تعریف نمودهایم که یک رشته است که می گوید این یک رشته است با ۲ عدد : ۵ و ۹ سپس ۶ رشته ۱۰ کاراکتری که مطمئن هستیم رشتهها بیشتر از ۱۰ کاراکتر ندارند ، اعلان نمودهایم . سپس ۲ کاراکتر ، اعلان نمودهایم و سپس نیز ۳ عدد داده صحیح را اعلان نمودهایم . تابع کتابخانهای sscanf رشته str را می گیرد و قسمتهای مختلف آن را اسکن می کند و به ترتیب در آرگومانهای تعیین شده ( که متغیرهایی هستند که بالاتر نوشتیم اعلان شدهاند ) ذخیره کردهایم . در نهایت با تابع printf دادههای ذخیره شده را در خروجی خطدستوری چاپ نمودهایم . دقت کنید که scanset ها در sscanf نیز برقرار و کارا هستند
همچنین تابع sscanf در صورت عملکرد موفقیتآمیز مقداری بزرگتر یا مساوی 0 را باز می گرداند و در غیر این صورت مقدار EOF سرنام End Of File به معنی پایان فایل یا پایان سند . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main()
{
char str[] = "This is a string with 2 numbers : 5 and 9";
char str2[10], str3[10], str4[10], str5[10], str6[10], str7[10];
char c1, c2;
int i1, i2, i3;
int itemsread = 0;
itemsread = sscanf(str, "%s %s %c %s %s %d %s %c %d %s %d", str2, str3, &c1, str4, str5, &i1, str6, &c2, &i2, str7, &i3);
printf("%s %s %c %s %s %d %s %c %d %s %d\n", str2, str3, c1, str4, str5, i1, str6, c2, i2, str7, i3);
printf("Items read are : %d\n", itemsread);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در این مثال تابع کتابخانهای sscanf مقدار ۱۱ را باز می گرداند . ۲ رشته سپس ۱ کاراکتر سپس ۲ رشته و سپس ۱ عدد و دوباره ۱ رشته و سپس ۱ کاراکتر سپس ۱ عدد و بعد ۱ رشته و ۱ عدد دیگر که مجموعاً می شود ۱۱ مورد و آیتم دریافت شده
== تابع vprintf ==
تابع vprintf سرنام variadic print formatted به معنی پرینت فرمت شده تعداد متغیر ، تابعی همانند printf را توسط کاربر می سازد . فقط این تابع نیاز به ماکروها و توابعی دارد که در فایل سرآیند stdarg تعریف شدهاند و ما در اینجا به صورت مختصر توضیح می دهیم تا در مبحث مربوطه مفصلاً آنها را تشریح کنیم . va_list یک ماکرو است که فهرستی ( لیستی ) از آرگومانهایی که قرار است ایجاد شوند را در یک متغیر ایجاد می کند . سپس تابع va_start با ۲ آرگومان که اولی همان آرگومانهای va_list است را دریافت می کند تا امکان دسترسی به آن را فراهم کند و دومی آخرین آرگومان ثابت و غیر متغیر تابع را دریافت می کند تا تابع متغیر آغاز به کار کند و va_end آرگومان ساخته شده را می گیرد تا آن را خاتمه دهد ( در تابعی با تعداد پارامترهای متغیر ) . به مثال زیر دقت کنید :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
#include <stdarg.h>
void PrintFormatted(char *string, ...)
{
va_list args;
va_start(args, string);
vprintf(string, args);
va_end(args);
return;
}
int main()
{
PrintFormatted("%d variable argument\n", 1);
PrintFormatted("%d variable %s\n", 2, "arguments");
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در مثال ساده بالا ابتدا stdio را ضمیمه برنامه خود نمودهایم و سپس stdarg را تا تابعی با تعدادِ آرگومانهای پذیرنده متغیر تعریف کنیم . تابع پوچ PrintFormatted یک پارامتر رشته به نام string دارد و سه نقطه ( ellipsis ) که تعداد پارامترهای متغیر را نشان می دهد و تعیین می کند . سپس va_list متغیری برای کار با آرگومانهای دریافت شده با نام args را تعریف کرده است . سپس va_start آرگومانهای ارسالی و آرگومان تابع را پذیرفته است . سپس vprintf هر رشتهای را که به آن فرستاده شود در args ذخیره می کند و پرینت می نماید و در پایان va_end عمر args و تابع با تعداد پارامترهای متغیر را پایان می دهد . حالا به جای printf می توانیم از تابع vprintf استفاده کنیم که ابتدا یک رشته را به آن فرستادهایم که اولین قسمت آن یک متغیر عددی صحیح است که تعیین کننده فرمت آن را نوشته و در پایان به آن ۱ را فرستادهایم . دومی نیز به همین شکل است به استثنای اینکه آخرین آرگومان فرستاده شده به آن ( قبل از خط شکسته ) یک رشته است ( "arguments" ) '''دقت کنید :''' تعیین کنندههای فرمت در vprintf همانند printf و sprintf میباشند
== تابع vsprintf ==
تابع vsprintf سرنام variadic string print formatted تلفیقی از vprintf و sprintf می باشد . نمای کلی ایجاد تابع vsprintf به شکل زیر است :
{{چپچین}}
vsprintf(char * buffer , const char * format , arguments-list)
{{پایان چپچین}}
ابتدا باید تابعی با تعداد پارامترهای متغیر تعریف نمود که در آن vsprintf یک متغیر اشارهگر را می پذیرد تا متن در آن ذخیره شود ، سپس تعیینکنندههای فرمت و در نهایت فهرست آرگومانهای فرستاده شده را . بدین ترتیب اگر متنی را با تعیین کنندههای فرمت به همراه آرگومانهای متناسب به vsprintf بفرستیم در متغیر اشارهگر ذخیره می شود که می توانیم آن را با یک تابع کتابخانهای مثل printf چاپ کنیم . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
#include <stdarg.h>
void vspfunc(char * str, char * fmt, ...)
{
va_list argptr;
va_start(argptr, fmt);
vsprintf(str, fmt, argptr);
va_end(argptr);
return;
}
int main(void)
{
char buff[50];
int c = 299792458;
double pi = 3.141592;
char string[] = "string";
vspfunc(buff, "%d %f %s", c, pi, string);
printf("%s", buff);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در مثال بالا ابتدا stdio.h و stdarg.h را ضمیمه برنامه خود نمودهایم تا از ماکروها و تابعهای کتابخانهای آنها در برنامه خود استفاده کنیم . سپس یک تابع پوچ با نام vspfunc مخفف vsprintffunction تعریف نمودهایم که یک متغیر اشارهگر از نوع کاراکتر به نام str مخفف string و یکی هم به نام fmt مخفف format دارد به همراه سه نقطه که نشانگر داشتن تعداد پارامترهای متغیر است . داخل تابع ابتدا به کمک ماکروی va_list متغیری که قرار است آرگومانها را پذیرا شود تعریف نمودهایم ( argptr ) سپس برای کار با آرگومانهای فرستاده شده و آرگومانهای تابع از va_start استفاده کردهایم . سپس تابع vsprintf سه آرگومان را می پذیرد . اولی اشارهگری که در آن دادهها ذخیره شوند ؛ دومی تعیینکنندههای فرمت و سومی فهرست آرگومانهای فرستاده شده . سپس va_end عمر argptr را پایان می دهد . چون تابع ، پوچ است مقداری را باز نمی گرداند . داخل تابع اصلی برنامه main یک رشته به کمک آرایهای از کاراکتر با نام buff مخفف buffer با پنجاه عنصر اعلان نمودهایم . یک متغیر صحیح که سرعت انتشار نور در خلأ را در خود ذخیره کرده یک متغیر اعشاری با دقت دو برابر که عدد پای ( پی ) را در ذخود ذخیره کرده و یک رشته که string را در خود ذخیره کرده . سپس آنها را به کمک تابع کتابخانهای vsprintf در buff ذخیره نمودهایم و با تابع کتابخانهای printf در خروجی خطدستوری چاپ نمودهایم و تابع با موفقیت به پایان می رسد
== تابع putchar ==
تابع کتابخانهای putchar سرنام put character به معنی کاراکتر را قرار بده یک کاراکتر را به خروجی خطدستوری می فرستد . نمای کلی ایجاد تابع کتابخانهای putchar به شکل زیر است :
{{چپچین}}
putchar(unsigned char);
{{پایان چپچین}}
برای استفاده از این تابع یا می توانید یک کاراکتر را داخل تابع بنویسید تا چاپ شود یا یک داده کاراکتری تعریف شده را به آن بفرستید . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
putchar('J');
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
که در خروجی خطدستوری کاراکتر J را چاپ می کند ؛ همچنین می توانید مقدار و موجودی J را داخل یک داده کاراکتری ذخیره کنید و سپس آن را به putchar بفرستید . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
char c = 'J';
putchar(c);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
یک مثال دیگر برای کامل کردن کاربرد تابع putchar :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
char ch = 'A';
for(ch = 'A'; ch <= 'Z'; ch++)
{
putchar(ch);
putchar('\n');
}
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
ابتدا یک کاراکتر با مقدار و موجودی کاراکتر A با نام ch تعریف نمودهایم . سپس با حلقه for کاراکتر ch را از A تا زمانی که مقدار کمتر و مساوی Z باشد به همراه یک خط شکسته در خروجی خطدستوری قرار دادهایم که همان حروف الفبای انگلیسی می باشد
== تابع getchar ==
تابع کتابخانهای getchar مخفف get character به معنی « کاراکتر را بگیر » برای دریافت یک کاراکتر از ورودی استاندارد ( معمولاً صفحهکلید Keyboard در ورودی خطدستوری ) می باشد . نمای کلی ایجاد تابع getchar بدین شکل می باشد :
{{چپچین}}
getchar(void);
{{پایان چپچین}}
تابع getchar آرگومانی را نمی پذیرد و مقدار آن فقط در دادههای صحیح قابل ذخیره است ( که کامپایلر به صورت خودکار نقش کاراکتر را به آن می دهد )
خروجی getchar باید یک کاراکتر باشد و اگر EOF یعنی End Of File را بازگرداند یعنی یا فایل به پایان رسیده است یا خطایی در وارد کردن کاراکتر وجود داشته است . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include<stdio.h>
int main()
{
int ch;
ch = getchar();
printf("The entered character is : %c", ch);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
ابتدا یک داده از نوع صحیح با نام ch اعلان نمودهایم ؛ سپس ch توسط getchar که مقداری از نوع کاراکتر دریافت می کند تعریف می شود و مقدار و موجودی آن ، همان مقدار و موجودی کاراکتری وارد شده است و سپس در خروجی خطدستوری چاپ می شود که کاراکتر وارد شده توسط شما کاراکتر ''x'' می باشد که ''x'' همان کاراکتر وارد شده توسط کاربر می باشد
== تابع puts ==
تابع کتابخانهای puts سرنام put string به معنی رشته را قرار بده ، یک رشته را در خروجی استاندارد که معمولاً محیط خطدستوری سیستم عامل است می نویسد . نمای کلی ایجاد تابع puts به شکل زیر می باشد :
{{چپچین}}
puts(const char * string);
{{پایان چپچین}}
می توانیم یک رشته را داخل آن بنویسیم یا نام یک متغیر از نوع رشته را که تعریف شده است به آن بفرستیم تا در خروجی خطدستوری نمایش دهد .
'''نکته :''' تابع puts به خودی خود ، در پایان رشته ، خط را می شکند و وارد خط بعدی می شوید
مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include<stdio.h>
int main()
{
puts("Hello World!");
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در قطعه کد بالا رشته !Hello World را نمایش دادهایم
مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include<stdio.h>
int main()
{
char ch[] = "This is a string";
puts(ch);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در مثال و قطعه کد بالا یک رشته به نام ch را تعریف کردهایم . سپس با تابع کتابخانهای puts مقدار و موجودی ch را نمایش دادهایم
همچنین اگر puts را داخل یک داده صحیح ذخیره کنید ، هم متن نمایش داده می شود و هم تعداد کاراکترهای داخل رشته puts ذخیره می شود . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include<stdio.h>
int main()
{
int n = puts("This is a string");
printf("%d", n);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
'''نکته :''' تعیینکنندهای فرمت در puts عمل نمی کنند و در صورت استفاده ، کامپایلر از شما خطا می گیرد
== تابع gets ==
تابع کتابخانهای gets سرنام get string به معنی رشته را بگیر ، از ورودی استاندارد که معمولاً صفحهکلید است رشتهای را دریافت می کند و سپس آن را در بافر ذخیره می کند ( که یک اشارهگر است ) . نمای کلی ایجاد تابع کتابخانهای gets به صورت زیر است :
{{چپچین}}
gets(char * buffer);
{{پایان چپچین}}
دقت کنید که از تعیینکنندههای فرمت نمی توانید در gets استفاده کنید . تابع gets با یک خط جدید ( شکسته شدن خط ) پایان می یابد که آن را به صورت یک تهی NULL ذخیره می کند و اگر عملیات دریافت با موفقیت انجام شود ، رشته ذخیره شده در خود را باز می گرداند و اگر یک اشارهگر تهی NULL Pointer را باز گرداند یعنی خطایی رخ داده و در صورتی که رشتهای وارد نشده باشد EOF سرنام End Of File را باز می گرداند
'''نکته :''' استفاده از تابع gets ریسک پذیر است ؛ چرا که چک نمی کند که رشتهای که شما اعلان کردهاید چند عنصری است و اگر از مقدار تعیین شده بیشتر باشد ، بافر Buffer سرریز می شود و آنچه که باز می گرداند تعریفنشده است
مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include<stdio.h>
int main()
{
char ch[30];
printf("Enter a string : \n");
gets(ch);
printf("%s", ch);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در قطعه کد بالا یک رشته ۳۰ کاراکتری با نام ch را اعلان نمودهایم . سپس در رابط خطدستوری چاپ کردهایم یک رشته را وارد کنید و خط را شکستهایم . سپس تابع gets رشته ch را از کاربر دریافت می کند و در نهایت تابع printf آنچه را که وارد کردهاید در خروجی خطدستوری چاپ می کند
'''
نکته مهم :''' تابع gets در استاندار C11 و از آن به بعد ، حذف شده است . اگر کامپایلر شما خطا گرفت یا اگر کامپایلر خود را تنظیم کردید تا از استاندارد جدید استفاده کند و از شما خطا گرفت ، علتش همین است . توصیه شده است که به جای gets از fgets استفاده کنید که در ادامه خواهیم نوشت
== ماکروهای stdin و stdout ==
در قسمت بعدی ماکروی FILE را خواهیم نوشت که به برنامهنویس اجازه میدهد تا جریان فایلی را ایجاد کند تا فایلی ساخته شود و آن را بخوانیم یا درون آن چیزی بنویسیم یا هر دوی اینها . اما ماکروهای stdin سرنام standard iput به معنی ورودی استاندارد و stdout سرنام standard output به معنی خروجی استاندارد برای ما این امکان را فراهم میآورند تا از ورودی و خروجی استاندارد ( در رایانه صفحهکلید و نمایشگر ) به جای جریان فایل در تابعهای کتابخانهای که فایل را میخوانند و در آن مینویسند از صفحهکلید و نمایشگر استفاده کنیم . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
fprintf(stdout, "%s", "string");
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در قطعه کد بالا از تابع کتابخانهای fprintf سر نام file print formatted به معنی چاپ فرمت شده فایل استفاده کردهایم اما به جای اینکه با فایلی سر و کار داشته باشیم و بخواهیم طبق معمول در فایلی چیزی را بنویسیم به جای نام فایل نوشتهایم : stdout
و سپس تعیینکننده فرمت تعیین کرده است که یک رشته نوشته شود ( در اینجا نمایش داده شود ) و به جای آن رشته string را به عنوان آرگومان به تابع فرستادهایم . به همین شکل می توان به جای یک تابع کتابخانهای که از فایل ، اطلاعات را می خواند ، بنویسیم : stdin و از صفحهکلید ، اطلاعات را دریافت کنیم
== ماکروی نوع داده FILE ==
به ورود و خروج دادهها از گذرگاه ( مثل برنامه ) جریان داده گفته می شود . همچنین به ورود و خروج دادهها به داخل فایل ، جریان فایل گفته می شود . ماکروی FILE با یک علامت استریسک و یک شناسه برای نام فایلی که می خواهیم بسازیم ، در برنامه ( زبان برنامهنویسی سی ) جریان فایلی را می سازد و آن را آماده استفاده می کند . نمای کلی ایجاد جریان فایل بدین شکل است :
{{چپچین}}
FILE * const char * name-of-file
{{پایان چپچین}}
که const char * name-of-file یک رشته است که نام فایلی را که قصد استفاده از آن را داریم را تعیین می کند . مثل : FILE * fp در اینجا fp سرنام file pointer نام انتخابی ما برای فایلی که قصد استفاده از آن را داریم می باشد
== تابعهای fopen و fclose ==
تابع fopen سرنام file open به معنی فایل را باز کن ، فایلی را که ماکروی نوع داده FILE آماده کرده باشد را باز میکند و در دادهی فایل باز شده ( توسط FILE ) ذخیره می کند . تابع کتابخانهای fopen دو پارامتر را از نوع رشته پذیرا می باشد : یکی نام فایل و دیگری نحوه باز کردن فایل file opening mode ( که هر دو طبعاً باید داخل دو دابل کوت " قرار بگیرند )
به عنوان نام فایل اگر فقط نامی را بنویسید ، برنامه فایل مورد نظر شما را در همان آدرس برنامه ایجاد می کند ، اما اگر آدرس معین دیگری را به آن بدهید در همان آدرس ایجاد می کند . تابع fopen در صورت عمل موفق ، یک اشارهگر به فایل ( و به طور کلّیتر شیئای که جریان فایل را در دست دارد ) باز می گرداند و در صورت عدم موفقیت یک اشارهگر تهی NULL باز می گرداند . تابع کتابخانهای fclose نیز سرنام file close فایل باز شده را می بندد تا از حافظه موقت ( RAM ) پاک شود و فضای اشغال شده را آزاد می کند که فقط باید بین جفت پرانتز باز و بسته آن ، نام فایلی را که ایجاد کردهاید بنویسید . تابع fclose در صورت موفقیتآمیز بودن عملیات مقدار 0 را باز می گرداند و در صورت خطا EOF را باز خواهد گرداند
نحوههای باز کردن فایل بدین شرح می باشند :
{{چپچین}}
r
{{پایان چپچین}}
مخفف read که برای خواندن فایل می باشد و به اولین کاراکتر فایل اشاره می کند
{{چپچین}}
w
{{پایان چپچین}}
مخفف write که برای نوشتن در فایل می باشد و فایل را باز نویسی می کند ( یعنی اگر داخل فایل متنی موجود باشد ، آن را جایگزین می کند ) و در صورت عدم وجود فایل ، فایل را ایجاد می کند
{{چپچین}}
a
{{پایان چپچین}}
مخفف append که در ادامه فایل ، متنی را می نویسد ( یعنی اگر متنی داخل آن موجود باشد ، در ادامه آن ، خواهد نوشت ) در صورت عدم وجود فایل آن را می سازد
{{چپچین}}
r+
{{پایان چپچین}}
مخفف + read که هم می خواند و هم می نویسد اما به اولین کاراکتر فایل اشاره می کند
{{چپچین}}
w+
{{پایان چپچین}}
مخفف + write که هم می خواند و هم می نویسد و در صورت نوشتن متن را جایگزین می کند . همچنین در صورت عدم وجود فایل ، آن را می سازد
{{چپچین}}
a+
{{پایان چپچین}}
مخفف + append که هم می خواند و هم در انتهای فایل می نویسد و به آخرین کاراکتر فایل اشاره می کند . در صورت عدم وجود فایل آن را می سازد
{{چپچین}}
rb
{{پایان چپچین}}
مخفف read binary که فایل را به صورت باینری ( دودویی ) و در واقع عددی می خواند . اگر فایل ، موجود نباشد یک اشارهگر NULL باز می گرداند
{{چپچین}}
wb
{{پایان چپچین}}
مخفف write binary که فایل را به صورت باینری ( دودویی ) و در واقع عددی می نویسد و جایگزین می کند . در صورت عدم وجود فایل آن را می سازد
{{چپچین}}
ab
{{پایان چپچین}}
مخفف append binary که فایل را به صورت باینری ( دودویی ) و در واقع عددی اضافه کرده و در انتهای می نویسد . در صورت عدم وجود فایل آن را می سازد
{{چپچین}}
rb+
{{پایان چپچین}}
مخفف + read binary که فایل را جهت خوانده و نوشته شدن در مبنای دو و به صورت عددی باز می کند . اگر فایلی وجود نداشته باشد یک اشارهگر NULL باز می گرداند
{{چپچین}}
wb+
{{پایان چپچین}}
مخفف + write binary که فایل را جهت خوانده و نوشته شدن در مبنای دو و به صورت عددی باز می کند و اگر محتوایی داشته باشد آن را جایگزین می کند . در صورت عدم وجود فایل ، آن را می سازد
{{چپچین}}
ab+
{{پایان چپچین}}
فایل را جهت خواندن و اضافه کردن در مبنای دو و در واقع عددی باز می کند . در صورت عدم وجود فایل آن را می سازد
مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
FILE * fp;
fp = fopen("/home/lovelorn/Documents/mytext.txt", "w");
fprintf(fp, "%s", "string");
fclose(fp);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
'''تشریح :''' ابتدا فایل سرآیند stdio را ضمیمه برنامه خود نمودهایم تا از ماکروها و تابعهای کتابخانهای استاندارد تعریف شده در آن استفاده کنیم . سپس داخل تابع اصلی برنامه main که پارامتری ندارد یک فایل را با نام fp آماده استفاده نمودهایم . موجودی fp توسط تابع کتابخانهای fopen که در فایل سرآیند stdio تعریف شده است یک فایل متنی به نام mytext می باشد که داخل آدرس home و نام کاربری خودم lovelorn می باشد ( این نام توسط شما در سیستم عامل لینوکس تعریف می شود ) که متعلق به سیستم عامل GNU/Linux می باشد شما در ویندوز می توانید بنویسید :
{{چپچین}}
"D:/myapp/mytext.txt"
{{پایان چپچین}}
که در حالت w یعنی نوشتن قرار دارد و فایلی به نام mytext را با فرمت txt در آدرس ذکر شده ایجاد می کند . سپس توسط تابع fprintf سرنام file print formatted به معنی چاپ فرمت شده فایل که هنوز به آن نرسیدهایم اما همان طور که اشاره شد جهت نوشتن در فایل می باشد ، نام فایل را ذکر کرده و سپس توسط تعیین کننده فرمت تعیین کردهایم که یک رشته را میخواهیم بنویسیم و سپس string به معنی رشته را به آن فرستادهایم که می توانستیم نام یک متغیر تعریف شده را نیز نویسیم که باید یک رشته می بود که داخل متنی موجود وجود داشت . سپس فایل fp را توسط تابع کتابخانهای fclse بستهایم تا فضای اشغال شده توسط فایل fp در حافظه موقت RAM آزاد شود . سپس تابع main با موفقیت به پایان می رسد
== تابع fprintf ==
تابع کتابخانهای fprintf سرنام file print formatted به معنی چاپ فرمتشده فایل متنی را از برنامه دریافت نموده و در جریان فایل می نویسد . شکل کلی ایجاد تابع fprintf به صورت زیر است :
{{چپچین}}
fprintf(FILE * stream, const char * format-string, argument list);
{{پایان چپچین}}
ابتدا نام جریان فایل را نوشته ؛ سپس تعیین کنندههای فرمت را به همراه متن دلخواه ( که ضروری نیست ولی می توانید بنویسید ) می نویسیم و سپس آرگومانهایی که به تابع فرستاده می شوند تا جایگزین تعیین کنندههای فرمت شوند را می نویسیم
مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
char str[] = "Hello World!\n";
FILE * fp;
fp = fopen("mytext.txt", "w");
fprintf(fp, "%s", str);
fclose(fp);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در مثال بالا رشته str جمله !Hello World را به همراه یک شکستن خط در خود ذخیره نموده و تعریف شده است . سپس فایل fp را آماده ایجاد نمودهایم . فایل fp توسط تابع کتابخانهای fopen با نام mytext در آدرس برنامه نوشته خواهد شد ( در صورتی که وجود نداشته باشد ساخته خواهد و در صورت وجود ، متن آن بازنویسی خواهد شد و همان طور که در مطلب پیشین گفتیم می توانید آدرس را هم بنویسید . تابع کتابخانهای fprintf که مطلب فعلی می باشد تابع fp را هدف قرار داده و یک رشته را پذیرا می باشد که رسته همان str با موجودی و مقدار !Hello World و یک شکستن خط می باشد . در پایان با تابع کتاخانهای fclose که در مطلب پیشین نوشتیم ، فایل fp زا می بندیم و فضای اشغال شده توسط آن را آزاد می نمائیم و تابع main با موفقیت به اتمام رسیده است . حالا شما می توانید فایل mytext.txt را در جایی که برنامه خود را نوشته و کامپایل نمودهاید بیابید که داخل همان متن نوشته شده به همراه یک خط شکسته در آن موجود می باشد . ضمناً تابع fprintf در صورت عملکرد موفقیتآمیز تعداد بایتهای نوشته شده را باز میگرداند و در صورت عدم موفقیت یک عدد منفی را باز میگرداند
'''نکته :''' تعیین کنندههای فرمت در fprintf همانند printf می باشند
== تابع fscanf ==
تابع fscanf سرنام file scan formatted به معنی اسکن فرمتشده فایل جهت خواندن دادهها از جریان فایل می باشد که دادهها را داخل متغیرهای آرگومانهای فرستاده شده به خود ذخیره می نماید . شکل کلی ایجاد تابع fscanf به صورت زیر می باشد :
{{چپچین}}
fscanf(FILE * stream, const char * format-string, argument-list);
{{پایان چپچین}}
ابتدا نام جریان فایلی را که قرار است خوانده شود می نویسیم ، سپس تعیین کنندههای فرمت را و سپس در پایان آرگومانهایی که قرار است جایگزین تعیین کنندههای فرمت شوند را به تابع می فرستیم
مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
char str1[10], str2[10];
float euler;
FILE * fp;
fp = fopen ("mytext.txt", "r");
fscanf(fp, "%s %s %f", str1, str2, &euler);
printf("The text in file is : %s %s %f\n", str1, str2, euler );
fclose(fp);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
ما سند و فایلی را به نام mytext.txt در آدرس و جایی که برنامه قرار دارد ایجاد نمودهایم و داخل آن نوشتهایم : Hello World! 2.71 سپس در برنامه خود ۲ رشته با نامهای str1 و str2 اعلان نمودهایم ؛ همین طور یک عدد اعشاری با نام اویلر . سپس یک فایل را با نام fp آماده استفاده نمودهایم و سپس با تابع کتابخانهای fopen فایل mytext.txt را جهت خواندن باز نمودهایم . تابع کتابخانهای fscanf که مطلب فعلی ماست فایل fp را اسکن می کند و داخل آن به دنبال ۲ رشته و یک عدد اعشاری می گردد که داخل str1 و str2 و euler ذخیره می کند . '''دقت کنید''' که رشتهها جهت دریافت شدن نیازی به عملگر آدرسدهی ( یعنی همان علامت امپرسند & ) ندارند اما جهت دریافت عدد در مثال نیز از آن استفاده نمودهایم که ضروری می باشد . سپس آنچه که در فایل mytext.txt خوانده شده است در خروجی خطدستوری نمایش داده می شود که اولین رشته Hello و دومین رشته !World و عدد اعشاری ما عدد اویلر با دقت ۲ رقم اعشار یعنی ۲٫۷۱ می باشد . در پایان نیز فایل را بسته و تابع را با موفقیت به پایان می رسانیم . مقداری که تابع fscanf باز می گرداند مقدار و تعداد دادههایی است که خوانده است ؛ اگر کمتر از دادههای داخل فایل باشد با مشکلی رو به رو شده است تا جایی که این مقدار می تواند 0 باشد ؛ اما اگر به کلی فایل را نتواند بخواند مقدار EOF را باز خواهد گرداند . '''دقت کنید''' که تعیین کنندههای فرمت در fscanf همانند scanf می باشند
== تابع getc ==
تابع کتابخانهای getc سرنام get character به معنی کاراکتر را بگیر همانند getchar می ماند اما به جای گرفتن کاراکتر از ورودی استاندارد ( صفحهکلید keyboard ) کاراکتر را از فایل می گیرد . شکل کلی ایجاد تابع getc بدین صورت می باشد :
{{چپچین}}
getc(FILE * Stream)
{{پایان چپچین}}
تابع getc از یک فایل کاراکتری را دریافت کرده و به اولین کاراکتر بعدی می رود . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
FILE * fp;
int ch;
fp = fopen("mytext.txt", "r");
ch = getc(fp);
while(ch != EOF)
{
putchar(ch);
ch = getc(fp);
}
putchar('\n');
fclose(fp);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
ابتدا فایل mytext را برای خواندن باز می کنیم ، داده صحیح ch با تابع کتابخانهای getc فایل را دریافت می کند و اولین کاراکتر آن را در ch ذخیره کرده و به سراغ کاراکتر بعدی می رود . سپس توسط حلقه while تا زمانی که به پایان فایل نرسیده کاراکتر(های) داخل فایل را نمایش داده و بعد دوباره کاراکتر بعدی را می گیرد . در پایان نیز خط را شکستهایم . که فایل تغییر نکرده و خروجی آن همان 2.71 !Hello World می باشد . تابع getc کاراکتری را که خوانده به صورت یک کاراکتر بدون علامت unsigned char که نقش یک صحیح int را ایفا می کند باز می گرداند و به کاراکتر بعدی در جریان فایل اشاره می کند . در صورت رسیدن به پایان فایل EOF را باز می گرداند و یا اگر مشکلی وجود داشته باشد یک خطا را باز می گرداند که می توان با تابعهای کتابخانهای feof و ferror آن را از هم تشخیص داد و خطای بازگردانده شده را دریافت نمود تا خطا را برطرف کرد . فایل را بسته و تابع اصلی برنامه را با موفقیت به پایان می رسانیم
== تابع putc ==
تابع putc همانند putchar میباشد و سرنام put character است جز اینکه کاراکتر دریافت شده را اخل یک فایل قرار می دهد و منتظر کاراکتر بعدی می ماند تا وارد شود و آن را داخل فایل قرار دهد . شکل کلی ایجاد تابع putc بدین صورت است :
{{چپچین}}
putc(int ch, FILE * stream);
{{پایان چپچین}}
تابع putc یک مقدار کاراکتری را که می تواند از نوع صحیح و یا کاراکتر باشد دریافت نموده و داخل جریان فایل می نویسد . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
FILE * fp;
char ch;
char brkline = '\n';
fp = fopen("alphabet.txt", "w");
for(ch='A'; ch<='Z'; ch++)
{
putc(ch, fp);
putc(brkline, fp);
}
fclose(fp);
printf("The Operation Has Finished Successfully !\n");
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در مثال بالا فایلی را با نوع داده FILE به نام fp آماده ایجاد شدن می نمائیم . یک کاراکتر با نام ch را اعلان نموده و کاراکتر brkline را با شکستن خط تعریف می کنیم . سپس با تابع کتابخانهای fopen فایل alphabet.txt به معنی الفبا را برای نوشته شدن می سازیم . با حلقه for از جایی که ch مقدار A دارد تا جایی که مقدار آن به Z برسد ch یک واحد یک واحد افزایش می یابد و به سراغ کاراکتر بعدی می رود . تا putc مقدار ch در فایل مد نظر چاپ می کند و سپس دوباره همین تابع مقدار خط شکسته را وارد می کند تا حروف الفبای انگلیسی در خطوط مجزا در فایلی با نام alphabet در دایرکتوری و فولدری که برنامه قرار دارد ایجاد شده و ذخیره گردند . سپس فایل را می بندیم و در پایان با تابع printf در خروجی خطدستوری چاپ نمودهایم عملیات با موفقیت به پایان رسید .
تابع putc در صورت موفقیتآمیز بودن عملیات خود کاراکتری را که نوشته است باز میگرداند و در صورت عدم موفقیت مقدار EOF را باز میگرداند
== ماکروی مقدار NULL ==
مقدار تهی با تلفظ نُل که آن را نول می نویسیم NULL در فایلهای سرآیند stdio و stdlib و stddef و time و locale و string و wchar تعریف شده است و مقدار اشارهگری است که آن اشارهگر به مکانی غیر قابل دسترسی اشاره می کند تا اگر به اشتباه از آن اشارهگر در برنامه استفاده شد باعث توقف سیستم نشود . حتماً از مبحث اشارهگرها به یاد دارید که اگر اشارهگری را اعلان نمودید و آن را به شکلی تعریف نکردید که به متغیر یا تابع دیگری اشاره کند ، بهتر است آن را با دادن مقدار NULL تعریف کنید . طبق استاندارد عبارت ثابت ;int * ptr = 0 یک اشارهگر NULL است نام آن ( ptr ) دل به خواه است اما اگر یک متغیر صحیح اشارهگر را مقدار 0 به آن بدهید همانند مقدار NULL خواهد بود و غیر قابل دسترسی است و در صورتی که بخواهید آدرس آن را به دست آورید یا در خروجی چاپ کنید و نمایش دهید آدرس آن غیر قابل دسترسی اعلام خواهد شد . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
int * iptr = NULL;
printf("%p\n", iptr);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در مثال بالا آدرس اشارهگر ptr غیر قابل دسترسی نمایش داده خواهد شد
طبق استاندارد مشخص نشده است که غیر قابل دسترسی بودن مقدار NULL در کامپایلر و پیادهساز باید چگونه باشد اما مقدار آن :
{{چپچین}}
((void *)0)
{{پایان چپچین}}
تعریف شده است . شما علاوه بر دادن مقدار تهی به اشارهگر در برنامههای بزرگ خود میتوانید در دستور شرطی if بررسی کنید که اشارهگر شما به جایی اشاره کرده است یا خیر که می نویسید if (ptr == NULL) بدین ترتیب مشخص می شود که اشارهگر ptr به جایی اشاره کرده و آدرسی دارد یا خیر . همچنین در ساخت دادههای درختی و لیست پیوندی باید آخرین مقدار آن را تهی تعیین کنید تا پایان دادهها را تعیین کنید
== تابع fputc ==
تابع fputc سرنام file put character همانند putc میباشد و یک کاراکتر را داخل فایل تعیین شده می نویسد و منتظر کاراکتر بعدی می ماند تا آن را وارد کند ( به محل بعدی اشاره می کند ) جز اینکه putc به نحوی در فایل سرآیند تعریف میشود که در هر بار فراخوانی ، فایل فرستاده شده به خود را دوباره می خواند و این مورد در نوشتن برنامه به صورت غیر حرفهای می تواند باعث ایجاد باگ ، مخصوصاً باگ امنیتی و رخنهپذیری شود در حالی که fputc اینگونه نیست و امن می باشد ؛ ضمن اینکه fputc را می توانید به عنوان آرگومان به یک تابع دیگر بفرستید و همچنین فضای حافظه موقت کمتری اشغال می کند ولی fputc کمی کندتر از putc می باشد . شکل کلی ایجاد تابع fputc بدین صورت می باشد :
{{چپچین}}
fputc(int ch, FILE * fp);
{{پایان چپچین}}
ch نام مقداری است که کاراکتر متناظر آن در ازکی ( ASCII ) توسط شما تعیین می شود تا در فایل نوشته شود . همچنین شما می توانید یک کاراکتر را تعریف کنید و به آن بفرستید تا آن را در فایل بنویسد . تابع fputc در صورت عملکرد موفقیتآمیز مقداری را که نوشته است باز می گرداند و در صورت بروز خطا مقدار EOF را می فرستد ؛ همچنین جهت اشکالزدایی مقادیر دیگری را می فرستد که با تابعهای کتابخانهای دیگر stdio همانند بسیاری از تابعهای کتابخانهای ، خطا را در آن بر طرف کنید . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main ()
{
FILE *fp;
int ch;
int nl = 10;
fp = fopen("alphabet.txt", "w+");
for( ch = 65 ; ch <= 90; ch++ )
{
fputc(ch, fp);
fputc(nl, fp);
}
fclose(fp);
return(0);
}
</syntaxhighlight>
{{پایان چپچین}}
همین برنامه را به صورت زیر نیز می توانیم بنویسیم :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main ()
{
FILE *fp;
char ch;
char nl = '\n';
fp = fopen("alphabet.txt", "w+");
for( ch = 'A' ; ch <= 'Z'; ch++ )
{
fputc(ch, fp);
fputc(nl, fp);
}
fclose(fp);
return(0);
}
</syntaxhighlight>
{{پایان چپچین}}
تشریح این برنامهها تکرار مکررات در همین صفحه است و واضح است که برنامه چگونه عمل می کند ، فقط در اولین قطعه کد مقدار ۶۵ تا ۹۰ کاراکترهای A تا Z در ازکی می باشند و مقدار ۱۰ کاراکتر خط شکسته که در هر بار اجرای حلقه for یک کاراکتر از حروف الفبای انگلیسی و یک کاراکتر خط شکسته نوشته می شود و در دومین قطعه کد دیگر کاراکتر ها را نوشتهایم و نه مقدار آن را
== تابع fgetc ==
تابع fgetc سرنام file get character به معنی کاراکتر را از فایل بگیر همانند getc می باشد و یک کاراکتر را از فایل دریافت می نماید و منتظر کاراکتر بعدی می ماند تا دریافت شود ؛ جز اینکه getc به عنوان یک ماکرو در فایل سرآیند stdio تعریف شده است و با هر بار فراخوانی ، فایل فرستاده شده به خود را دوباره می خواند و اگر کد به درستی نوشته نشود باعث ایجاد باگ مخصوصاً باگ امنیتی و رخنهپذیری می شود ؛ در حالی که fgetc اینگونه نیست و امن می باشد . fgetc را می توانید به عنوان یک آرگومان به تابع دیگری بفرستید و فضای حافظه کمتری را اشغال می کند اما چون fgetc به صورت یک تابع در stdio تعریف شده است کمی کندتر از getc می باشد . شکل کلی ایجاد تابع fgetc بدین صورت می باشد :
{{چپچین}}
fgetc(FILE * stream);
{{پایان چپچین}}
یک فایل را به fgetc می فرستید تا از اولین کاراکتر آن شروع به خواندن کند و منتظر کاراکتر بعدی بماند و به آن اشاره کند تا در ادامه اگر باز هم فراخوانده شد آن را نیز دریافت نماید . تابع fgetc در صورت موفقیتآمیز بودنِ عملکرد خود ، کاراکتری را که خوانده است مقدار عددی صحیح آن را باز می گرداند و در صورت عدم موفقیت EOF را باز می گرداند که با تابعهای feof و ferror که تابعهای تعریف شده در stdio هستید می توان پی برد که فایل به پایان رسیده یا خطایی وجود دارد . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main ()
{
FILE *fp;
int ch;
fp = fopen("alphabet.txt", "r");
ch = fgetc(fp);
while(ch != EOF)
{
putchar(ch);
ch = fgetc(fp);
}
fclose(fp);
return(0);
}
</syntaxhighlight>
{{پایان چپچین}}
'''توضیح برنامه :''' برنامه یک متغیر از نوع صحیح با نام ch دارد که مقدار آن تابع fgetc با دریافت فایل fp می باشد که اولین کاراکتر فایل alphabet.txt را می خواند ( فایلی که در برنامه قبلی ایجاد کردیم که حروف الفبا را نوشت ) و سپس تا زمانی که ch به آخر فایل نرسیده است ch که کاراکتر alphabet.txt است را بر روی خروجی خطدستوری نمایش داده و سپس دوباره fgetc کاراکتر بعدی را می خواند و در خود ذخیره می کند و در پایان فایل را بسته و تابع اصلی را با موفقیت به پایان رساندهایم
== تابع fputs ==
تابع کتابخانهای fputs سرنام file put string به معنی رشته را در فایل قرار بده یک رشته از کاراکترها را داخل جریان داده و معمولاً فایل فرستاده شده به آن ، می نویسد . شکل ایجاد تابع fputs بدین صورت می باشد :
{{چپچین}}
fputs(const char * str, FILE * stream);
{{پایان چپچین}}
ابتدا یک فایل را آماده ایجاد می کنیم سپس آن را باز کرده و نامی برای آن انتخاب می کنیم و بعد به کمک fputs متنی را داخل آن می نویسیم و سپس فایل را می بندیم تا فضای اشغال شده آزاد شود .ضمناً تابع fputs در صورت موفقیتآمیز بودن عملکرد خود یک مقدار غیر منفی را می فرستد و در صورت خطا EOF را و البته مقادیر دیگری که می توانید توسط ferror و دیگر تابعهای خطا یاب ، خطای آن را بیابید و بر طرف کنید که در ادامه می نویسیم . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main ()
{
FILE *fp;
fp = fopen("mytext.txt", "w");
fputs("Hello World!\n2.71", fp);
fclose(fp);
return(0);
}
</syntaxhighlight>
{{پایان چپچین}}
'''توضیح :''' همان طور که نوشته شد ، فایلی را آماده کردهایم تا ایجاد شود ( fp ) سپس آن را جهت نوشتن ایجاد نمودهایم ( mytext.txt ) و با تابع کتابخانهای fputs در آن نوشتهایم :
!Hello World<br>
2.71
و البته اگر دقت کنید این بار در ایجاد نوشته و رشته ، خط را شکستهایم . حال اگر با یک پیرایشگر متن ، فایل ایجاد شده را باز کنید ، متن را داخل آن ، مشاهده خواهید نمود
== تابع fgets ==
تابع fgets سرنام file get string به معنی رشته کاراکترها را از فایل بگیر ، جهت دریافت یک خط از متن فایل داده شده می باشد . شکل کلی ایجاد تابع fgets بدین صورت می باشد :
{{چپچین}}
fgets(char * str, int limit number, FILE * Stream);
{{پایان چپچین}}
تابع نام یک رشته را دریافت می کند ، سپس تعداد محدودیت تعداد کاراکترهای دریافتی را می نویسیم و سپس ورودی جریان داده که معمولاً جریان فایل است . تابع تا زمانی که به خط شکسته یا تعداد محدود کننده نوشته شده نرسیده باشد ، فایل را می خواند و آن را ذخیره می کند . تابع fgets در صورت داشتن عملکرد موفقیتآمیز ، یک اشارهگر را به رشته خود باز می گرداند و در صورت رسیدن به پایان خط یا خطا در عملکرد یک مقدار نول NULL را می فرستد که با feof می توان فهمید که به پایان رسیده است یا خیر و در صورت خطا می توان با تابع ferror خطای آن را پیدا نمود . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main ()
{
FILE *fp;
fp = fopen("mytext.txt", "r");
char str[20];
fgets(str, 20, fp);
puts(str);
fclose(fp);
return(0);
}
</syntaxhighlight>
{{پایان چپچین}}
توضیح : در صورت کامپایل قطعه کد بالا و اجرای آن تنها !Hello World را از فایل mytext.txt در خروجی خطدستوری خواهیم دید ، چرا که 2.71 در خط بعدی و بعد از شکسته شدن خط وجود دارد . فایل mytext.txt ابتدا آماده و سپس برای خوانده شدن باز شده . آرایه کاراکتری str با ۲۰ عنصر ، اعلان شده است . تابع fgets فایل mytext.txt را باز نموده و از آن ۲۰ کاراکتر خط اول را می خواند و در str ذخیره می کند و سپس توسط تابع puts این رشته در خروجی خطدستوری نمایش داده می شود و سپس فایل بسته شده و تابع اصلی ، با موفقیت به پایان می رسد
برای اینکه به صورت مطمئن از fgets متنی را از ورودی استاندارد دریافت کنید باید به شکل زیر عمل کنید ( چرا که با زدن دکمه ورود Enter یا همان Return داخل صفحهکلید ) کاراکتر خط شکسته را به متن اضافه می کند که در صورتی که بخواهید دستوری را بدهید یا نام فایلی را وارد کنید دچار مشکل خواهید شد . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
fgets(filename, 200, stdin);
filename[strcspn(filename, "\r\n")] = 0;
</syntaxhighlight>
{{پایان چپچین}}
'''توضیح :''' تابع fgets داده یا فایلی را با نام filename دریافت میکند که تعداد آن نهایتاً ۲۰۰ تا است و از ورودی استاندارد ، یعنی صفحهکلید ، داده را وارد میکنیم . سپس تابع strcspn که در فایل سرآیند string تعریف شده است هر جا ورودی به خط جدید ( در ویندوز ) و البته خط شکسته ( در تمام سیستم عاملها ) را پیدا کند ، آن را خالی کرده و حذف می کند
== ماکروی نوع داده size_t ==
ماکروی نوع داده size_t سرنام size type به معنی « اندازه نوع » ، اندازه اشیائی همچون آرایهها ، بلوکهای حافظه ، ساختمانها و رشتهها را به بایت در خود ذخیره می کند . اندازه size_t هرچه که باشد منفی نیست . اندازه size_t در C99 شانزده بیت تعریف شد و در حال حاضر حداکثر مقدار ذخیره شده در کامپایلرها و سیستمهای ۳۲ بیتی قدیمی ۲ بایت و در سیستمهای ۶۴ بیت با کامپایلرها و سیستمهای قدیمیتر ۴ بایت و در سیستمهای جدید ۸ بایت است یعنی به اندازه یک int یا یک long long int بدون علامت . اندازه size_t توسط عملگر sizeof به دست میآید . استفاده از size_t به تخصیص حافظه پویا کمک می کند . ضمناً size_t علاوه بر فایل سرآیند stdio در فایلهای سرآیند stddef و stdlib و string و time و wchar تعریف شده است . '''نکته :''' وقتی می خواهید اندازه شیئای را به دست بیاورید بهتر است از size_t استفاده کنید ؛ همچنین برای تعریف اندازههای بزرگ ، جهت قابل حمل بودن برنامه خود بهتر است از size_t استفاده کنید
مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main()
{
int array[5] = { 1, 2, 3, 4, 5 };
size_t size = sizeof(array);
printf("The size of the array is: %zu\n", size);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
'''توضیح :''' در تابع اصلی برنامه ، یک آرایه صحیح به نام array تعریف نمودهایم که ۵ عنصر دارد و هر صحیح ( int ) در سیستمهای ۶۴ بیتی ۴ بایت است . سپس یک نوع داده size_t با شناسه و نام size تعریف نمودهایم که مقدار آن مقدار array است . سپس در تابع printf در خروجی خطدستوری ، چاپ کردهایم اندازه آرایه مورد نظر به اندازه size می باشد که این کار را با تعیینکننده فرمت z به همراه u که سرنام unsigned می باشد نوشته و آرگومان size را به آن فرستادهایم تا جایگزین شود . در پایان ، تابع اصلی برنامه با موفقیت به پایان می رسد و در صورت کامپایل و اجرای برنامه با اندازه آرایه ۲۰ است ، مواجه خواهیم شد ( ۵ عنصر که هرکدام ۴ بایت را اشغال می کند )
'''دقت کنید :''' در تعاریف استانداردهای قدیمیتر مثل C98/C99 ماکروی نوع داده size_t طوری تعریف شده است که تعیینکننده فرمت آن d یا ul یا ull است و نه zu . بنابراین در هنگام نوشتن کد دقت کنید که کامپایلر شما با چه استانداردی ، مطابقت دارد
== تابع fread ==
تابع fread سرنام file read به معنی « فایل را بخوان » فایل فرستاده شده به خود را به تعدادی که تعیین کردهایم و تعداد بایتهایی که باید یکجا خوانده شوند ، در یک متغیر اشارهگر که عموماً باید یک آرایه باشد ذخیره می کند . شکل کلی ایجاد تابع fread بدین صورت می باشد :
{{چپچین}}
fread(void * buffer, size_t size, size_t count, FILE * stream);
{{پایان چپچین}}
فایل stream به تعداد count و اندازه هر یک بلوک از بایتهای size در buffer ذخیره می شود . تابع fread در صورت موفقیتآمیز بودنِ عملکرد خود ، تعداد نوشتههای خود ( count ) را باز می گرداند ولی در صورتی که از تعداد count کمتر شود یعنی خطایی رخ داده و یا به پایان فایل رسیدهایم ( EOF ) . اگر size و یا count را 0 بنویسید تابع مقدار 0 را باز میگرداند اما اختلالی در جریان فایل و یا دادههایی که فرستادهایم ایجاد نمی شود و برنامه به ادامه خود می پردازد . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
FILE * fp;
char buf[100];
fp = fopen ("alphabet.txt", "r");
fread(buf, 1, 100, fp);
printf("%s\n", buf);
fclose(fp);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در مثال بالا ابتدا فایل fp را آماده ایجاد نمودهایم . بعد از آن ، رشته ۱۰۰ کاراکتری buf را اعلان نمودهایم . سپس فایل fp را تعیین کردهایم تا توسط تابع fopen برای خوانده شدن باز شود که همان فایل alphabet.txt می باشد . تابع fread صد بایت را دانه به دانه ( چون برای size نوشتهایم 1 ) از فایل fp می خواند و در buf ذخیره می کند . سپس تابع printf آن را در خروجی خطدستوری چاپ می کند که همان حروف الفبای انگلیسی است . سپس فایل را بسته و تابع با موفقیت به اتمام می رسد
در نظر داشته باشید که fread قابلیت خواندن فایلها را به صورت عددی نیز دارد و یکی از مهمترین تابعهای کتابخانهای زبان سی C برای خواندن فایلها به صورت عددی می باشد . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main()
{
FILE * fp = fopen("/home/lovelorn/Pictures/post-3.jpeg", "rb");
unsigned char n;
for (int i = 0; i < 100; i++)
{
fread(&n, 1, 1, fp);
printf("%d\n", n);
}
fclose(fp);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در مثال بالا فایل post-3.jpeg از قالب و فرمت JPEG را به صورت عددی باز نمودهایم ( شما میتوانید هر فایلی را که داخل سیستم خود دارید قرار داده و آدرس بدهید ) سپس متغیر کاراکتری بدون علامت n را اعلان نمودهایم تا یک بایت جا را در خود بگیرد . پس از آن با یک حلقه for صد بار تابع fread را فراخواندهایم تا از فایل مورد نظر یک بار یک بایت را بخواند و آن را در n ذخیره کند ؛ دقت کنید که بافر باید یک اشارهگر باشد و چون n اشارهگر نیست ، با عملگر آدرسدهی ، در آن مقادیر را ذخیره کرده و سپس توسط تابع printf در خروجی خطدستوری چاپ نمودهایم . دقت کنید که شما درصورتی که هر واحد را ۴ بایت تعریف کنید هر ۴ بایت یک عدد خوانده می شود و در سیستمهای ۳۲ بیتی قدیمی باید تعیین کننده فرمت lu را بنویسید و در صورتی که داده شما ۸ بایتی باشد که آن را بدون علامت تعیین کنید از فرمت llu و در غیر این صورت با خطای نااندازه بودن حافظه مواجه خواهید شد ( که البته همان طور که در پائین نوشتهایم شما باید دادهها را تبدیل کنید ) . در پایان ، فایل مورد نظر خود را بسته و تابع اصلی برنامه را با موفقیت به پایان می رسانیم . در صورتی که با موفقیت برنامه بالا را کامپایل و اجرا کنید با اعداد ۲۵۵ ، ۲۱۶ ، ۲۵۵ و ... ( وابسته به نسخه استاندارد JPEG ) مواجه خواهید شد ( دقت کنید که اکر تعیینکننده فرمت خود را X بنویسید همانند یک هگزادسیمال ادیتور مقادیر برای شما شانزده شانزدهی و به عبارت دیگر در مبنای ۱۶ نوشته خواهد شد )
'''دقت کنید :''' تابع fread به صورت ویژه برای خواندن فایلها به صورت عددی می باشد و اگر بخواهید یک فایل متنی را عددی بخوانید به مشکلاتی بر می خورید و بهتر است از fscanf و sscanf و یا gets استفاده کنید . همچنین تابع fread مقادیر عددی را که به آن می فرستیم و بزرگتر از ۱ بایت ( برای هر حجم size ) باشد در سیستمهای اندین کوچک ( لیتل اندین Little Endian ) از راست به چپ می خواند و اگر آن را چاپ کنید با عدد برعکس شده ۰ و ۱ آن رو به رو خواهید شد . جهت رفع این مشکل در سیستم عاملهای شبهیونیکس و البته ویندوز تابع ntohs سرنام network to host system به معنی عدد شبکه را به سامانه ( سیستم ) میزبان تبدیل کن ، موجود می باشد ( در شبکه ، اعداد ، اندین بزرگ یا همان بیگ اندین Big Endian هستند ) تا قبل از چاپ نمودن عدد آن را بر عکس کنید تا درست خوانده شود ولی تابع استانداردی برای این کار وجود ندارد
در سیستم عاملهای شبهیونیکس و با رابط پازیکس ( POSIX ) می توانید برنامه را همانند برنامه زیر بنویسید :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
#include <arpa/inet.h>
int main()
{
FILE * fp = fopen("/home/lovelorn/Pictures/post-3.jpeg", "rb");
unsigned short n;
unsigned short rev;
for (int i = 0; i < 100; i++)
{
fread(&n, 2, 1, fp);
rev = ntohs(n);
printf("%d\n", rev);
}
fclose(fp);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
'''دقت کنید :''' گنجایش ntohs فقط ۲ بایت است و چک کنید که در سیستم شما هم short فقط ۲ بایت جا اشغال می کند . اگر در سیستمهای ۳۲ بیتی قدیمی هستید int هم ۲ بایت است . همچنین این مشکل در سیستمهای اندین کوچک ( لیتل اندین Little Endian ) مثل معماریهای x86 یا بعضاً ARM ( که در گذشته دو اندینه بود و در حال حاضر اندین کوچک است ) وجود دارد و در سیستمهای اندین بزرگ ( بیگ اندین Big Endian ) وجود ندارد . از سویی برخی از سیستمها فایل سرآیند netinet/in.h را به جای arpa/inet.h برای استفاده از ntohs نیاز دارند و باید آن را ضمیمه برنامه خود کنید و همچنین در ویندوزهای قدیمی تا نسخه ۸.۱ فایل سرآیند winsock.h و در ویندوزهای جدید باید Winsock2.h را ضمیمه فایل برنامه خود کنید
'''توضیح :''' این برنامه همانند برنامه قبلی نوشته شده است با این تفاوت که نوع داده short را انتخاب نمودهایم که ۲ بایت است و یک متغیر دیگر rev مخفف reversed اعلان نموده و دادههای خود را با ntohs در آن ذخیره نمودهایم و سپس مقدار rev را در خروجی خطدستوری چاپ نمودهایم . اگر مقادیر فایل را ۲ بایت به ۲ بایت به مبنای ۱۰ تبدیل کنید خواهید دید که ارقام و مقادیر صحیح و درست هستند و دیگر برعکس نیستند
== تابع fwrite ==
تابع fwrite سرنام file write به معنی « فایل را بنویس » دادههای تحویل داده شده به تابع را داخل یک فایل می نویسد . شکل کلی ایجاد تابع fwrite بدین صورت می باشد :
{{چپچین}}
fwrite(const void * ptr, size_t size, size_t nmemb, FILE * fp);
{{پایان چپچین}}
یک داده اشارهگر به اندازه بلوکهای بایتی size و به تعداد nmemb در داخل فایل fp نوشته می شود . تابع fwrite در صورت موفقیتآمیز بودنِ عملکرد خود تعداد nmemb را باز خواهد گرداند و در غیر این صورت پیام خطایی را خواهد فرستاد که توسط تابع ferror می توانید ایراد را پیدا کرده و رفع کنید . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
FILE * fp;
int num[100];
int number;
fp = fopen("myfile.bin", "wb");
for (number = 0; number < 100; ++number)
{
num[number] = number;
}
fwrite(num, 4, 100, fp);
fclose(fp);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
'''توضیح :''' فایل fp آماده ساختن شده است . یک آرایه از نوع متغیر صحیح با ۱۰۰ عنصر و با نام num اعلان شده است . همچنین یک متغیر صحیح با نام number اعلان شده است . تعیین کردهایم که فایلی که می خواهیم به صورت عددی بنویسیم myfile.bin نام دارد و باید ساخته شود و یا بازنویسی شود . با یک حلقه for متغیر number به عنوان اندیس num از مقدار ۰ شروع کرده و تا ۹۹ ادامه می یابد و البته قبل از اجرای حلقه number یک بار افزایش خواهد یافت چون عملگر افزایش پیش از number نوشته شده است . num[0] مقداری نمی گیرد ، بنابراین توسط کامپایلر مقدار 0 را خواهد گرفت . در چهار بایت بعدی num[1] برابر مقدار 1 است و سپس 2 و الی آخر . تابع fwrite متغیر آرایهای num را که ۱۰۰ عنصر ۴ بایتی دارد را هر ۴ بایت به ۴ بایت ، ۱۰۰ بار در فایل fp که همان myfile.bin است می نویسد . سپس فایل را بسته و تابع main را با موفقیت به پایان می رسانیم . برای مشاهده نتیجه ، یک پیرایشگر فایل یا همان پیرایشگر هگزادسیمال ( Hex Editor یا همان Hexadecimal Editor ) نیاز دارید که برای تمام سیستم عاملها موجود است
== تابع ungetc ==
شکل کلی فراخواندن تابع کتابخانهای ungetc که سرنام unget character می باشد به معنی کاراکتر را نگیر بدین صورت است :
{{چپچین}}
ungetc(int ch, FILE * fp);
{{پایان چپچین}}
تابع ungetc بر خلاف getc عمل می کند و تضمین شده است که حداقل یک کاراکتر را که وارد یا خوانده شده است به جریان داده یا جریان فایل بفرستد تا آماده خواندن شود ( دقت کنید که برخی به کارگیرندهها تعداد بیشتری را می فرستند که به ترتیب عکس ذخیره می شود ، یعنی آخرین کاراکتر فرستاده شده ، اولین کاراکتر برای جریان داده یا جریان فایل است که خوانده شود ) همچنین ungetc تنها ورودی getc را به جریان داده و یا فایل باز نمی گرداند و شامل دیگر گیرندهها نظیر scanf نیز می شود . مهم است بدانید که کامپایلر ، کاراکتر تعریف شده توسط ungetc از نوع صحیح int را به نوع داده unsigned char تبدیل می کند . شما می توانید به جای نوشتن متغیری جهت فرستاده شدن به جریان ، یک کاراکتر نوشتاری را نیز بفرستید . نتیجه هر دو این است که زمانی که یک تابع بخواهد از جریان ورودی داده یا فایل ، کاراکتری را بخواند ، کاراکتر فرستاده شده از ungetc را جهت نوشتن به خروجی می فرستد . تابع ungetc در صورت موفقیتآمیز بودن عملکرد خود ، کاراکتری را که به جریان داده و یا فایل فرستاده است ، باز می گرداند و در غیر این صورت مقدار EOF را . اگر ch مقدار EOF را بگیرد ، تنها EOF را باز می گرداند که البته طبق استاندارد نباید به ungetc مقدار EOF را فرستاد . کاراکتری که شما با ungetc بازگشت می زنید برای جریان ، لازم نیست همان کاراکتری باشد که بار آخر ، توسط جریان خوانده شده است و در واقع ضرورتی ندارد که کاراکترهایی را از جریان داده بخوانید که قبل از آن توسط ungetc بازگشت خورده و خوانده نشدهاند . اما این کار در نوشتن برنامه تقریباً بیهوده و عجیب است . معمولاً از ungetc برای نخواندن یک کاراکتر که از همان جریان داده یا فایل برای خواندن استفاده شده ، استفاده می شود . شما مجاز به چند بار استفاده مکرر از ungetc به صورت پشت سر هم بدون تابعهای خواندن از ورودی استاندارد ( صفحه کلید Keyboard ) یا فایل نیستید . اما برخی به کارگیرندهها این اجازه را می دهند . بازگرداندن کاراکترها توسط ungetc فایل را تغییر نمی دهد . اگر از یک تابع جهت تغییر مکان خواندن فایل مثل fseek یا fseeko یا rewind یا حتی fflush ( که در ادامه خواهند آمد ) استفاده شود ungetc نادیده گرفته می شود . نخواندن یک کاراکتر توسط ungetc در فایلی که به انتهای خود رسیده ، علامت انتهای فایل را پاک می کند چون یک کاراکتر را جهت ورود آماده می کند ولی بعد از آنکه کاراکتر را خواندید اگر دوباره بخواهید بخوانید با انتهای فایل EOF مواجه خواهید شد . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include<stdio.h>
int main(void)
{
int ch = 0;
FILE * fr;
fr = fopen("alphabet.txt", "r");
while(ch != EOF)
{
ch = getc(fr);
putchar(ch);
ungetc(ch, fr);
printf("\n%c", ch);
break;
}
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
'''توضیح :''' یک متغیر که قرار است نقش یک کاراکتر را ایفا کنید با نام ch تعریف کردهایم . فایل fr را آماده ایجاد نمودهایم . سپس توسط تابع fopen فایل alphabet.txt را که در همین صفحه ایجاد کردیم ، چهت خواندن باز می کنیم . سپس حلقه while تا زمانی که به پایان فایل نرسیدهایم ch را توسط getc از فایل fr دریافت می کند و سپس آن را چاپ می کند . تابع ungetc آخرین کاراکتر خوانده شده را به جریان می فرستد . و بعد از آن با تابع printf یک بار خط را شکسته و آخرین مقدار باقیمانده در جریان را که همان A می باشد چاپ می کند . سپس حلقه را می شکنیم چرا که در صورتی که آن را نشکنیم ، مقداری که توسط ungetc به جریان ورودی می فرستد باقی می ماند و تا بی نهایت چاپ می شود A در صورتی که حالا فقط ۲ A در خطهای جداگانه داریم
'''نکته :''' اگر یک یا چند بار دیگر تلاش کنید تا ch را چاپ کنید باز هم با مقدار A رو به رو خواهید شد ؛ چرا که در ذخیرهگاه جریان داده یا فایل ، A ذخیره شده است و ungetc آن را به ذخیرهگاه ( buffer ) که در ادامه نوشته خواهد شد فرستاده است
== تابع fflush ==
شکل کلی فراخواندن تابع fflush سرنام file flush به معنی فایل را خالی کن بدین صورت می باشد :
{{چپچین}}
fflush(FILE * stream)
{{پایان چپچین}}
در کرنل سیستم عامل قسمتی وجود دارد که ذخیرهگاه جریان ورودی/خروجی دادهها و فایلها می باشد که به آن بافر Buffer گفته می شود . با بسته شدن فایل یا خروجی موفقیتآمیز برنامه خود به خود بافر ، تخلیه می شود اما گاهی ممکن است برنامه دچار اشکال شود و متوقف گردیده و بدین صورت فایل نوشته نشود . در این صورت ، اگر شما از تابع کتابخانهای fflush استفاده کرده باشید ، فایل بر روی دیسک و یا خروجی استاندارد نوشته خواهد شد . در استاندارد C تابع fflush برای ورودی ، تعریف نشده است ( و فقط برای خروجی فایل است ) ولی برخی از پیادهسازها از آن پشتیبانی می کنند . اما قبل از اینکه برای ورودی از آن استفاده کنید ، راهنمای کامپایلر خود را مطالعه کنید ؛ چرا که ممکن است با یک رفتار تعریفنشده مواجه شوید . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main()
{
int c;
FILE * fr;
fr = fopen("alphabet.txt", "r");
c = getc(fr);
ungetc(c, fr);
c = getc(fr);
printf("Character read after ungetc: %c\n", c);
fflush(fr);
c = getc(fr);
printf("Character read after fflush: %c\n", c);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در مثال بالا یک کاراکتر از فایل الفبا یک بار خوانده می شود . سپس توسط ungetc به ذخیرهگاه ( بافر ) فرستاده می شود . دوباره کاراکتر را دریافت کرده و آن را در خروجی خطدستوری چاپ می کنیم . حالا از تابع fflush برای خالی کردن ذخیرهگاه استفاده می کنیم و بار دیگر از فایل می خوانیم و آن را در خروجی خطدستوری چاپ می کنیم که عملاً هیچ چیز نیست . چون ذخیرهگاه خالی شده است ( یعنی ungetc بی اثر شده است )
مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int * program_crash = 0;
int main(void)
{
FILE * fp;
fp = fopen("testfile.txt", "w");
printf("Enter a number : \n");
int num = 0;
scanf("%d", &num);
fprintf(fp, "The number is : %d\n", num);
fflush(fp);
*program_crash = 5;
fclose(fp);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در مثال بالا یک اشارهگر خالی تعریف نمودهایم . سپس فایلی را با نام testfile.txt به معنی فایل امتحانی با پسوند txt سرنام text به معنی متن ساده آماده نوشتن کردهایم . سپس در خروجی خطدستوری ، چاپ نمودهایم تا کاربر یک عدد را وارد کند . عدد را دریافت نموده و سپس توسط تابع fprintf در فایل مورد نظر نوشتهایم : The number is و سپس عدد وارد شده توسط کاربر را که همان num می باشد در فایل خواهیم نوشت به معنی عدد وارد شده شما اینقدر می باشد . پس از آن ذخیرهگاه را تخلیه نمودهایم تا هر آنچه در ذخیرهگاه فایل موجود است نوشته شود . سپس به اشارهگر program_crash مقدار غیر استاندارد 5 را دادهایم که مجاز به این کار نیستیم ( مراجعه شود به مبحث اشارهگرها در فصل دادهها ) و برنامه متوقف می شود . اما فایل ما با موفقیت نوشته شده است و شما می توانید آن را در یک پیرایشگر متن مشاهده کنید . تابع fflush در صورت موفقیتآمیز عمل کردن مقدار 0 را باز می گرداند و مقدار EOF نشانگر وجود یک اختلال است که موفقیتآمیز عمل نکرده است . با نوع داده ماکروی errno می توانید مقادیر اضافهتری دریافت کنید که نشان می دهد خطای ایجاد شده از کجاست تا آن را بر طرف کنید
'''نکته :''' پیام خطای Segmentation Fault که به نام Core Dump نیز معروف است زمانی رخ می دهد که بر روی حافظه ضروری کرنل بخواهیم چیزی بنویسیم و یا دادهای را وارد حافظه کنیم که اندازه آن بزرگتر از مقدار حافظه می باشد
== تابع remove ==
این تابع کتابخانهای ، همان طور که از اسمش پیداست فایلی را که به آن بفرستیم ، حذف می کند . شکل کلی ایجاد تابع remove بدین صورت می باشد :
{{چپچین}}
remove(const char* filename);
{{پایان چپچین}}
داخل جفت پرانتزهای باز و بسته تابع ، یک رشته می نویسیم که نام فایلی است که می خواهیم حذف شود . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
remove("testfile.txt");
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
حتماً به یاد دارید که یک فایل در دایرکتوری کامپایلر ( فولدر کامپایلر ) به نام testfile.txt ایجاد نمودیم . حال اگر برنامه بالا را بنویسید و آن را کامپایل کرده و اجرا کنید ، فایل مذکور حذف می شود . تابع remove در صورت موفقیتآمیز بودن عملکرد خود مقدار 0 را باز می گرداند و یک مقدار غیر 0 در صورت وجود اختلال . با استفاده از نوع داده ماکروی errno می توانید مقادیر اختلال و مشکل را دریافت نموده و اختلال را رفع کنید
== تابع rename ==
تابع کتابخانهای rename نیز همان طور که از نامش پیداست ، برای یک فایل یا دایرکتوری ( فولدر ) ، نام جدیدی را که به آن دستور دادهایم قرار می دهد و نام آن را عوض می کند . شکل کلی ایجاد تابع rename بدین صورت می باشد :
{{چپچین}}
rename(const char * oldfilename, const char * newfilename);
{{پایان چپچین}}
ابتدا نام فایلی را که موجود است می نویسیم و سپس نام فایل جدیدی را که قرار است پس از تعویض داشته باشد می نویسیم . این تابع ، در صورت عملکرد موفقیتآمیز خود مقدار 0 را باز می گرداند و در صورت اختلال مقدار دیگری را که البته با نوع داده ماکروی errno با مقدار بازگردانده شده ما می توانیم اختلال را بر طرف کنیم . دقت کنید که برخی پیادهسازها و سیستم عاملها به شما اجازه می دهند تا در صورتی که آدرسی دیگر ، نسبت به فایل موجود بنویسید ، آن را نام نویسی جدید نمایند و آن را انتقال دهند به دایرکتوری و آدرس داده شده در حالی که مابقی خطا می گیرند ؛ همین طور برخی اجازه می دهند تا اگر نامی که می خواهید بدهید در دایرکتوری موجود است آن را جایگزین فایل مشابه کنید و مابقی این اجازه را نمی دهند و خطا می گیرند . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main()
{
rename("oldfile.txt", "newfile.txt");
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
یک فایل متنی با نام oldfile ایجاد کرده و در صورت تمایل ، داخل آن ، متنی بنویسید و سپس برنامه بالا را نوشته و کامپایل کرده و اجرا کنید . نام آن به newfile.txt تغیییر پیدا خواهد نمود
== تابع fseek ==
تابع fseek سرنام file seek به معنی جستجو در فایل ، جهت اشاره به قسمت معینی از فایل است که بخواهیم در آن چیزی بنویسیم یا آن را بخوانیم . شکل کلی ایجاد تابع fseek بدین صورت می باشد :
{{چپچین}}
fseek(FILE * filepointer, long int offset, int position);
{{پایان چپچین}}
تابع fseek ابتدا اشارهگر فایل را پذیرا می باشد ؛ سپس باید تعداد جایگاهی که می خواهیم جا به جایی در فایل صورت بگیرد (offset) را می نویسیم و در پایان مقادیر از پیش تعیین شده ( position ) استاندارد فایل را می نویسیم که در هر دفعه فقط می تواند یکی از مقادیر زیر باشد :
{{چپچین}}
SEEK_SET
{{پایان چپچین}}
برای رفتن به ابتدای فایل
{{چپچین}}
SEEK_CUR
{{پایان چپچین}}
سرنام Seek Current که می شود همان جایی که فایل در حال استفاده بوده است ، به همان جا اشاره کند و فایل را آماده استفاده نماید
{{چپچین}}
SEEK_END
{{پایان چپچین}}
که به پایان فایل می رود
'''نکته :''' در صورتی که به ابتدای فایل بروید و بعد مقداری را بدهید که به عقب بازگردید ( یعنی عدد منفی بنویسید ) اجرای تابع ناموفق خواهد بود ؛ ضمناً اگر به انتهای فایل بروید و بخواهید مقداری بدهید که به جلوتر برود و دادههایی را بنویسید طبق استاندارد به انتهای فایل ، مقادیر تهی ( 00 در شانزده شانزدهی Hexadecimal ) و مقادیر متناظر در مبناهای دیگر به آخر فایل اضافه می شود
'''دقت کنید :''' بهتر است در صورتی که نمی خواهید عدد خیلی بزرگی که در نوع داده بلند long جا می شود را بنویسید حتماً از تعیین کننده نوع L جهت تعیین بزرگی عدد استفاده کنید و توصیه می شود حتی برای اعداد بزرگ نیز استفاده کنید تا دچار خطایی نشوید
تابع fseek در صورت موفقیتآمیز عمل کردن ، مقدار 0 را باز می گرداند و در صورت بازماندن از عملکرد درست ، مقدار غیر صفر را باز می گرداند
مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
FILE * fp = fopen("test.txt", "r");
fseek(fp, 5L, SEEK_SET);
char str[15];
fgets(str, 15, fp);
printf("%s\n", str);
fclose(fp);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
یک فایل متنی را با متن ! This is a test file ایجاد کنید ( در صورت تمایل از متن دیگری استفاده کنید ) و حتماً فایل را در دایرکتوری و یا فولدری که برنامه کامپایل می شود ذخیره کنید ؛ در غیر این صورت در باز کردن فایل ، آدرس آن را بنویسید . سپس قطعه کد بالا را در یک فایل با پسوند c ذخیره کرده و پس از کامپایل اجرا کنید . فایل test.txt جهت خوانده شدنِ متنی ، باز شده است . سپس تابع fseek به ابتدای فایل رفته و ۵ کاراکتر ( و در فایلهای دودویی ، بایت ) به جلو می رود . آرایه کاراکتری str که همان رشته می باشد با ۱۵ عنصر اعلان شده است . سپس توسط تابع fgets از رشته مورد نظر ۱۵ کاراکتر را از فایل fp که همان فایل test.txt می باشد خواندهایم و آن در در خروجی خطدستوری چاپ کردهایم . در پایان ، فایل خودمان را بستهایم . اگر این قطعه کد را کامپایل و اجرا کنید با متن ! is a file مواجه خواهید شد ( چرا که This چهار کاراکتر دارد و جلوی آن نیز یک فاصله خالی وجود دارد که می شود ۵ تا و ما ۵ کاراکتر در فایل ، جلو رفتهایم و کاراکترهای قبلتر خوانده نشدهاند )
== تابع ftell ==
تابع ftell سرنام file tell به ما جایی که در حال حاضر ، فایل تعیین شده ، قرار دارد ( برای نوشتن یا خواندن ) اعلام می کند . شکل کلی ایجاد تابع ftell بدین صورت می باشد :
{{چپچین}}
ftell(FILE * filepointer);
{{پایان چپچین}}
تابع ftell در صورت موفقیت آمیز بودن عملکرد خود ، شماره بایتی که فایل در حال استفاده است را باز می گرداند و در صورت عملکرد ناموفق مقدار منفی یک را یعنی 1- . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main ()
{
printf("Enter file name :\n");
char name[200];
scanf("%s", name);
FILE * fp;
fp = fopen(name, "rb");
fseek(fp, 0L, SEEK_END);
long size = ftell(fp);
printf("%ld\n", size);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در مثال بالا از کاربر خواستهایم تا نام فایل را وارد کند . آرایه کاراکتری name با ۲۰۰ عنصر اعلان شده تا نام فایل ، در آن ذخیره شود . با تابع scanf نام را از کاربر می گیریم . سپس ماکروی نوع داده FILE یک اشارهگر فایل را با نام fp آماده ایجاد شدن کرده است . با تابع fopen اشارهگر فایل fp فایلی را با نام name برای خوانده شدن دودویی ( باینری ) باز می کند . با تابع fseek به انتهای فایل می رویم و پیش روی نیز نمی کنیم ( 0L ) سپس چون نوع داده تاع ftell از نوع بلند long است یک داده بلند با نام size ایجاد نمودهایم تا وقتی به انتهای فایل رفتیم و جایگاه اشاره به فایل را بررسی نمودیم ، به این شکل ، اندازه ( size ) فایل را به دست بیاوریم . در پایان با printf همان اندازه را در خروجی خطدستوری ، چاپ نمودهایم . یکی از متداولترین استفادههای ftell میزان عملیات بر روی فایل است ؛ عملیاتی مثل کپی کردن . وقتی کپی می کنید مدام با حلقه هم می خوانید و هم هر چه نوشتید بررسی می کنید تا ببینید چند در صد فایل ، نوشته شده است ( نسبت به اصل فایل که می خواهید آن را کپی کنید و اندازه آن را به دست آوردهاید )
== تابع rewind ==
تابع کتابخانهای rewind به معنی بازگرد به ابتدا ، جهت بازگرداندن اشارهگر جریان فایل به ابتدای آن است . شکل کلی فراخوانی تابع rewind بدین صورت است :
{{چپچین}}
rewind( FILE * filepointer );
{{پایان چپچین}}
مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main()
{
FILE * fp;
fp = fopen("mytext.txt", "r");
int text;
while((text=fgetc(fp)) != EOF)
{
printf("%c", text);
}
rewind(fp);
text=fgetc(fp);
printf("Read character is : %c\n", text);
fclose(fp);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در مثال بالا ، فایل متنی mytext که قبلاً آن را ایجاد نمودیم ( با پسوند txt ) را جهت خواندن ، باز می کنیم . سپس یک صحیح با شناسه text اعلان نمودهایم تا با تابع fgetc تا زمانی که به انتهای فایل نرسیدهایم آن را بخوانیم و با تابع printf آن را در خروجی خطدستوری ، چاپ کنیم . سپس به ابتدای فایل برگشته ( توسط همین تابع ، یعنی rewind ) و یک کاراکتر را که اولین آن خواهد بود میخوانیم و آن را با printf در خروجی خطدستوری ، چاپ میکنیم که همان H است . سپس فایل را بسته و تابع اصلی برنامه ( main ) را با موفقیت به پایان می رسانیم
'''دقت کنید :''' تابع rewind هیچ مقداری را باز نمی گرداند ( چه در صورت موفقیت و چه در صورت وجود خطا ) و همچنین تمام دادههای پیدا کردن خطا در عملکرد آن و خواندن یا نوشتن فایل را پاک می کند . بنابراین توصیه می شود که برای بازگشتن به ابتدای فایل نیز همچنان از fseek استفاده کنید
== تابع ferror ==
تابع کتابخانهای ferror سرنام find error به معنی خطا را بیاب ، اگر در جریان داده فایل ، هنگام خواندن یا نوشتن ، خطایی رخ دهد مقداری را بازگردانده و نشانگر خطا را با مقداردهی ماکروی errno تعیین می کند تا برنامهنویس بتواند خطا را برطرف کند . تابع ferror در صورت موفقیتآمیز بودن عملکرد خود ( یعنی خطایی در جریان داده فایل موجود نباشد ) ، مقدار 0 را باز میگرداند و در غیر این صورت ( یعنی وجود خطا ) مقداری غیر 0 را باز خواهد گرداند . شکل کلی فراخوانی تابع ferror بدین صورت است :
{{چپچین}}
ferror(FILE * stream);
{{پایان چپچین}}
مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main()
{
FILE * fp;
fp = fopen("myexample.txt", "w");
if (fp == NULL)
{
printf("File doesn't exist\n");
return 1;
}
fputs("This is an example\n", fp);
fclose(fp);
fputs("This text won't be written on file\n", fp);
if (ferror(fp))
printf("Error during writing to file\n");
fp = fopen("myexample.txt", "a");
fputs("This will append to the end of file\n", fp);
if (ferror(fp))
printf("Error during writing to file\n");
else
printf("The writing operation was successful\n");
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در مثال بالا در هنگام کامپایل ، احتمالاً کامپایلر به شما هشدار خواهد داد که اشارهگر فایل ، پس از بسته شدن فایل ، مورد استفاده قرار گرفته است . اما این مثال ساده ، فقط جهت درک کارآمدی تابع ferror می باشد . '''توضیح :''' ابتدا با اشارهگرِ نوع داده FILE ، فایل fp را آماده ایجاد شدن نمودهایم . سپس fp فایلی متنی را با نام myexample.txt جهت ایجاد و نوشتن ، بازکرده است . چک کردهایم که اگر فایل به هر دلیلی موجود نیست ( NULL ) پیغام خطای فایل موجود نیست را در خروجی خطدستوری ، چاپ کند و برنامه با عدم موفقیت ، به اتمام برسد . سپس داخل فایل خود نوشتهایم This is an example یعنی این یک مثال است و خط را شکستهایم . سپس فایل را بستهایم و نوشتهایم This text won't be written on file یعنی این متن در فایل نوشته نخواهد شد ( چرا که فایل را بستهایم و دیگر نمیتوانیم در آن ، بنویسیم یا حتی آن را بخوانیم ) . سپس با دستور if چک کردهایم که اگر ferror مقداری دارد ( که یعنی خطایی رخ داده ) در خروجی خطدستوری ، چاپ کنید : خطایی در حین نوشتن در فایل وجود دارد . ( چون فایل ، بسته شده است ) که همین اتفاق ، رخ خواهد داد . سپس دوباره فایل را جهت اضافه نمودن ( a که همان طور که در بالاتر نوشتیم سرنام append است ) باز کردهایم و نوشتهایم : This will append to the end of file یعنی این متن در ادامه فایل ، اضافه خواهد شد . سپس دوباره با تابع ferror چک کردهایم که آیا خطایی وجود دارد یا خیر که در صورت وجود خطا چاپ کند : Error during writing to file یعنی در هنگام نوشتن در فایل ، خطایی رخ داده است و خط را بشکند اما خطایی وجود نخواهد داشت ( مگر اینکه فایل را پاک کنید یا قفل کنید یا سیستم عامل شما مخصوصاً در صورت آلوده بودن ، فایل را قفل کند ) و در غیر این صورت چاپ کند : The writing operation was successful یعنی عملیات نوشتن با موفقیت ، انجام شد . سپس برنامه با موفقیت به پایان می رسد
'''دقت کنید :''' در صورتی که چک نکنید اشارهگرِ فایل ، تهی است ( NULL ) و ferror با خطای NULL مواجه شود ، رفتاری تعریفنشده بروز خواهد داد و البته برخی کامپایلرها به جدای از استاندارد ، ماکروها و توابعی را در نظر گرفتهاند تا این خطا را شناسایی کرده و بر طرف کنید ولی بهتر است همیشه در ابتدا چک کنید که فایل موجود است و اشارهگرِ فایل ، تهی نیست
'''دقت کنید :''' تابع ferror خطای جریان داده آخرین فایل باز شده را بررسی کرده و نشانگر خطا را مقداردهی میکند و در صورتی که فایل را ببندید یا از تابع rewind یا تابع clearerr که به معنی خطا را پاک کن می باشد ، استفاده کنید نشانگر خطا خالی می شود ( تابع clearerr را در ادامه همین مبحث ، می نویسیم )
== ماکروی مقدار EOF ==
ماکروی مقدار EOF سرنام End Of File به معنی پایان سند یا همان فایل ، مقداری است که اگر بازگردانده شود ؛ یعنی تابع ( مثل getc یا fread ) جهت خواندن سند ، به انتهای آن رسیده است و یا بعضاً در همان تابعها خطایی در خواندن فایل ایجاد شده است . مقدار بازگردانده شده توسط EOF طبق استاندارد باید یک صحیح منفی باشد اما مقدار دقیق آن ، تعیین نشده است اما بسیاری از پیادهسازها ( کامپایلرها ) مقدار منفی یک 1- را باز میگردانند . برنامهنویسان میتوانند از ماکروی EOF جهت خواندن کامل و صحیح اسناد یا همان فایلها استفاده کنند که تا به همین جای مبحث چند بار از آن استفاده نمودهایم و شما نیز آنها را دیدهاید . ماکروی EOF هم در stdio تعریف شده است و هم در stdlib که موضوع بعدی کثاب است و فرقی با هم ندارند ( تعریف EOF )
مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include<stdio.h>
int main(void)
{
FILE * fr = fopen("test.txt", "r");
int ch;
ch = getc(fr);
while(ch != EOF)
{
putchar(ch);
ch = getc(fr);
}
printf("\n");
fclose(fr);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در مثال بالا که همانند مثال دیگری در همین مبحثِ stdio میباشد یک کاراکتر از فایل test.txt را که پیشتر ایجاد نمودیم می خوانیم و سپس توسط حلقه while تا زمانی که مقدار متغیر ch انتهای سند نیست ، مرتب یک کاراکتر که دریافت شده را در خروجی خطدستوری چاپ می کنیم و سپس کاراکتر بعدی را می خوانیم تا جایی که به انتهای سند می رسیم که شرط حلقه برقرار نیست و حلقه می شکند که در خروجی خطدستوری چاپ می شود : ! This is a test file که محتوای سند test.txt می باشد ( که پیشتر آن را در همین مبحث ایجاد نمودیم ) . سپس خط را شکسته ، پرونده را میبندیم و تابع main را با موفقیت به پایان می رسانیم
'''دقت کنید :''' استفاده از تابعهای rewind و fsetpos و fseek یا clearerr ماکروی مقدار EOF را پاک می کنند
== تابع feof ==
تابع feof سرنام find end of file ماکروی مقدار EOF را در تابعهایی که آن را باز می گردانند بررسی می کند تا پیدا کند که آیا واقعاً به پایان فایل رسیدهایم یا نه . اگر به پایان فایل رسیده باشیم ، مقداری غیر 0 را باز می گرداند و در غیر این صورت مقدار 0 را . دقت کنید که یک خطای مرسوم وجود دارد که برای کنترل یک حلقه از ()feof! استفاده می شود تا بررسی شود که تا زمانی که به پایان فایل نرسیدهایم ، توسط تابعهای مربوطه ، فایل خوانده شود اما چون feof بررسی می کند که بعد از انتهای فایل ، می شود خواند یا نه ، این خطر وجود دارد که یک داده اضافه و زباله ، خوانده شود و یا خطایی ایجاد شود که شما را گمراه کند . شکل کلی فراخوانی تابع feof بدین صورت می باشد :
{{چپچین}}
feof(FILE * stream);
{{پایان چپچین}}
که اشارهگر فایل را به آن می فرستیم ( فایلی که توسط برنامه ، باز شده و در حال خوانده شدن است )
مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include<stdio.h>
int main(void)
{
FILE * fr = fopen("test.txt", "r");
int ch;
ch = getc(fr);
while(1)
{
if(feof(fr))
break;
putchar(ch);
ch = getc(fr);
}
fclose(fr);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
'''توضیح :''' فایل fr را با تابع fopen که فایل test.txt می باشد جهت خوانده شدن به صورت متنی ، باز نمودهایم . سپس یک کاراکتر از آن را خواندهایم . بعد از آن با حلقه بی نهایت while ( که مقدار 1 را در آن گذاشتهایم تا همیشه صحیح و برقرار باشد ) ابتدا بررسی نمودهایم که اگر feof مقدار دارد ( چون fr را می خواند ) که یعنی به پایان فایل رسیدهایم ( مقدار غیر 0 ) بشکند که اگر شرط برقرار نباشد ادامه خواهد یافت و کاراکترِ خوانده شده را در خروجی خطدستوری نمایش خواهد داد و سپس به سراغ کاراکتر بعدی می رود که این حلقه یک جا به پایان فایل می رسد و feof مقدار 0 را باز می گرداند . در ادامه فایل fr را بسته و تابع اصلی برنامه را با موفقیت به پایان رساندهایم
== تابع clearerr ==
تابع clearerr سرنام clear error به معنی نشانگر خطا را خالی کن یا پاک کن ، مقدار خطای errno برای نوع خطای خواندن یا نوشتن در فایل و EOF برای انتهای فایل را برای اشارهگرِ فایلی که به آن فرستاده شده ، خالی و پاک می کند . زمانی که در خواندن یا نوشتن فایل ، خطایی رخ می دهد یا به انتهای فایل می رسیم نشانگر خطا و انتهای فایل ( به ترتیب برای هرکدام یعنی errno و EOF ) ایجاد و مقداردهی می شوند ( به اصطلاح سِت می شوند ) ، برای اینکه بعد از رفع خطا و یا بعد از رسیدن به انتهای فایل ، در ادامه فایلِ مورد استفاده ، دادههایی را بنویسیم و دوباره خطایابی کنیم یا بررسی کنیم که به انتهای فایل رسیدهایم یا نه باید نشانگر خطای فایل یا انتهای فایل را پاک کرده و دوباره به کار خود ادامه دهیم که این کار را می توانیم توسط تابع clearerr انجام دهیم . نشانگر خطا و یا انتهای فایل پس از مقدار یافتن در برنامه ، باقی می مانند و گفتیم که اگر فایل را ببندیم یا از fseek استفاده کنیم ، نشانگر خطا پاک می شود ؛ ولی این روش حرفهای برای پاک کردن و خالی کردن نیست ؛ چون بهتر است خطا یا انتهای فایل را ابتدا پیدا نموده ، رفع خطا کنیم و در ادامه فایل ، چیزی بنویسیم و سپس آنها را خالی کرده و به ادامه کار خود در مورد فایل بپردازیم که برای این کار بهتر است از تابع clearerr استفاده کنیم . شکل کلی فراخوانی تابع clearerr بدین صورت می باشد :
{{چپچین}}
clearerr(FILE * Stream);
{{پایان چپچین}}
مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include<stdio.h>
int main(void)
{
FILE * fr = fopen("test.txt", "r");
if(fr == NULL)
{
printf("File not found\n");
return 1;
}
int ch;
ch = getc(fr);
while(ch != EOF)
{
putchar(ch);
ch = getc(fr);
}
printf("We Reached EOF\n");
clearerr(fr);
if(feof(fr) != 0)
printf("EOF still set\n");
else
printf("EOF is cleared\n");
fclose(fr);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
'''توضیح :''' فایل test.txt را که پیشتر ایجاد نمودیم جهت خوانده شدن به صورت متنی ، باز می کنیم . چک می کنیم تا در صورت عدم وجود ، در خروجی خطدستوری ، چاپ شود : فایل موجود نیست و تابع main با خطا پایان یابد . متغیر ch را از نوع صحیح ایجاد نموده و یک کاراکتر از فایل خود را خوانده و در آن ذخیره می کنیم . سپس تا زمانی که به پایان فایل نرسیدهایم فایل test را به صورت کاراکتری ، یک به یک ، خوانده و در خروجی خطدستوری ، چاپ می کنیم . سپس چاپ کردهایم به پایان فایل رسیدهایم ( همان EOF ) سپس تابع clearerr را فراخواندهایم تا ماکروی علامت EOF پاک شود . سپس چک کردهایم تا اگر EOF وجود دارد و feof مقدار 0 ندارد چاپ شود EOF still set یعنی علامت پایان فایل همچنان سِت شده است و در غیر این صورت چاپ کند EOF is cleared یعنی علامت پایان فایل پاک شده است که همین طور است ؛ چون با clearerr ماکروی علامت EOF پاک شده است و feof مقدار 0 را می گیرد ( یعنی به پایان فایل نرسیدهایم که البته رسیدهایم و این تمرین مناسبی نیست ، مگر آنکه در ادامه سند یا همان فایل بخواهید متن یا مقادیر دیگری بنویسید ) سپس فایل را بسته و تابع main را با موفقیت به پایان رساندهایم
== ماکروی stderr ==
ماکروی stderr سرنام standard error یکی دیگر از ماکروهای استاندارد ورودی و خروجی همانند stdin و stdout است که برای چاپ پیام خطا در خروجی خطدستوری به کار می رود و می توان از تابعهایی که در خروجی فایل متنی می نویسند استفاده کرد تا به جای نوشتن خطا در فایل ، آن را در خروجی خطدستوری چاپ کند . همانند تابع perror سرنام print error که در همین مبجث آن را می نویسیم و مخصوص چاپ پیام خطاست و هیچ آرگومانی نمی پذیرد ، stderr نیز برای چاپ پیام خطاست . ما می توانیم هر متن خطایی را که خواستیم با stdout آن را چاپ کنیم اما تفاوت stdout و stderr در این است که stdout در بافر buffer سیستم عامل ، ذخیره می گردد اما stderr در بافر نوشته نمی شود و تنها در ترمینال سیستم عاملهای مبتنی بر یونیکس یا شبهیونیکس و خطدستور command prompt ویندوز وجود دارد و به محض بسته شدن آن ، تمام محتوای آن ، پاک می شود . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include<stdio.h>
int main(void)
{
fprintf(stderr, "This is an error\n");
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
توضیح این مثال بسیار ساده است و ما با تابع کتابخانهای fprintf که در فایل متنی می نویسد ، در خروجی خطدستوری ، چاپ کردهایم : این یک خطاست و خط را شکستهایم اما '''دقت کنید''' که تابع ، دیگر آرگومانی نمی تواند بپذیرد و به جای اشارهگر فایل خود می نویسیم stderr
== ماکروی نوع داده fpos_t و تابعهای fgetpos و fsetpos ==
در سیستم عامل قدرتمندی همچون گنو/لینوکس fseek که پیشتر آن را نشریح کردیم می تواند تعداد کاراکترها را نیز در فایل متنی بخواند و به همان جا اشاره کند . اما سیستم عاملهای دیگری نظیر ویندوز در گذشته این قابلیت را نداشتند . ضمناً برخی از فایلها حجمشان از تعداد بایتهای قابل ذخیره در یک صحیح بلند long int بیشتر است . برای همین در استانداردهای C 98/99 و نوینتر از آن ، نوع داده fpost_t به عنوان یک ماکروی نوع داده شیئ کامل تعریف شد که یک آرایه نیست و می تواند به یک رکورد اشاره کند ؛ '''نکته :''' در دانش برنامهنویسی ، یک آرایه ، مجموعهای از عناصرِ فقط یک نوع داده است اما یک رکورد می تواند مجموعهای از عناصرِ انواع مخلف باشد که هر کدام ، یک نام دارند و از طریق آن نام ، می توان به محتوای آن دسترسی پیدا کرد .
ماکروی نوع داده شیئ کامل fpost_t یک داده را اعلان می کند که به انتهای فایل اشاره می کند . پس از آن تابع fgetpos هر جا که در فایل بنویسیم یا از آن بخوانیم و داده اعلان شده را در آن ، قرار دهیم به داده اعلان شده مقدار می دهد و هر جا که تابع fsetpos را به همراه داده مقداردهی شده به کار ببریم ، اشارهگر فایل را به همان جا می برد . شکل کلی استفاده از این ماکرو و تابعها بدین صورت می باشد :
{{چپچین}}
fpos_t pos;
{{پایان چپچین}}
نام pos یک نام اختیاری برای fpos_t است که سرنام file position type و به معنی نوع جای فایل ، می باشد
{{چپچین}}
fgetpos(FILE *stream, fpos_t *pos);
{{پایان چپچین}}
تابع کتابخانهای fgetpos سرنام file get position به معنی جای فایل را به دست بیاور ، یک اشارهگر به فایل را به همراه داده اعلان شده توسط fpos_t می گیرد و آن را مقداردهی می کند . این تابع در صورت موفقیت آمیز بودن عملکرد خود ، مقدار 0 را باز می گرداند و در غیر این صورت مقداری دیگر را باز می گرداند و ضمناً متغیر خطایاب errno را مقداردهی می کند که مقدار آن در هر پیادهساز ، تعریف خود را دارد
{{چپچین}}
fsetpos(FILE *stream, fpos_t *pos);
{{پایان چپچین}}
تابع کتابخانهای fsetpos سرنام file set position به معنی جای فایل را قرار بده ( ست کن ) ، یک اشارهگر به فایل را به همراه داده مقداردهی شده توسط fgetpos می گیرد و نمایانگر یا همان اشارهگر فایل را به همان جا می فرستد . دقت کنید که پیش از استفاده از fgetpos باید با fgetpos جای فایل را تعیین کنید ، در غیر این صورت نمی توانید به درستی از آن استفاده کنید و در برنامه شما خطایی رخ می دهد چرا که جای فایل ، تعیین نشده است . این تابع ، در صورت موفقیتآمیز بودن عملکرد خود مقدار 0 را باز می گرداند و EOF را پاک می کند و ضمناً تمام کاراکترهایی که توسط ungetc به عقب رانده شدهاند را نادیده می گیرد و در غیر این صورت مقداری غیر از 0 را باز می گرداند و متغیر خطایاب errno را مقداردهی می کند
مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
FILE * fp;
fp = fopen("example.txt", "w+");
if(fp == NULL)
{
printf("Error during open file\n");
return 1;
}
fputs("1st sentence\n2nd sentence\n3rd Sentence", fp);
fpos_t pos;
rewind(fp);
char str[25];
fgets(str, sizeof(str), fp);
printf("1 : %s", str);
fgetpos(fp, &pos);
fgets(str, sizeof(str), fp);
printf("2 : %s", str);
fsetpos(fp, &pos);
fgets(str, sizeof(str), fp);
printf("After getting same position : %s", str);
fgetpos(fp, &pos);
fgets(str, sizeof(str), fp);
printf("3 : %s", str);
fclose(fp);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
:توضیح : در مثال بالا فایلی به نام example.txt را جهت نوشتن و خواندن متنی ، ایجاد نمودهایم . سپس در آن نوشتهایم : جمله اول ، جمله دوم و جمله سوم ؛ که در هر کدام خط را شکستهایم . سپس fpos_t یک داده را به نام pos اعلان کرده است که به انتهای فایل ، اشاره می کند . پس به ابتدای فایل باز می گردیم ( با تابع rewind ) . با نوشتن شماره ۱ ، جمله اول را در خروجی خطدستوری ، چاپ کردهایم .
:پس اشارهگر فایل به ابتدای خط دوم می رود و با fgetpos آن را مقداردهی کردهایم تا ابتدای خط دوم مقدار pos شود . خط دوم را خواندهایم و در خروجی خطدستوری ، چاپ کردهایم : ۲ : جمله دوم . سپس با fsetpos مقداری را که fgetpos تعیین کرده بود برای pos تعیین می کنیم که همان ابتدای خط دوم است و دوباره خط دوم را خوانده و در خروجی خطدستوری چاپ کردهایم : بعد از رسیدن به همان جا : خط دوم .
:ما به ابتدای خط سوم می رسیم اما هنوز pos مقدار دهی مجدد نشده است دوباره با fgetpos مقدار pos را به روزرسانی کردهایم که ابتدای خط سوم است و از فایل خود ، خط سوم را خوانده و در خروجی خطدستوری چاپ می کنیم : ۳ : جمله سوم .
:البته این کار ضروری نیست ، چون به خودی خود ، pos به ابتدای خط سوم اشاره می کند اما اگر بخواهیم حتما به جای خاصی از فایل برویم باید با fgetpos مقدار pos را به روزرسانی کنیم . در پایان فایل را بسته و تابع اصلی برنامه را با موفقیت به پایان می رسانیم
== نکته : میانگیری یا بافرینگ ==
بافرینگ ( Buffering ) یا با برگردان فرهنگستان به میانگیری به روشی می گویند که دادهها یا اجسام و موادّ در جایی به صورت موقت ، انباشه می شوند تا بعد از پردازش و یا پیرایش به جای دیگری فرستاده شوند که باعث دست نخوردگی و پایداری ( استیبل شدن Stable ) و یا تسریع در روند آن می شود . اما ما فعلاً فقط به میانگیری یا بافرینگ دادهها در علوم رایانه می پردازیم . میانگیری در علوم رایانه ۳ کاربرد دارد :
۱ - تسریع در روند پردازش دادهها و ورودی/خروجی : در همین کتاب و در همین مبحث بارها مثالهایی را از خواندن و نوشتن و کپی ( Copy کاپی ) کردن فایل نوشتهایم . در برخی از آنها یک بایت به یک بایت ( که عموماً به آن کاراکتر می گوئیم - در تابعهایی مثل fgetc و fputc - اما هر کاراکتری در استاندارد انسی ANSI که کاراکترست ASCII ازکی است را شامل می شود و به صورت دودویی هر مقداری را می توان خواند و نوشت ) خواندهایم و نوشتهایم . تقریباً تمام سیستم عاملها در هسته خود ( Core ) شامل کرنل Kernel و اجزاء کمکی آن ( Core Components ) میانگیر یا بافر ( Buffer ) دارند و عمل ورودی/خروجی ( I/O ) را تسریع می کنند اما اگر برنامه نویس یک بایت به یک بخواهد بخواند و بنویسید ، در زبان C به سیستم عامل تحمیل و دستور داده می شود تا به همان شکل عمل کند ( فراموش نکنید که زبان سی ، زبان اصلی اکثر کرنلهاست و تمام سیستم عاملها کتابخانههایی را برای اجرای برنامهها به زبان سی و/یا سیپلاسپلاس دارند - چه در زمانی که برای سیستم عامل کامپایل می کنید و چه یک برنامه نویس برای نوشتن کرنل خود از یک کامپایلر و کتابخانههای آن استفاده کند این تحمیل و دستور وجود دارد ) اما اگر به جای آن ، یک آرایه بسازیم که مثلاً هزار عنصر داشته باشد و یا ده هزار عنصر ، و بعد به اندازه آن از فایل ، بخوانیم و به همان اندازه بنویسیم در واقع میانگیری کردهایم و سرعت کپی کردن خود و یا هر نوع خواندن و نوشتن را بالا بردهایم
۲ - پیمانهای کردن دادهها و تنظیم سرعت : این روش در علوم بسیاری ، از جمله الکترونیک و مخابرات و همچنین همین علوم رایانه ، کاربرد پایدار کردن ( استیبل کردن Stabilization ) و تنظیم سرعت را دارد . نمی خواهیم از بحث خارج شویم ولی این مثال به درک نحوه میانگیر کردن کمک بزرگی می کند . در یاختههای مهرهداران و یا حتی دیگر جانداران پریاختهای ، در یاختههای مخصوصی در انباشتگاههای خودشان ( Buffer یا میانگیر ) اسید و باز ، انباشت می کنند تا در صورتی که خون و یا بدن جانور از حدی اسیدیتر شد و pH پهاش آن پائین آمد ، بازِ انباشت شده در خود را آزاد کنند و یا خلاف جهت آن ؛ اگر از حدی بازیتر شد و pH آن بالاتر رفت ، اسید خود را آزاد کنند که در این صورت اسید و باز با هم ترکیب میشوند ( و نمک و آب می سازند که نمک ، توسط تصفیه کننده خون ، مثل کلیهها در برخی از پستانداران ، دفع می گردد ) و در نتیجه پهاش pH خون و بدن ثابت باقی می ماند . در علوم رایانه و الکترونیک ، میانگیر کردن به همین شکل به پایداری عملکرد سیستم ، کمک می کند . به عنوان مثال ، پخش کردن ویدئو و یا صدا را در نظر بگیرید . کاربران قدیمی رایانه به خوبی به یاد خواهند داشت و یا حتی هم اکنون نیز ممکن است با چنین پدیدهای مواجه شوید که سرعت ارتبط شما با شبکه ( کانکشن Connection ) پائین باشد ( در گذشته اتصال به اینترنت اکثراً از طریق مودمهای تماسی Dial-Up امکانپذیر بود که سرعت بسیار بسیار پائینی داشت ) و شما بخواهید یک فایل ویدوئی را تماشا کرده و بشنوید و یا فایل صدایی ( صوتی ) را گوش بدهید . در چنین مواقعی اگر به اندازه سرعت شما قابهای ویدئو ( فریمها Frames - واحد سازنده هر ویدئو یا انیمیشن که پشت سر هم و با سرعت معین به تصویر متحرک تبدیل می شوند و به صورت متحرک دیده می شوند ) و یا نمونه-بیتها ( بیت سمپلها Bit Samples واحد سازنده هر فایل صدایی - یا همان صوتی ) را نشان دهد و/یا پخش کند شما نمیتوانید عملاً آن فایل را تماشا کرده و گوش دهید . برای همین برنامهنویسان ، فایل را میانگیر می کنند و هر مثلاً یک یا دو یا سه ثانیه از ویدئو یا صدا را انباشت میکنند و بعد از رسیدن به آن مقدار ، ویدئو و صدا را برای شما پخش می کنند یا اینکه فرض کنید سیستم شما چندان به روز و قدرتمند نیست و شما می خواهید یک فیلم سینمایی با کیفیت ۱۰۸۰ پیکسلی ( که ارتفاع قابهای آن - فریمهای آن - ۱۰۸۰ پیکسل و یا نزدیک به آن است ) تماشا کنید . اگر قرار باشد پخش کننده رسانه Media Player بخواهد کل فایل را رمزگشایی و سپس در حافظه موقت ( Memory که همان رم RAM است ) بارگذاری کند ( Loading ) سیستم شما یا قفل خواهد کرد و مجبور به راه اندازی مجدد سیستم خواهید شد یا اینکه اگر سیستم عامل شما قدرتمند باشد پس از چند ثانیه ، سیستم عامل ، برنامه را پایان می دهد ( Termination ) بنابراین پخش کنندههای رسانه یک یا دو دقیقه از فیلم و ویدئو را رمزگشایی ( دکود Decode ) می کنند و بر روی حافظه موقت بارگذاری می کنند و آن را پخش می کنند و حتی اگر بخواهید فیلم را ۵ دقیقه یا مثلاً نیم ساعت جلو ببرید ، یک یا دو دقیقه قبلی را از حافظه موقت پاک می کنند و سپس دوباره آن قسمت از فیلم و ویدئو را که شما دستور داده بودید پخش کند بارگذاری می کنند . به همین شکل ممکن است سرعت دستگاههای الکترونیکی رایانه ( که میانگیر کردن در خود الکترونیک نیز به کار می رود اما ما در اینجا به آن نمی پردازیم ) و یا در شبکههای مختلف رایانه مثل شبکه اینترنت و پروتکلهای آن ، تداخل پیش بیاید و سرعتهای دادهها نسبت به هم و یا میزبان/میهمان و یا حجم دادهها در آنها نسبت به سرعت میهمان بیشتر باشد ( و یا حتی بعضاً حجم درخواستهای میهمانها از سرعت میزبان بیشتر باشد ) در چنین مواقعی ، پیمانهای عمل کردن برنامهها و یا میانافزارها و سختافزارها ، کمک می کند تا کم کم ، ورودی دریافت شده و به خروجی فرستاده شود و چه سرعت ورودی کم یا زیاد باشد و یا سرعت خروجی کم یا زیاد باشد ، سامانه دچار مشکل و قفل شدن نمی شود
۳ - دادههای موقتی : یکی دیگر از کاربردهای میانگیر کردن ، ساخت یک داده موقتی است ( که این داده از هر نوعی و در هر اندازهای ممکن است باشد ) که دو کاربرد دارد : ۱ - بخواهیم همان زمان با ساخت داده موقت ، بر روی آن پردازش و پیرایش انجام دهیم . به عنوان مثال ، در گذشتهها پیرایشگرهای تصاویر رستر ( Raster Graphics گرافیکهای مبتنی بر پیکسل Pixel ) وقتی فایلی را باز می کردند پیرایشها را بر روی خود همان فایل انجام میدادند و اگر حتی پیرایشهای خود را ملغا ( Undo ) می کردید و آن را ذخیره ( Save ) می کردید باز هم فایل شما دستخوش تغییر قرار می گرفت ( چون تصویر ، پیرایش شده بود و فقط توسط رمزنگار برنامه مجدداً مانند اولش نوشته می شد اما اگر از یک فایل ادیتور یا همان هگزادسیمال ادیتور Hexadecimal Editor استفاده می کردید ، مشاهده می کردید که فایل تغییر پیدا کرده است ) به این روش ویرانگر یا Destructive گفته می شود . اما امروزه برنامههای پیرایشگر رستر به روش ناویرانگر Non Destructive عمل می کنند و هر فایلی که باز می کنید یک فایل کپی موقت ( Temporary ) از روی آن می سازند و بعد از رمزگشایی و بارگذاری بر روی حافظه تغییرات را بر روی آن اعمال می کنند و بدین صورت فایل شما دست نخورده باقی می ماند و هر وقت که خواستید می توانید آن را در فایلی جدید ذخیره ( Save ) و یا جایگزین همان فایل خودتان کنید . همین تکنیک در مورد پیرایش فایلهای ویدئویی نیز به کار می رود ۲ - گاهی نیاز پیدا خواهید کرد تا فایل موقتی بسازید و چند بار بر روی آن پردازش انجام دهید که غیر متوالی هستند . در این صورت فایل را میانگیر می کنید و هر موقع نیاز داشتید آن را پردازش کرده و به سراغ فایلهای دیگر می روید و یا کارهای دیگری انجام می دهید و سپس دوباره به پردازش فایل میانگیر شده خود ( Buffer ) باز می گردید
در مجموع ، میانگیر کردن و ساخت یک میانگیر ( بافر Buffer ) در نوشتن برنامههای شبکه و پروتکلهای آن ، پخش کنندههای رسانه ( میانافزاری و نرمافزاری ) و هسته سیستم عامل ، مخصوصاً کرنل آن در کنار بسیاری دیگر از بخشهای مهندسی نرمافزار و برنامهنویسی ، ضروری و حیاتی است
== تابع setbuf و ماکروی مقدار BUFSIZ ==
گاهی در برنامهنویسی پیشرفته ، امکان دستی ، تعیین کردن میانگیر یا بافر ناممکن و یا بسیار سخت است ( مخصوصاً در برنامهنویسی سطح پائین ) که ما هنوز به این مرحله نرسیدهایم . اما تابع قدیمی setbuf سرنام set buffer به معنی میانگیر را تعیین کن ، با ماکروی اندازه حداقل به اندازه BUFSIZ سرنام Buffer Size به معنی اندازه میانگیر ( بافر ) که امروزه منسوخ شده است و به جای آن در استاندارد سی C تابع setvbuf تعریف شده است ، می تواند میانگیر را برای شما ایجاد کند تا هم فایل را به صورت موقت در حافظه RAM نگهداری کنید و به پردازش آن بپردازید و هم عملیاتهای خواندن/نوشتن را پیمانهای می کند . دقت کنید : ۱ - تابع setbuf باید برای فایلی تعیین شود که باز شده است ۲ - تابع setbuf باید قبل از هر عملی بر روی فایل برای خواندن و نوشتن ، اعمال شود ۳ - اگر مقدار میانگیر را که باید تعیین کنید ، در یک حوزه محلی ، تعیین کنید پس از اتمام بلوکِ آن میانگیر ، همانند یک متغیر معمولی ، میانگیر و بافر ، خالی می شود و دیگر موجود نخواهد بود . اگر می خواهید میانگیر را توسط تابعهای زبان سی C و کامپایلر بسازید ، بهتر است آن مقدار آن را ( مثل مقدار BUFSIZ ) با حوزه سراسری تعیین کنید . در غیر این صورت برنامه شما رفتار تعریفنشدهای بروز خواهد داد ۴ - مقدار میانگیر (بافر ) ، طبق استاندارد باید حداقل به اندازه ماکروی مقدار BUFSIZ که در فایل سرآیند stdio تعریف شده است باشد ( استاندارد ، مقدار آن را تعیین نکرده است ولی در کامپایلری مثل GCC مقدار آن 8192 بایت است ) اگر کامپایلر شما از مقدار کوچکتر پشتیبانی نکند و شما مقداری کوچکتر تعیین کنید با خطا در برنامه مواجه خواهید شد
در صورتی که می خواهید فایل بزرگی را میانگیر کنید بهتر است مقداری بزرگتر از BUFSIZ استفاده کنید و باز هم بهتر است مقدار آن ، مقدار از توان ۲ باشد ؛ مثل : 16384 یا 32768 و ... ) . شکل کلی استفاده از تابع setbuf بدین صورت می باشد :
{{چپچین}}
setbuf(FILE *stream, char *buffer);
{{پایان چپچین}}
باید اشارهگر فایلی را که می خواهید میانگیر کنید را به آن بفرستید و یک آرایه کاراکتری با اندازه حداقل BUFSIZ تا به همان اندازه ، فایل شما را میانگیر کند . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
#include <time.h>
int main()
{
clock_t start, end;
double time_passed;
char buf[BUFSIZ];
start = clock();
FILE * fp, * fp2;
fp = fopen("post-1.jpeg", "rb");
fseek(fp, 0, SEEK_END);
long int size = ftell(fp);
fseek(fp, 0, SEEK_SET);
unsigned char fr[size];
setbuf(fp, buf);
fread(fr, size, 1, fp);
fclose(fp);
fp2 = fopen("copy.jpeg", "wb");
setbuf(fp2, buf);
fwrite(fr, size, 1, fp2);
fclose(fp2);
end = clock();
time_passed = ((double) (end - start)) / CLOCKS_PER_SEC;
printf("Program execution time: %lf seconds\n", time_passed);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در این برنامه از فایل سرآیند time که هنوز به مبحث آن نرسیدهایم استفاده نمودهایم . به معنی زمان می باشد و دارای تابعها و ماکروهایی برای تعیین زمان و سنجش آن می باشد . ابتدا توسط ماکروی clock_t دو متغیر به نام آغاز و پایان اعلان نمودهایم و هر دو را یک بار در آغاز برنامه و یک بار در پایان برنامه با تابع clock که زمان را تعیین می کند مقداردهی نمودهایم . '''دقت کنید :''' ما در این برنامه از دو روش فایلی را با نام post-1.jpeg میانگیر کردهایم . یک بار توسط پیمانه size که به اندازه فایل خودمان ( که شما میتوانید هر فایلی را که در دایرکتوریِ برنامه کامپایل شده خودتان قرار دارد بنویسید ) آن را خواندهایم و به همان اندازه نوشتهایم . یک بار هم توسط تابع setbuf آن را میانگیر و بافر کردهایم . در پایان برنامه مقدار زمان پایان برنامه را منهای مقدار زمان آغاز برنامه نموده و با دقت دو برابر اعشار در خروجی خطدستوری چاپ نمودهایم . دقت کنید که در این برنامه کارکرد setbuf به حداقل خود رسیده است چون به اندازه فایل ، خواندهایم و آن را در حافظه موقت ( RAM ) نوشتهایم سپس فایل را بر روی حافظه دائمی ( مثل H.D.D یا S.S.D ) نوشتهایم . اما اگر اندازه فایل بزرگتر از مقدار قابل سنجش می بود ( مثل نوشتن برنامه سامانه فایلبندی File System ) عملکرد setbuf با مقدار بززگ ، کاملاً چشمگیر می شد
== تابع setvbuf و ماکروهای IOFBF_ و IOLBF_ و IONBF_ ==
تابع setvbuf همانند تابع setbuf می باشد با این تفاوت که نوع میانگیر کردن و اندازه میانگیر ، در دست برنامهنویس است . شکل کلی فراخوانی تابع setvbuf بدین صورت می باشد :
{{چپچین}}
setvbuf(FILE * stream, char * buffer, int mode, size_t size);
{{پایان چپچین}}
ابتدا نام جریان فایل را می نویسیم ، سپس آرایه کاراکتری خود را و سپس نوع میانگیر کردن را که یکی از سه ماکروی نوشته شده است و در نهایت اندازه میانگیر کردن را . سه ماکروی نوشته شده که نوع میانگیر را تعیین می کنند بدین قرار هستند :
IOFBF_ سرنام Input/Output Full Buffer به معنی میانگیر کردن کامل ورودی/خروجی
IOLBF_ سرنام Input/Output Line Buffer به معنی میانگیر کردن خط در ورودی/خروجی
و
IONBF_ سر نام Input/Output Not Buffer به معنی عدم میانگیر کردن ورودی/خروجی
'''دقت کنید :''' در صورتی که بخواهید میانگیر کردن را از کار بیاندازید و از IONBF_ استفاده کنید باید حتماً به جای آرایه کاراکتری از ماکروی مقدار تهی NULL نول استفاده کنید و اندازه را 0 تعیین کنید ؛ در غیر این صورت در هر گونه میانگیر کردن باید اندازهای بزرگتر از 0 داشته باشد . تابع setvbuf در صورت موفقیتآمیز بودن عملکرد خود مقدار 0 را باز می گرداند و در غیر این صورت مقداری غیر 0 را . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
char buf[30];
if(setvbuf(stderr, buf, _IOFBF, sizeof buf))
{
printf("failed to change the buffer of stdout");
return 1;
}
fprintf(stderr, "He");
fflush(stderr);
if(setvbuf(stdout, NULL, _IONBF, 0))
{
printf("failed to change the buffer of stdout");
return 1;
}
printf("llo w");
if(setvbuf(stdout, buf, _IOLBF, sizeof buf))
{
printf("failed to change the buffer of stdout");
return 1;
}
printf("orld!");
putchar('\n');
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
این قطعه کد را مشابه قطعه کد مثال setvbuf در ویکی کتاب انگلیسی نوشتهام ؛ چرا که بسیار زیبا و کارآمد نوشته شده است . یک آرایه کاراکتری با ۳۰ عنصر ، اعلان نمودهایم که نقش میانگیر ما را ایفا می کند . سپس در داخل شرط ، میانگیر کامل خود را بر روی stderr اعمال نمودهایم تا میانگیر و بافر شود . اگر به یاد داشته باشید گفتیم که stderr در داخل بافر سیستم عامل یا کرنل ، نوشته نمی شود . ولی با این کار می توانیم stderr را نیز میانگیر کنیم . در صورت خطا ، پیغامی ، چاپ خواهد شد و تابع اصلی برنامه با خطا به کار خود خاتمه خواهد داد اما در غیر این صورت He در بافر سیستمعامل یا کرنل ( بسته به اینکه برای سیستم عامل ، برنامه می نویسیم و یا سطح پائین و برای سیستم ) می نویسد و سپس آن را خالی می کنیم . سپس بدون میانگیر کردن در خروجی خط دستوری چاپ می کنیم : llo w و در ادامه با میانگیر کردن خط در محیط خطدستوری مثل ترمینال در سیستمعاملهای یونیکس و شبه یونیکس و command prompt در ویندوز و همچنین خطدستور در برنامههای سطح پائین ( مثل بارگذار بوت یا کرنل یا هسته سیستمعامل ) چاپ می کنیم : !orld و در ادامه خط را می شکنیم تا میانگیر شود . دقت کنید اگر خط ، شکسته نشود ، میانگیر ما در حافظه موقت ، تخلیه نمی شود و به جای حروف نوشته شده به احتمال زیاد ، حروف دیگری نمایش داده می شوند ( می توانید امتحان کنید و putchar(\n) را کامنت کنید یا حذف کنید و کامپایل و لینک کرده و سپس اجرا کنید و دوباره آن را اضافه کنید و کامپایل و لینک و اجرا کنید تا نتیجه را ببینید )
== تابع perror ==
تابع perror سرنام print error به معنی خطا را چاپ کن ، خطایی را که در عملیات ورودی/خروجی پیش آمده است را به خروجی استاندارد که معمولاً محیط خطدستوری است می فرستد و نمایش می دهد . شکل کلی استفاده از perror بدین صورت می باشد :
{{چپچین}}
perror(const char * string);
{{پایان چپچین}}
شما مجاز هستید تا درون تابع ، پیامی را به صورت یک رشته یا حتی یک کاراکتر بنویسید تا نمایش داده شود و در این صورت ابتدا پیام شما نمایش داده شده و سپس با یک دو نقطه ( : ) و یک فاصله خالی ( اسپیس Space ) perror پیام خطای سیستم را که در آخرین ورودی/خروجی پیش آمده در stderr می نویسد . ولی اگر داخل تابع یک کاراکتر با مقدار ماکروی تهی ( نول NULL ) قرار بدهید و یا رشته را خالی بگذارید ، تنها پیام خطای سیستم ، نمایش داده می شود . '''دقت کنید :''' هر جا که امکان وجود خطا در ورودی/خروجی پیش آمد perror را بنویسید و گرنه errno با مقدار و پیام خطای دیگری که پیش بیاید جایگزین می شود . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
FILE * file = fopen("imaginary_file.bin", "rb");
if(file == NULL)
{
perror("Error on opening file");
return 1;
}
else
fclose(file);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
'''توضیح :''' در تابع اصلی برنامه ( main ) تلاش کردهایم تا فایلی را که وجود ندارد ( دقت کنید تا در جایی که برنامه را اجرا می کنید فایلی با این نام وجود نداشته باشد تا کارایی مثال بالا را متوجه شوید ) با نام فایل خیالی ( imaginary_file ) با پسوند bin که نشان می دهد فایل از نوع اجرایی و دودویی است ( binary ) با حالت خواندن دودویی rb باز کنیم و اگر فایل موجود نبود پیام خطا چاپ شود : خطا در باز کردن فایل و سپس سیستم ، پیام خطای خود را چاپ می کند که چیزی شبیه به No Such File or Directory یا دقیقاً همین پیام است . در غیر این صورت فایل با موفقیت باز شده و سپس بسته می شود ولی اگر این فایل را در دایرکتوری ( که در ویندوز با اصطلاح فولدر Folder شناخته می شود ) برنامه کامپایل شده بالا ایجاد نکنید ، پیام خطا را مشاهده خواهید نمود
== تابع tmpnam و ماکروهای TMP_MAX و L_tmpnam ==
تابع tmpnam سرنام temporary name به معنی نام موقت برای ایجاد نامی تصادفی و موقت و معمولاً برای سندها ( فایلها ) است که هنوز تصمیمی برای انتخاب نامی برای آن نداریم و البته این نام ، توسط پیادهساز ، نامی ساخته می شود که در سند برنامه و یا دایرکتوری سندهای موقت ، موجود نباشد . اما TMP_MAX سرنام Temporary Maximum به معنی حداکثر (نام ) موقت ، یک ماکرو است که نشان می دهد پیادهساز ( کامپایلر ) تا چند ، نام موقت را می تواند بسازد و ماکروی L_tmpnam سرنام Length of temporary name به معنی طول نام موقت است که حداکثر تعداد کاراکترهایی که پیادهساز می تواند برای نام موقت ، بسازد چند کاراکتر است . جهت متوجه شدن این مسئله به راحتی میتوانید از printf استفاده کنید . یعنی :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
printf("longest name generated is %d and maximum number of random names are : %d\n", L_tmpnam, TMP_MAX);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
در پیادهسازهای محتلف و سیستم عاملهای مختلف و البته با توجه به اندازه حافظه موجود در سیستم شما این اعداد می توانند متفاوت باشند . به طور مثال در سیستم عامل گنو/لینوکس و کامپایلر GCC در یک افراز ( پارتیشن Partition ) ۵۱۲ گیگابایتی این مقادیر ۲۰ و ۲۳۸۳۲۸ است ؛ یعنی طولانیترین نامی که GCC می سازد ۲۰ کاراکتر دارد و نهایتاً می تواند ۲۳۸ هزار و ۳۲۸ نام تصادفی ، تولید کند
شکل کلی استفاده از تابع tmpnam بدین صورت می باشد :
{{چپچین}}
tmpnam(char * str);
{{پایان چپچین}}
در ابتدا دقت کنید که شما برای مقدار دهی tmpnam یا باید از ماکروی مقدار تهی NULL استفاده کنید که تابع ، یک اشارهگر به میانگیر ( بافر Buffer ) ایستای سیستم را باز می گرداند و نام می تواند در یک رشته ذخیره شود یا اینکه یک رشته می سازید که تعداد عنصرهای آرایه باید '''حداقل''' به تعداد L_tmpnam باشد و tmpnam را فرا می خوانید تا آن را مقدار دهی کند . ضمناً اگر بخواهید از این نامها برای ایجاد سند ( فایل ) استفاده کنید کامپایلر ، سندها را در دایرکتوری موقت سیستم عامل می سازد . این دایرکتوری در گنو/لینوکس و دیگر شبهیونیکسها همچون سیستم عاملهای مکینتاش ( Mac OS X , OS X , macOS ) در نشانی tmp/ یعنی در فولدر یا دایرکتوری tmp در ریشه ( root ) قرار دارد و در سیستم عاملهای جدید مایکروسافت ویندوز در :
C:\Users\LocalUser\AppData\Local\Temp\
'''دقت کنید :''' یکم اینکه در گذشته ، ویندوز ، همانند سیستم عاملهای شبهیونیکس برای نشانیدهی از اسلش / استفاده میکرد ولی از ویندوز XP به بعد از بک اسلش ( Back Slash ) \ استفاده می کند . دوم اینکه این آدرس در ویندوزهای قدیمی ، متفاوت است و سوم اینکه از ویندوز ۷ به بعد هر افراز ( پارتیشن ) ـی که بر روی آن ویندوز حاضر و فعلی نصب باشد C نام میگیرد ( ممکن است شما دو ویندوز نصب کنید و یکی بر روی افراز D باشد ولی وقتی آن را آغاز کنید - Start Up - نام آن به C تغییر پیدا میکند )
ضمناً این دایرکتوری برای برنامهنویسی حرفهای ، بسیار کاربرد دارد . فرض کنید میخواهید یک پخش کننده چند رسانهای ( Multimedia Player ) یا هر برنامه دیگری بنویسید و هر سندی ( فایلی File ) که باز شد را در فهرست آخرین سندها نگه دارید و به درخواست کاربر ، هر موقع که خواست آن را پاک کنید . برای این کار ، یک فایل در دایرکتوری موقت Temporary می سازید و آن را با سندهایی که باز می شوند ، پیرایش کرده و به روز رسانی می کنید و هر موقع کاربر به برنامه دستور داد که تخلیه شود آن را پاک می کنید و از نو آغاز می کنید . یا مثلاً یک پیرایشگر متن ( Text Editor ) یا واژه پرداز ( Word Processor ) می نویسید و برای آن می خواهید هر ۵ یا ۱۰ دقیقه ( به طور نمونه ) یک بار یک نسخه پشتیبانی ( Backup ) از سند ( File ) یا پرونده ( Document در واژه پرداز ) ایجاد شود ؛ بنابراین آن را در دایرکتوری موقت ، می نویسید . بدین ترتیب اگر برنامه قفل کند یا متوقف شود ، پس از گشودن مجدد برنامه ، حداقل بخش بزرگی از سند یا پرونده ذخیره شده است
'''دقت کنید :''' تابع tmpnam با هر بار فراخوانی ، نام جدیدی را می سازد ؛ پس اگر هنوز نام ساخته شده را ذخیره نکرده باشید و دوباره آن را فرا بخوانید نام قبلی از بین می رود
تابع tmpnam در صورت موفقیت آمیز عمل کردن خود ، یک اشارهگر به نام ساخته شده خود باز می گرداند که اگر آرگومان آن NULL باشد یک اشارهگر به بافر ایستای سیستم ، بازمیگرداند و اگر یک رشته باشد یک رشته را باز میگرداند و اگر در هر صورتی ، کامپایلر ، موفق به ساخت نام موقت نشود یک اشارهگر تهی NULL باز میگرداند . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
char * buf1 = tmpnam(NULL);
char buf2[L_tmpnam];
tmpnam(buf2);
char buf3[30];
tmpnam(buf3);
FILE * fp1 = fopen(buf1, "w");
fputs("first file", fp1);
FILE * fp2 = fopen(buf2, "w");
fputs("second file", fp2);
FILE * fp3 = fopen(buf3, "w");
fputs("third file", fp3);
fclose(fp1);
fclose(fp2);
fclose(fp3);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
'''توضیح :''' یک رشته با نام buf1 تعریف کردهایم که مقدار آن را تابع tmpnam با آرگومان NULL مقداردهی می نماید . یک رشته دیگر با نام buf2 اعلان کردهایم که تعداد عنصرهای آن به اندازه L_tmpnam که اندیس آن می باشد است و سپس آن را با tmpnam مقداردهی کردهایم . سپس یک رشته با نام buf3 با ۳۰ عنصر ، اعلان کردهایم . دقت کنید چون GCC حداقل طول قابل پذیرشش ۲۰ است باید مقداری بزرگتر از آن را بنویسیم ( که در همین مبحث ، کمی بالاتر نوشتیم ؛ شما نیز مقداری بزرگتر از L_tmpnam در کامپایلر خود بنویسید ) سپس ۳ فایل ایجاد نمودهایم که نامهای آنها همان نامهای ایجاد شده توسط تابع tmpnam است ( به ترتیب ) و آنها را به صورت متنی برای نوشتن ، باز کردهایم و در هر کدام از آنها به ترتیب نوشتهایم : سند اول ، سند دوم و سند سوم و سپس فایلها را بستهایم و تابع اصلی برنامه را با موفقیت به پایان رساندهایم ( اگر به دایرکتوری - فولدر - موقت سیستم عامل خود مراجعه کنید ، آنها را خواهید یافت - Visual Studio در ویندوز تماماً آنها را تصادفی میسازد و GCC در گنو/لینوکس با پیشنام file )
'''نکته :''' تابع tmpnam از نظر امنیت زنجیره ، امن است البته اگر آرگومان آن NULL نباشد ؛ برای همین سیستمعاملهای شبهیونیکس و حتی ویندوز هر کدام تابعهایی غیر استاندارد دارند که فرآیند ساخت نامها کاملاً ایمن باشد . برای اطلاع از تابعهای موجود در کامپایلر و سیستم عامل خود به راهنمای آن مراجعه کنید
== ماکروی FOPEN_MAX ==
این ماکرو در فایل سرآیند stdio فقط یک مقدار ثابت دارد که سرنام File Open Maximum به معنی بیشینه ( حداکثر ) تعداد فایل می باشد و نشان می دهد که مطابق با سیستم عامل شما و کامپایلر شما ، در هر سند متن برنامه ، شما چند فایل را پشت سر هم می توانید بدون بسته شدن ، باز کنید . این مقدار باید حداقل طبق استاندارد ۸ باشد ولی به طور مثال در سیستم عامل گنو/لینوکس و کامپایلر GCC این مقدار ۱۶ است . برای اینکه این مقدار را که در فایل stdio کامپایلر شما تعریف شده است بیابید ، قطعه کد زیر را بنویسید و کامپایل و پیوند ( لینک ) کنید و سپس آن را اجرا کنید :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
printf("%d\n", FOPEN_MAX);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
'''توضیح :''' همانند مثالهای پیشین در این مبحث ، پس از تشریحهای فراوان دیگر در مباحث پیشین ، وقت را هدر نداده و قطعه کد را تشریح نمی کنیم . تابع کتابخانهای printf یک مقدار دسیمال ( دهدهی ) را که آرگومانش به آن فرستاده شود در خروجی خطدستوری ، نمایش می دهد و آرگومان آن ، ماکروی FOPEN_MAX می باشد که پس از اجرا می بینید که بیشینه فایلهایی را که در هر برنامه مجاز هستید تا پشت سر هم و بدون بستن فایلهای قبلی باز کنید چه تعداد می باشد
== ماکروی FILENAME_MAX ==
این ماکروی استاندارد که سرنام Maximum File Name می باشد به معنی بیشینه طول نام فایل ، بیشترین مقدار صحیحی که سیستم عامل اجازه می دهد برای هر نام فایل استفاده شود را نشان می دهد . دقت کنید که این مقدار صحیح ثابت است و در فایل سرآیند stdio تعریف می شود تا برنامهنویس بداند که بیشینه مقدار ، چه قدر است که این مقدار فقط تعداد کاراکترهای تعیین شده در ازکی ASCII می باشد ( منهای یکی ؛ چون آخرین مقدار ، تهی است ) و اگر از کاراکترهای یونیکد استفاده شود تعداد کاراکترهای قابل استفاده کاهش می یابد ( مثلاً در UTF-8 که زبانهای مختلف و شکلکها -ایموجیها - پشتیبانی می شوند هر کاراکتر غیر انگلیسی و ازکی ، چهار بایت اشغال می کند ) . این مقدار در حال حاضر در تقریباً تمامیِ سیستم عاملها و سامانههای فایلبندی ۲۵۶ بایت است که چون آخرین بایت آن ، تهی است می شود ۲۵۵ کاراکتر . برای مشاهده این مقدار در سیستم خود از قطعه کد زیر استفاده کنید :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
printf("%d\n", FILENAME_MAX);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
'''نکته :''' هرگز فراموش نکنید که برای برنامه خود در نوشتن آن برای تعیین نامهای فایلها از آرایهای با اندیس این ماکرو استفاده نکنید یعنی char fn[FILENAME_MAX] کاملاً '''خطاست''' . کامپایلر نه از شما خطا می گیرد و نه هشدار می دهد اما چون یک رشته می سازید که مقدار آن در سیستمهای مختلف مقادیر مختلف و بعضاً بزرگی دارد که باید پشت سرهم باشند ( رجوع کنید به مبحث آرایه ) برنامه شما به راحتی مرتکب خطا خواهد شد . بهتر است در صورتی که قصد دارید از این ماکرو برای تعیین نام فایلها استفاده کنید از ترفند تخصیص حافظه پویا که در مباحث بعدی مطرح می شود استفاده نمائید
== تابع tmpfile ==
تابع کتابخانهای tmpfile سرنام temporary file به معنی سند موقت ، یک فایل موقت می سازد که با بستن فایلِ آن یا تمام شدن اجرای برنامه ، حذف می شود . در سیستم عاملهای شبهیونیکس ، معمولاً در دایرکتوری tmp/ ساخته می شود که همین امر باعث می شود سیستم عامل از شما مجوزی برای اجرای برنامه نخواهد . ولی در سیستم عاملی مثل ویندوز Windows در نسخههای نوین آن پوشه (فولدر موقت temporary folder ) داخل فولدرهای اصلی ویندوز موجود است ؛ بنابراین یا باید به عنوان Admin مدیر ، وارد ویندوز شده باشید و یا گذرواژه ( پسورد Password ) آن را بدانید تا بتوانید برنامه را اجرا کنید . فایل موقت به صورتِ پیشفرض به حالت خواندن/نوشتنِ خام یا همان دودویی ( باینری Binary ) باز می شود اما شما می توانید به راحتی در آن ، متن را نیز بنویسید . شکل کلی فراخوانی تابع tmpfile بدین صورت می باشد :
{{چپچین}}
FILE * tmpfile(void);
{{پایان چپچین}}
سند ، توسط یک ماکروی اشارهگر نوع فایل آماده می شود و سپس با نوشتن ;()tmpfile ایجاد می گردد ( دقت کنید که این تابع ، آرگومانی نمی پذیرد و باید آن را خالی بگذارید و حتی اجازه نوشتن void را داخل آن ندارید ) . این تابع در صورت موفقیتآمیز بودن عمل خود ، اشارهگری را به فایل ساخته شده باز می گرداند و در صورت هر گونه عدم موفقیت ، یک اشارهگر تهی ( نول NULL ) را باز می گرداند . مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
FILE *fp, *tmpf;
fp = fopen("copy.txt", "w+");
tmpf = tmpfile();
if (tmpf == NULL)
{
perror("System failed to make temporary file");
return 1;
}
char tmpstr[100];
fgets(tmpstr, 100, stdin);
fputs(tmpstr, tmpf);
char str[100];
for(int i = 0; i <= 100; i++)
{
str[i] = tmpstr[i];
}
fputs(str, fp);
fclose(fp);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
'''توضیح :''' دو اشارهگر فایل را به نامهای fp و tmpf ساختهایم و آمادهایم تا فایلهای آنها را بسازیم . اولی به صورت متنی در فایلی با نام copy.txt ساخته می شود . دومی فایل موقت است که اگر موفق به ساخت آن نشویم پیام خطا را چاپ می کند که سامانه ، موفق به ایجاد فایل موقت ، نشد . سپس یک رشته را از ورودی استاندارد ( صفحهکلید Keyboard ) به طول نهایتاً ۱۰۰ کاراکتر دریافت می کند و داخل خود می نویسد ( آنچه را که کاربر بنویسد و در نهایت دکمه ورود Enter را بزند ) سپس رشته دیگری به همان اندازه ساخته می شود و متن فایل موقت را در خود کپی ( کاپی Copy ) می کند و آن را در copy.txt می نویسد و فایل copy.txt بسته می شود و با پایان برنامه فایل موقت نیز پاک می شود . دقت کنید این ، سادهترین شکل گرفتن فایل پشتیبانی Backup از فایل اصلیِ کاربر است . برنامه gEdit به همین شکل ، کاراکتر به کاراکتر ، متن را داخل سند ، ذخیره می کند و بسیار کند است اما روش مطمئنی است که دادهای از دست نرود ( به همین شکل نیز پشتیبانی آن ، کند است ) . در صورتی که بخواهید با سرعت بالایی سند خود را ذخیره کنید باید از روشها و ترفندهای دیگری استفاده کنید که در مباحث بعدی به آنها می رسیم . اما فعلاً برای کپی کردن یک رشته در رشته دیگر چارهای جز این نداشتیم
== تابع freopen ==
تابع کتابخانهای freopen سرنام file re-open به معنی دوباره فایل را باز کن ؛ در صورتی که فایلی باز شده باشد ( توسط fopen ) و اشارهگر فایل باز شده را به آن بفرستیم ، جریان فایل قبلی را می بندد ( دیگر نیازی به fclose نخواهد داشت ) و دوباره آن را باز می کند و در صورتی که فایلی باز نشده باشد و یا اشارهگر فایلِ آن را به freopen نفرستیم باید از جریان ورودی/خروجی استاندارد stdin و stdout و stderr استفاده کنیم تا از فایلی متنی ، بخوانیم یا داخل آن ، متنی را بنویسیم . طبق استاندارد ، استفاده از حالت دودویی ، تعریف نشده است و پیادهسازها در شبهیونیکسها آن را نادیده گرفته و ویندوز نیز تنها به نادیده گرفتن شکسته شدن خط در پایان هر خط متن ، بسنده می کند ( البته برخی سیستم عاملها از آن پشتیبانی می نمایند )
شکل کلی استفاده از تابع freopen بدین صورت می باشد :
{{چپچین}}
freopen(const char * filename, const char * mode, FILE * stream);
{{پایان چپچین}}
می شود گفت همانند fopen است و mode های آن ( یعنی حالتهای باز کردن فایل آن ) همانند fopen در همین مبحث فایل سرآیند stdio می باشد ( با این تفاوت که همان طور که گفته شد حالت دودویی و خام باز نمیکند و البته می تواند از ورودی خروجی استاندارد جهت نوشتن و یا خواندن استفاده کند )
مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main(void)
{
FILE *fp, *fp2;
fp = fopen("example.txt", "r");
if (fp == NULL)
{
perror("File couldn't be opened");
return 1;
}
fp2 = freopen("example.txt", "a", fp);
fputs("4th sentence", fp2);
fclose(fp2);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
'''توضیح :''' در مثال بالا ۲ اشارهگر فایل را آماده ایجاد نموده و اولی را با باز کردن فایل متنی example.txt که کمی پیشتر آن را ایجاد نمودیم با حالت خواندن متنی به پایان رساندهایم . اشارهگر فایل دوم با freopen با حالت اضافه کردن باز شده است و سپس توسط تابع fputs جمله 4th sentence در خط چهارم اضافه شده است و سپس fp2 را بستهایم و نیازی به بستن fp نیست چون freopen آن را بسته است . تابع اصلی برنامه با موفقیت به پایان رسیده است . اگر فایل متنی example.txt را باز کنید حالا به جای ۳ خط ، ۴ خط دارد
مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include <stdio.h>
int main()
{
FILE * fp = freopen("copy.txt", "w", stdout);
if (fp == NULL)
{
perror("File couldn't be open");
return 1;
}
printf("This text will replace content of copy.txt");
fclose(fp);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
'''توضیح :''' فایل copy.txt را که در قسمت قبل ، ایجاد کردیم را جهت نوشته شدن مجدد با حالت نوشتن و جریان خروجی استاندارد جهت خارج کردن - نوشتن - متن به فایل باز کردهایم . از اینجا به بعد هر آنچه که در خروجیخط دستوری ، دستور بدهیم تا نمایش داده شود در فایل copy.txt نوشته خواهد شد تا زمانی که اشارهگر فایل خود را ببندیم که ما نیز همین کار را کردهایم . حال اگر فایل متنی copy.txt را باز کنید در آن نوشته شده است : This text will replace content of copy.txt یعنی « این متن ، جایگزین محتوای فایل copy.txt خواهد شد » و اگر فایل را باز کنید همین متن را خواهید دید . تابع اصلی برنامه را با موفقیت به پایان رساندهایم
مثال :
{{چپچین}}
<syntaxhighlight lang=c>
#include<stdio.h>
int main()
{
FILE * fp = freopen("example.txt", "r", stdin);
if (fp == NULL)
{
perror("File couldn't be found");
return 1;
}
char text[150];
while(fgets(text, sizeof(text), stdin) != NULL)
{
printf("%s", text);
}
fclose(fp);
return 0;
}
</syntaxhighlight>
{{پایان چپچین}}
'''توضیح :''' فایل example.txt را جهت خوانده شدن و با جریان ورودی - خواندن - استاندارد stdin باز نمودهایم تا از فایل وارد کنیم . رشته text را با ۱۵۰ عنصر ، اعلان نمودهایم . با حلقه while تابع fgets را اجرا نمودهایم تا متن بخواند و تا زمانی که مقدار دریافتی آن تهی ( نول NULL ) نباشد در خروجی خطدستوری ، متن را نمایش دهد که همان ۴ خطی است که در مثال پیشتر از پیش آن را بازنویسی کردیم و خط چهارم را نیز به آن اضافه نمودیم . سپس فایل fp را بسته و تابع را با موفقیت به پایان رساندهایم
[[رده:زبان برنامه نویسی سی]]
1oi6n41zjesqlgucu3gn9q4rqcwfrxt
ویکیکتاب:میز تحریر
4
41152
134489
134444
2026-07-24T12:24:24Z
MediaWiki message delivery
6433
/* Request for comment (the future of Abstract Wikipedia) */ بخش جدید
134489
wikitext
text/x-wiki
{| class="plainlinks" style="background:transparent; width:100%; border: 2px ridge #A7D7F9; "
|-
| colspan=2 style="vertical-align: top; background-color:#F0F2F5;text-align:center;font-size:9pt;border: 2px #A7D7F9;"|
{{میانبر|وک:مت}}
[[تصویر:Polarstern library hg.jpg|left|200px|link=ویکیکتاب:میز تحریر]]
[[تصویر:Gnome-applications.svg|right|140px|link=ویکیکتاب:میز تحریر]]
'''ردکردن به:''' [[#toc|فهرست بحثها]] {{ن}} [[#below_toc|آغاز بحثها]]{{ن}}[[#footer|پایین صفحه]]{{ن}}'''[{{fullurl:{{FULLPAGENAME}}|action=edit§ion=new}} افزودن بحث تازه]'''<br/>
{{Purge|پاکسازی میانگیر برای تازهکردن صفحه}}
----
<big>میز تحریر در ویکیکتاب، مکانی برای مطرح کردن سوالات عمومی، درخواست راهنمایی {{سخ}}و اظهار نظر از دیگر کاربران، و بحث بر سر مسایل مختلفی است که در ویکیکتاب اهمیت دارد.</big>
|-
| style="vertical-align: top; background-color:#F6F6F6;font-size:9pt;"|
<div style="padding:1px 10px; text-align:right; font-size: 13pt; border-bottom:1px solid #A7D7F9; background:#E8F2F8; color:#534741;">استفاده از این صفحه</div>
*بحثهای جدید را به '''انتهای''' این صفحه بیفزایید.
*'''[{{SERVER}}{{localurl:{{ns:project}}:میز تحریر|action=edit§ion=new}} برای افزودن بحث تازه اینجا کلیک کنید.]'''
<div style="padding:1px 10px; text-align:right; font-size: 13pt; border-bottom:1px solid #A7D7F9; background:#E8F2F8; color:#534741;">بایگانی</div>
{{جعبه بایگانی|
[[/بایگانی۱|بایگانی۱]]{{*}}
[[/بایگانی۲|بایگانی۲]]{{*}}
[[/بایگانی۳|بایگانی۳]]{{*}}
[[/بایگانی۴|بایگانی۴]]{{*}}
[[/بایگانی۵|بایگانی۵]]{{*}}
[[/بایگانی۶|بایگانی۶]]{{*}}
[[/بایگانی۷|بایگانی۷]]{{*}}
[[/بایگانی۸|بایگانی۸]]{{*}}
[[/بایگانی۹|بایگانی۹]]{{*}}
[[/بایگانی۱۰|بایگانی۱۰]]{{*}}
[[/بایگانی۱۱|بایگانی۱۱]]{{*}}
[[/بایگانی۱۲|بایگانی۱۲]]{{*}}
[[/بایگانی۱۳|بایگانی۱۳]]{{*}}
[[/بایگانی۱۴|بایگانی۱۴]]{{*}}
[[/بایگانی۱۵|بایگانی۱۵]]{{*}}
[[/بایگانی۱۶|بایگانی۱۶]]{{*}}
[[/بایگانی۱۷|بایگانی۱۷]]{{*}}
[[/بایگانی۱۸|بایگانی۱۸]]{{*}}
[[/بایگانی۱۹|بایگانی۱۹]]{{*}}
[[/بایگانی۲۰|بایگانی۲۰]]{{*}}
[[/بایگانی۲۱|بایگانی۲۱]]{{*}}
[[/بایگانی۲۲|بایگانی۲۲]]
}}
<inputbox>
type=fulltext
bgcolor=transparent
prefix=ویکیکتاب:میز تحریر
break=no
searchbuttonlabel=جستجو در بایگانیهای میز تحریر
</inputbox>
|}
==ویکیکتاب فارسی بیست و یک ساله شد==
بیش از ۲۰ سال از راهاندازی ویکیکتاب فارسی میگذرد. پارسال [[ویکیکتاب:ستاد برگزاری بیستمین سالگرد ویکیکتاب|بیستسالگی]] آن را جشن گرفتیم. اکنون ویکیکتاب فارسی در رتبه ۱۶ هست و یکی از موفقترین پروژههای پارسی بنیاد ویکیمدیا است. ویکیکتاب، یک پروژه مبتنی بر ویکی است که توسط سازمان ناسودبر بنیاد ویکیمدیا اداره میشود. البته همچنان مشکلاتی نیز پس از گذشت سالها گریبانگیر ویکیکتاب است از جمله اینکه معیارهای سرشناسی در ویکیکتاب هنوز به طور دقیق مشحص نیست. هنوز به دقت مشخص نشده است چه صفحههایی سرشناسی کافی دارند و چه صفحههایی سرشناسی ندارند. به طور کلی تا مشخص شدن معیارهای سرشناسی ویکیکتاب، بهتر است به کتاب های با موضوع سیاسی و اجتماعی که به مسائل روز میپردازند اجازه نشر ندهیم زیرا چنین کتاب هایی معمولا هدف آموزشی ندارند.
[[پرونده:TRABAJO COLABORATIVO.jpg|250px|بیقاب|وسط]]
در ویکیکتاب، ممکن است درباره یک موضوع چند کتاب مختلف وجود داشته باشد اما نوشتن داستان و سفرنامه در این وبگاه ممنوع است. تا حد امکان در صفحههای کتاب، از دادن پیوندهای بیرونی خودداری میشود. ایبوک یا کتاب الکترونیکی، پدیدهای کاملاً تازهاست و انتظار میرود تا نظام آموزش و اطلاعرسانی را در ایران همانند سایر کشورها با دگرگونیهایی اساسی مواجه سازد. کتابخانه دیجیتال کتابخانه ای است که در آن اسناد و منابع به جای کاغذ یا سایر رسانهها به صورت الکترونیکی ذخیره شدهاند. به کتابخانه دیجیتال، کتابخانه آنلاین یا کتابخانه اینترنتی نیز میگویند. جستجو در این کتابخانهها به مراتب آسانتر از کتابخانههای سنتی است. ویکیکتاب یک کتابخانه دیجیتال است که نسخه انگلیسی آن نزدیک به ۱۰۰ هزار صفحه مفید دارد ولی نسخه فارسی آن هنوز ۳ هزار و پانصد صفحه مفید دارد.
پروژه ویکیکتاب اگرچه نسخههایی به زبانهای دیگر نیز دارد ولی هر زبان مستقل عمل میکند. این طور نیست که ویکیکتاب فارسی بر طبق سیاستها و رهنمودهای آلمانی یا انگلیسی عمل کند. در [[ویکیکتاب:نظرخواهی/نویسنده کتاب|یکی از نظرخواهیها (نظرخواهی برای تصمیم گرفتن درباره درج نام نویسنده یا نویسندگان)]] یک کاربر پیشنهاد داد از رهنمود ویکیکتاب انگلیسی استفاده کنیم (بگذریم که ویکیکتاب انگلیسی خود رهنمود مشخصی ندارد برای این منظور) اساسا نظرخواهی برای چیست؟ جامعه کاربری ویکیکتاب فارسی نظرش مهم نیست؟ در این خلاصه خواستم تأکید کنم ما در ویکیکتاب فارسی خودمان برای خودمان تصمیم میگیریم و چیزی را ترجمه نمیکنیم و اگر ترجمه ای انجام شود اول باید توسط کاربران همین ویکی [[ویکیکتاب:خودآموز/بحث و اجماع|تأیید یا تغییر داده شود]]. شایان ذکر است بخش نظرخواهی ویکیکتاب فارسی در سال ۱۳۹۲ راهاندازی شد تا کاربران بتوانند در تصمیمگیریهای راهبردی مشارکت کنند.
در سال ۱۴۰۳ پروانه تمام فایلهای بارگزاری شده اعم از نگاره، فایل صوتی، پیدیاف، ... از گنو (GFDL) به کریتیو کامنز (CC ویرایش چهارم) تغییر کرد و از آن پس، پروژههای ویکیمدیا دیگر از پروانه گنو استفاده نکردند.
--[[کاربر:Doostdar|دوستدار ایران بزرگ]] [[بحث کاربر:Doostdar|☎]] یکشنبه،۱۱ خرداد ۱۴۰۴، ساعت ۰۱:۱۳ (ایران) ۳۱ مهٔ ۲۰۲۵، ساعت ۲۰:۴۳ (UTC)
__NEWSECTIONLINK__
[[en:Wikibooks:Reading room/General]]
== شروع حمله اسرائیل به ایران ==
[[پرونده:Al-Tabieen school massacre 05.jpg|250px|بندانگشتی|چپ|اجساد تکه تکه شده نسلکشی فلسطین توسط نظامیان اسرائیلی]]
در ساعات اولیهٔ صبح روز ۲۳ خرداد ۱۴۰۴ اسرائیل با چند فروند هواپیمای نظامی به ایران حمله کرد. در پی این حمله انفجارهایی در سراسر تهران گزارش شد، از جمله در نزدیکی پایگاههای نظامی و محلههایی که فرماندهان ارشد نظامی در آن سکونت داشتند. برخی از دولتها، اسرائیل را به دلیل این حمله محکوم کردند. [[کاربر:Doostdar|دوستدار ایران بزرگ]] [[بحث کاربر:Doostdar|☎]] یکشنبه،۲۵ خرداد ۱۴۰۴، ساعت ۲۱:۳۴ (ایران) ۱۵ ژوئن ۲۰۲۵، ساعت ۱۷:۰۴ (UTC)
:پس از حدود دو هفته، جنگ متوقف شد. نکته جالب، ظهور افراد خائن (وطنفروشان) بود که از روشهای مختلف در این مدت کوتاه با دشمن همکاری کردند و تعدادی از آنها که شناسایی شدند به مجازات رسیدند. [[کاربر:Doostdar|دوستدار ایران بزرگ]] [[بحث کاربر:Doostdar|☎]] پنجشنبه،۵ تیر ۱۴۰۴، ساعت ۱۹:۳۷ (ایران) ۲۶ ژوئن ۲۰۲۵، ساعت ۱۵:۰۷ (UTC)
::{{شعر}}
::{{ب|{{نستعلیق|وطن بسوزد و من در خروش و جوش نباشم}}|{{نستعلیق|خدا کند که بمیرم وطنفروش نباشم}}}}
::{{پایان شعر}} [[کاربر:Doostdar|دوستدار ایران بزرگ]] [[بحث کاربر:Doostdar|☎]] جمعه،۱۳ تیر ۱۴۰۴، ساعت ۱۸:۲۱ (ایران) ۴ ژوئیهٔ ۲۰۲۵، ساعت ۱۳:۵۱ (UTC)
== موفقترین پروژههای ویکیمدیا ==
به نظر میرسد ویکیسفر، ویکیکتاب، ویکیپدیا، ویکینبشته و ویکیگفتاورد موفقترین پروژههای پارسی باشند. [[کاربر:Doostdar|دوستدار ایران بزرگ]] [[بحث کاربر:Doostdar|☎]] دوشنبه،۹ تیر ۱۴۰۴، ساعت ۱۳:۴۸ (ایران) ۳۰ ژوئن ۲۰۲۵، ساعت ۰۹:۱۸ (UTC)
== قربانی قتل ناموسی ==
یک جوان هفده ساله در مشهد قربانی قتل ناموسی شد. محمدجواد ایزانلو در خیابان رسالت به دلیل رابطه دوستی توسط یک پسر به قتل رسید. یک نوجوان دیگر به دلایل ناموسی دست به این قتل زد. اگر به ویکیپدیا نگاه کنید هیچ مقالهای درباره این قتل پیدا نمی کنید اما در مورد قتل های ناموسی دیگر مثل قتل مونا حیدری در اهواز حتما مقاله ایجاد کردهاند. رویکرد فمینیستی در ویکیپدیای فارسی دلیل این موضوع است. [[کاربر:Doostdar|دوستدار ایران بزرگ]] [[بحث کاربر:Doostdar|☎]] شنبه،۱۴ تیر ۱۴۰۴، ساعت ۲۲:۰۷ (ایران) ۵ ژوئیهٔ ۲۰۲۵، ساعت ۱۷:۳۷ (UTC)
:در سال ۱۳۹۹ در زمینهای کشاورزی اطراف روستای عباسآباد مشهد یک مرد ۳۸ ساله توسط خانواده دختر به دلیل ازدواج با دخترشان به قتل رسیده است ولی این هم مقالهای در ویکیپدیا ندارد. گویا ویکینویسهای فارسی، فمنیست هستند و به مذاقشان خوش نمیآید! [[w:fa:قتل ناموسی در ایران|به ویکیپدیا بروید و خودتان ببینید]]. [[کاربر:Doostdar|دوستدار ایران بزرگ]] [[بحث کاربر:Doostdar|☎]] شنبه،۱۴ تیر ۱۴۰۴، ساعت ۲۲:۱۸ (ایران) ۵ ژوئیهٔ ۲۰۲۵، ساعت ۱۷:۴۸ (UTC)
:درود بر شما
:فکر نکنم برچسب زدن به ویکی پدیا و یک اندیشه (فمینیست) کار درستی باشد، اگر مقاله ای در این مورد نوشته نشده دلیلش میتواند رسانه ای نشدن این نام ها باشد. زیرا رسانه های زرد بیشتر بدنبال محتوای زرد میگردند و قتل یک مرد محتوای زرد نیست (مگر در مواردی عجیب).
:رسانه هم دلیلی است اما دلیلی دیگر وجود دارد به نام "جامعه" جامعه که به این اخبار اهمیت نمیدهد و بدنبال اصلاح نیست.
:پس بجای اینکه به یک اندیشه یا شخص برچسب زده شود بهتر است جامعه اصلاح شود تا بتواند هر چیز را اصلاح کند. شاید بعضی از اعضا فمینیست باشند اما هیچ قانون و منطقی اجازه برخورد با آن ها را نمیدهد. [[کاربر:Fwldom|Fwldom]] ([[بحث کاربر:Fwldom|بحث]]) ۶ ژوئیهٔ ۲۰۲۵، ساعت ۱۴:۳۸ (UTC)
== صفحههای ویژه ==
:پیوند به [[Special:SpecialPages|صفحههای ویژه]]
[[کاربر:Doostdar|دوستدار ایران بزرگ]] [[بحث کاربر:Doostdar|☎]] دوشنبه،۱۶ تیر ۱۴۰۴، ساعت ۱۶:۲۲ (ایران) ۷ ژوئیهٔ ۲۰۲۵، ساعت ۱۱:۵۲ (UTC)
== نگارههایی از همایش ویکیکتاب در اندونزی (آگست ۲۰۲۵) ==
[[پرونده:Dokumentasi WikiLatih WikiBuku Jember 2.jpg|250px|بیقاب|چپ]]
[[پرونده:Dokumentasi WikiLatih WikiBuku Makassar 2.jpg|250px|بیقاب|راست]]
{{سخ}}
--[[کاربر:Doostdar|دوستدار ایران بزرگ]] [[بحث کاربر:Doostdar|☎]] سهشنبه،۱۴ مرداد ۱۴۰۴، ساعت ۱۲:۲۵ (ایران) ۵ اوت ۲۰۲۵، ساعت ۰۷:۵۵ (UTC)
== آبانگان روز نکوداشت آناهیتا ایزدبانوی آبها ==
[[پرونده:Anahita Vessel, 300-500 AD, Sasanian, Iran, silver and gilt - Cleveland Museum of Art - DSC08130.JPG|بندانگشتی|راست|نگارهای از آناهیتا بر روی کوزهای باستانی]]
[[پرونده:Fuman anahita.jpg|500px|بندانگشتی|چپ|تندیسی از ایزدبانو آناهیتا]] [[کاربر:Doostdar|دوستدار ایران بزرگ]] [[بحث کاربر:Doostdar|☎]] شنبه،۱۷ آبان ۱۴۰۴، ساعت ۱۲:۴۵ (ایران) ۸ نوامبر ۲۰۲۵، ساعت ۰۹:۱۵ (UTC)
==شب یلدا (۲۱ دسمبر)==
شب یلدا یا شب چله یکی از کهنترین جشنهای ایرانی است که هر سال با فرا رسیدن بلندترین شب سال برگزار میشود. مراسم شب یلدا از غروب آفتاب ۳۰ آذر آغاز شده و تا طلوع آفتاب ۱ دی ادامه مییابد. در این شب، ایرانیان میوهها و خشکبار مانند انار، هندوانه و خرمالو را آماده کرده و در دورهمی دوستانه میخورند؛ این میوهها نمادی از زندگی، انرژی و امید هستند. در برخی مناطق اعتقاد بر این است که چهل نوع خوراکی باید در مراسم شب چله آماده باشد. رنگ قرمز این میوهها نماد رنگهای سرخ سپیدهدم و تابش زندگی است.
<div style="font-size:large">
[[پرونده:Flickr_-_Government_Press_Office_(GPO)_-_Pomegranate_Fruits.jpg|350px|بندانگشتی|چپ|شب یلدا خجسته باد]]
* {{رنگی|آبی}}Happy Yalda Night{{رنگی/پ}}
* {{رنگی|سبز}}Feliz Yaldá{{رنگی/پ}}
* {{رنگی|زرد}}С Ялда{{رنگی/پ}}
* {{رنگی|قرمز}}جه ژنی شەوی یەڵدا{{رنگی/پ}}
* {{رنگی|خاکستری}}Yelda gece mübarək olsun{{رنگی/پ}}
* {{رنگی|بنفش}}یلدا گئجهسی موبارك اولسون{{رنگی/پ}}
* {{رنگی|قرمز}}Шáби Ялдó Мoбаpаc{{رنگی/پ}}
</div>
--[[کاربر:Doostdar|دوستدار ایران بزرگ]] [[بحث کاربر:Doostdar|☎]] جمعه،۲۸ آذر ۱۴۰۴، ساعت ۱۲:۲۲ (ایران) ۱۹ دسامبر ۲۰۲۵، ساعت ۰۸:۵۲ (UTC)
== ویکیکتابهای برتر (۲۰۲۵ میلادی)==
همانطور که در جدول زیر نشان داده شده است نسخههای ویکیکتاب به زبانهای مختلف از نظر کمی به سرعت در حال رشد هستند به گونهای که ویکیکتاب انگلیسی نزدیک به ۱۰۰ هزار صفحه دارد. اعداد نوشته شده در جدول بر حسب هزار صفحه است.
[[پرونده:Wikibooks-logo-fa2.svg|200px|بندانگشتی|چپ|ویکیکتاب]]
{|class="wikitable sortable"
|-
! نام ویکیکتاب!! ۲۰۲۴ میلادی!! ۲۰۲۵ میلادی
|-
| انگلیسی
|۹۷
|۹۸
|-
| مجاری
|۳۹
|۴۵
|-
| آلمانی
|۳۱
|۳۳
|-
| فرانسوی
|۱۹
|۲۱
|-
| ایتالیایی
|۱۶
|۱۹
|-
| ژاپنی
|۱۴
|۱۷
|-
| پرتغالی
|۱۳
|۱۳
|-
| اسپانیایی
|۹
|۹
|-
| هلندی
|۹
|۹
|-
| اندونزیایی
|۵
|۵
|-
| فارسی
|۳
|۳
|}
--[[کاربر:Doostdar|دوستدار ایران بزرگ]] [[بحث کاربر:Doostdar|☎]] دوشنبه،۱ دی ۱۴۰۴، ساعت ۰۱:۲۴ (ایران) ۲۱ دسامبر ۲۰۲۵، ساعت ۲۱:۵۴ (UTC)
==جشن سده (۳۰ جنوئری)==
[[پرونده:Sadeh Festival in Shiraz 2020-01-30 05.jpg|200px|بندانگشتی|چپ|جشن سده خجسته باد]]
'''سد به سده، سی به گله پنجاه به نوروز'''
<div style="font-size:large">
* {{رنگی|سبز}}جشن سده خجسته باد{{رنگی/پ}}
* {{رنگی|آبی}}Happy Sadeh{{رنگی/پ}}
* {{رنگی|زرد}}Ҷашни Сада Мoбаpаc{{رنگی/پ}}
* {{رنگی|قرمز}}Félicitations pour Sadeh{{رنگی/پ}}
* {{رنگی|سبز}}С Новым Содо{{رنگی/پ}}
* {{رنگی|بنفش}}bimbarek Sadeh{{رنگی/پ}}
</div> [[کاربر:Doostdar|دوستدار ایران بزرگ]] [[بحث کاربر:Doostdar|☎]] جمعه،۱۰ بهمن ۱۴۰۴، ساعت ۲۰:۰۵ (ایران) ۳۰ ژانویهٔ ۲۰۲۶، ساعت ۱۶:۳۵ (UTC)
== همدردی با مردم برای از دست رفتگان در جنگ ==
[[پرونده:Shajareh Tayyebeh school in Minab photos from Mehr (12).jpg|بندانگشتی|چپ|گوشهای از آثار جنگ (میناب)]]
درود. کشته شدن تعدادی از هموطنان در جنگ تحمیلی سوم را که منجر به تشدید بحران در خاورمیانه و غرب آسیا شده است تسلیت میگویم. --[[کاربر:Vivairan2|Vivairan2]] ([[بحث کاربر:Vivairan2|بحث]]) ۴ ژوئن ۲۰۲۶، ساعت ۰۸:۲۴ (UTC)
== آثاری که با همکاری کاربران تکمیل میشود (تیر ۱۴۰۵) [[پرونده:Wikibooks-logo-fa2.svg|20px]] ==
[[پرونده:Couverture-wikimedia.jpg|بیقاب|چپ]]
هماکنون ۵۳ کتابچه [[ویکیکتاب:ایبوکها بر حسب وضعیت تکمیلشدگی|در حال تکمیل شدن هستند]]. [[کاربر:Vivairan2|Vivairan2]] ([[بحث کاربر:Vivairan2|بحث]]) ۲۹ ژوئن ۲۰۲۶، ساعت ۰۵:۱۴ (UTC)
:اگر قصد مشارکت در نوشتن یا ویرایش یکی از این ایبوکها رو دارید اعلام کنید. [[کاربر:Vivairan2|Vivairan2]] ([[بحث کاربر:Vivairan2|بحث]]) ۵ ژوئیهٔ ۲۰۲۶، ساعت ۰۵:۰۷ (UTC)
:چهارچوب اصلی محتوای هر ایبوک با توجه به فهرستی که در صفحه اول قرار داده شده مشخص شده است. [[کاربر:Vivairan2|Vivairan2]] ([[بحث کاربر:Vivairan2|بحث]]) ۵ ژوئیهٔ ۲۰۲۶، ساعت ۰۵:۰۸ (UTC)
:تعداد زیرصفحه هایی که در هر ایبوک تا کنون ایجاد شده و نیز موضوع ایبوک مشخص شده. لطفا با توجه به اطلاعات و توانایی هایی که در نوشتن دارید اقدام به مشارکت کنید. [[کاربر:Vivairan2|Vivairan2]] ([[بحث کاربر:Vivairan2|بحث]]) ۵ ژوئیهٔ ۲۰۲۶، ساعت ۰۵:۱۰ (UTC)
:در پایین صفحه نام آخرین ایبوک هایی که در چند سال گذشته توسط کاربران در ویکیکتاب تکمیل شدهاند در یک جدول جداگانه نوشته شده است. [[کاربر:Vivairan2|Vivairan2]] ([[بحث کاربر:Vivairan2|بحث]]) ۵ ژوئیهٔ ۲۰۲۶، ساعت ۰۵:۱۶ (UTC)
:میزان توسعه برای ایبوکهای در حال تکمیل به صورت تقریبی میباشد و وضعیت آنها به صورت در حال انجام نشان میدهد نیاز به مشارکت کاربران نویسنده دارد. [[کاربر:Vivairan2|Vivairan2]] ([[بحث کاربر:Vivairan2|بحث]]) ۵ ژوئیهٔ ۲۰۲۶، ساعت ۰۵:۲۴ (UTC)
== درگاههای علمی ویکیپدیا ==
بعضی از درگاههای علمی ویکیپدیا که برای موضوعات علمی قابل استفاده هستن. اگر قصد نوشتن یا ویرایش کتابی تو ویکیکتاب رو دارید می تونید از این درگاه ها کمک بگیرید:
{| class="wikitable" style="font-size: 95%"
!'''نام درگاه'''||'''موضوع'''||'''توضیحات'''
|-
||''[[W:fa:درگاه:دانش|دانش]]''|| دانش|| موضوعات مختلف علمی همچون اخترشاسی، زمینشناسی، الخ
|-
||''[[w:fa:درگاه:اخترشناسی|اخترشناسی]]''|| اخترشناسی|| پدیدههای آسمانی از جمله ستارگان، سیارات، دنبالهدار، کهکشانها و پدیدههایی مانند شفق قطبی
|-
||''[[w:fa:درگاه:جغرافیا|گیتاشناسی]]''|| گیتاشناسی|| جغرافیا دانشیاست دربارهٔ سطح زمین و پدیدههای طبیعی، آبوهوا، رستنیها، خاک، فراوردهها؛ شهرها و کشورها و قاره ها
|-
||''[[W:fa:درگاه:ریاضیات|ریاضیات]]''|| ریاضیات|| هندسه، آمار، توابع مثلثاتی، جبر، حساب دیفرانسیل و انتگرال، الخ
|-
||''[[W:fa:درگاه:حسابداری|حسابداری]]''|| حسابداری|| حسابداری، تجارت، حسابرسی، الخ
|-
||''[[w:fa:درگاه:شیمی|شیمی]]''|| شیمی|| عنصرهای شیمیایی و ترکیبهای شیمیایی شامل اتمها، مولکولها و برهمکنش میان آنها
|-
||''[[w:fa:درگاه:تاریخ|تاریخ]]''|| تاریخ|| باستانشناسی، تاریخ ایران، تاریخ هنر، تاریخ جنگ، الخ
|-
||''[[W:fa:درگاه:پزشکی|پزشکی]]''|| پزشکی|| شناخت بیماریها، تشخیص، درمان و جلوگیری از بروز آنها
|-
||''[[w:fa:درگاه:فیزیک|فیزیک]]''|| فیزیک|| مفهومهایی همچون انرژی و نیرو که در چگونگی و نوع رفتار ماده تاثیرگذارند
|-
||''[[w:fa:درگاه:پرستاری|پرستاری]]''|| پرستاری|| اصول علمی و مهارتهای حرفهای مراقبت، درمان و آموزش بیماران
|-
||''[[w:fa:درگاه:فناوری|فناوری]]''|| فناوری|| شیوه و شگرد ساخت و کاربرد ابزار، دستگاهها، مادهها و فرایندهای گرهگشای دشواریهای انسان
|-
||''[[w:fa:درگاه:رایانه|رایانه]]''|| رایانه|| سختافزار، نرمافزار، تعامل انسان و رایانه، انواع رایانه، رایانش، الخ
|-
||''[[w:fa:درگاه:انرژی|انرژی]]''|| انرژی|| یک کمیت بنیادین فیزیکی شامل انرژی جنبشی، انرژی پتانسیل، انرژی گرمایی، انرژی شیمیایی و انرژی هستهای، الخ
|-
||''[[w:fa:درگاه:زیستشناسی|زیستشناسی]]''|| زیستشناسی|| فیزیولوژی، بومشناسی، زیستشناسی مولکولی و سلولی، زیستشیمی، ژنتیک، الخ
|-
||''[[w:fa:درگاه:اینترنت|اینترنت]]''|| اینترنت|| اینترنت سامانهای جهانی از شبکههای رایانهای بهم پیوستهاست که از مجموعه پروتکل اینترنت برای ارتباط با یکدیگر استفاده مینمایند
|-
||''[[w:fa:درگاه:داروسازی و داروشناسی|داروسازی و داروشناسی]]''|| داروسازی و داروشناسی|| داروشناسی شاخهای از داروسازی و زیستشناسی است که به مطالعه واکنش متقابل داروها بر موجودات زنده میپردازد.
|-
||''[[w:fa:درگاه:علوم زمین|علوم زمین]]''|| علوم زمین|| علوم زمین گونهای خاص از سیارهشناسی است که به مطالعهٔ ساختار و ترکیبات زمین، خاستگاه، ویژگیهای فیزیکی، ... میپردازد.
|} [[کاربر:Vivairan2|Vivairan2]] ([[بحث کاربر:Vivairan2|بحث]]) ۵ ژوئیهٔ ۲۰۲۶، ساعت ۰۵:۰۶ (UTC)
== چرا ویکیکتاب؟ ==
«باید درهای علم به روی همه باز باشد، هرجا مزرعه هست، هرجا آدم هست، آنجا کتاب هم باید باشد.»
: ''ویکتور هوگو''
[[کاربر:Vivairan2|Vivairan2]] ([[بحث کاربر:Vivairan2|بحث]]) ۵ ژوئیهٔ ۲۰۲۶، ساعت ۰۶:۰۲ (UTC)
== ویکیکتابهای برتر (۲۰۲۵ میلادی) با میزان رشد ==
همانطور که در جدول زیر نشان داده شده است نسخههای ویکیکتاب به زبانهای مختلف از نظر کمی به سرعت در حال رشد هستند به گونهای که ویکیکتاب انگلیسی نزدیک به ۱۰۰ هزار صفحه دارد. اعداد نوشته شده در جدول بر حسب هزار صفحه است.
[[پرونده:Wikibooks-logo-fa2.svg|200px|بندانگشتی|چپ|ویکیکتاب]]
{|class="wikitable sortable"
|-
! نام ویکیکتاب!! ۲۰۱۵ میلادی!! ۲۰۲۴ میلادی!! ۲۰۲۵ میلادی
|-
| انگلیسی
|۵۰
|۹۷
|۹۸
|-
| مجاری
|ن
|۳۹
|۴۵
|-
| آلمانی
|۲۲
|۳۱
|۳۳
|-
| فرانسوی
|۱۶
|۱۹
|۲۱
|-
| ایتالیایی
|ن
|۱۶
|۱۹
|-
| ژاپنی
|۱۰
|۱۴
|۱۷
|-
| پرتغالی
|۷
|۱۳
|۱۳
|-
| اسپانیایی
|ن
|۹
|۹
|-
| هلندی
|۶
|۹
|۹
|-
| اندونزیایی
|۳
|۵
|۵
|-
| فارسی
|۱
|۳
|۳
|} [[کاربر:Vivairan2|Vivairan2]] ([[بحث کاربر:Vivairan2|بحث]]) ۵ ژوئیهٔ ۲۰۲۶، ساعت ۰۶:۳۶ (UTC)
== همه چیز درباره خواندنیهای خوب ==
'''تقدیم به همه کاربران فعال ویکی کتاب'''
[[آموزش کار با گودریدز|گودریدز]] یک شبکه اجتماعی کتاب است، که کاربران در آن کتابهایی که خواندهاند را پیدا میکنند، به کتابها امتیاز میدهند، و کتابهای محبوب خود را به دوستان خود توصیه میکنند.
وبگاه گودریدز در دسامبر ۲۰۰۶ توسط اوتیس چندلر، یک مهندس نرمافزار و کارآفرین وب باز شد و در دسامبر ۲۰۰۷ بیش از ۶۵۰،۰۰۰ عضو داشت و بیش از ۱۰،۰۰۰،۰۰۰ کتاب به آن افزوده شده بود. در ژوئیه ۲۰۱۲ اعلام شد که گودریدز ۱۰ میلیون عضو و ۲۰ میلیون بازدید ماهانه دارد. در ژوئیه ۲۰۱۳ در وبلاگ خود اعلام کردند که تعداد اعضای گودریدز از مرز ۲۰ میلیون نفر گذشته است. این رقم نشان دهنده ی این است که تعداد اعضای گودریدز در کمتر از یک سال دو برابر شده است.
در این شبکه اجتماعی کاربران به سه شکل میتوانند وضعیت مطالعه کتاب را نشان دهند؛ یا کتاب را پیشتر خواندهاند، یا در حال مطالعهاند، یا اینکه قرار است بعداً کتاب را بخوانند. کاربران میتوانند در مورد کتابها نظرشان را بنویسند و در کلوبهای مجازی بحث کنند. برای هر کتاب امکان امتیازدهی اعضا هم وجود دارد و کسانی که کتاب را مطالعه کردهاند به کتاب امتیاز میدهند.
از ویژگیهای این شبکه، امکان یافتن کتابهای قدیمی، کتابهای ناشران غیر رسمی، یا کتابهایی کمترشناختهشده در کنار دیگر کتابهای مشهور به زبانهای گوناگون است. [[کاربر:Vivairan2|Vivairan2]] ([[بحث کاربر:Vivairan2|بحث]]) ۵ ژوئیهٔ ۲۰۲۶، ساعت ۰۶:۵۴ (UTC)
== کپی ممنوع ==
{| class="wikitable"
|لطفا توجه کنید که در بیشتر موارد موارد کپی خطبهخط از وبگاهها، وبلاگها یا کتابها خلاف قانون حق تکثیر اینجا است. به جای کُپی-پیست کردن مطالب، میتوانید آن را با انشای خودتان به طور کامل بازنویسی کنید؛ البته آوردن مطلب با تغییر بسیار اندک، به طوری که نوشتهٔ جدید اثری منتج تلقی شود نیز هنوز در تضاد با قانون حق تکثیر است. --[[کاربر:Vivairan2|Vivairan2]] ([[بحث کاربر:Vivairan2|بحث]]) ۵ ژوئیهٔ ۲۰۲۶، ساعت ۰۷:۰۳ (UTC)
|}
== درگاه کتاب ==
[[w:fa:درگاه:کتاب|درگاه کتاب]] توضیحاتی درباره انواع کتاب، صنعت چاپ، گفتاورد درباره کتاب داره. نوشتار برگزیده این درگاه «محمد علی جمالزاده» و نگاره برگزیده اون یکی از نسخ قدیمی قرآن هست. حتما از این درگاه بازدید کنید. [[کاربر:Vivairan2|Vivairan2]] ([[بحث کاربر:Vivairan2|بحث]]) ۵ ژوئیهٔ ۲۰۲۶، ساعت ۰۷:۲۰ (UTC)
== نام ویکی از کجا اومده؟ ==
کانینگهام در ۲۵ مارس ۱۹۹۵ این نرمافزار (ویکی) را روی وبگاه شرکت خودش (کانینگهام اند کانینگهام) نصب کرد. کانینگهام به یاد مسئول باجه فرودگاه هونولولو که به او گفته بود برای رفتن به پایانه فرودگاه سوار اتوبوس ویکیویکی شود این نام را برگزید. ویکیویکی دوگانسازی واژه «ویکی» است که در زبان هاوایی به معنی تند و زود به کار میرود. [[کاربر:Vivairan2|Vivairan2]] ([[بحث کاربر:Vivairan2|بحث]]) ۵ ژوئیهٔ ۲۰۲۶، ساعت ۰۷:۲۹ (UTC)
== چرا ویکیپدیا نه؟ ==
(منظور از ویکیپدیا در اینجا، ویکیپدیای فارسیه) راهی که کاربران ویکیپدیای فارسی طی کردند ستودنی است اما افزایش جایگاه زبان فارسی در بین سایر ویکیپدیاها بعید به نظر میرسه (اکنون در جایگاه ۱۷ قرار دارد). برعکس، ویکیهای کوچکتر مثل ویکیکتاب فارسی روند رو به رشدی رو طی میکنند و در صورت مشارکت بیشتر، نیل به جایگاه های بهتر برای این پروژهها دور از انتظار نیست. در سالهای اخیر پربازدیدترین مقالههای ویکیپدیا مربوط به موضوع تفریح و سرگرمی، ترندهای سیاسی و جنجالی بوده و موضوعهای علمی جایگاه خوبی در بین مخاطبان ویکیپدیا نداشتهاند، در حالیکه بیشتر محتوای ویکیکتاب، علمی و آموزشیه و در ماه اخیر (شاید به علت رویداد کرونا و افزایش آموزش آنلاین دانشجویان) صفحههای مربوط به [[ریاضی پایه]] و [[اسید و باز]] جزو ۱۰ تای پربازدید ویکیکتاب فارسی بودند. این یکی از مهمترین انگیزههای ویکینویسها برای فعالیت در ویکیکتابه چون بسیاری از مقالههای علمی ویکیپدیا خُرد هستند و مطالب کافی ندارند. به نظر بنده با توجه به روند کنونی، دور از ذهن به نظر میرسه که مقاله های علمی بتونند در ویکیپدیا رشد کنند چرا که بیشتر ویرایشها در مقاله های سیاسی و اجتماعی انجام میشه و کمتر به موضوعهای علمی پرداخته میشه. [[کاربر:Vivairan2|Vivairan2]] ([[بحث کاربر:Vivairan2|بحث]]) ۵ ژوئیهٔ ۲۰۲۶، ساعت ۰۷:۳۳ (UTC)
== کاربر گرامی! ویکی برای تبلیغ شما نیست ==
شوربختانه در ویکی های فارسی مثل ویکی کتاب، ویکی گفتاورد، ویکی پدیا، ... ویرایش های خرابکارانه، توهین، فحش و تبلیغات بسیار زیاد هست و در مقایسه با زبان های دیگر میزان خرابکاری بیشتر است. همچنان که گزارش نشان داد مسئول بخش عمده ای از این خرابکاری ها و تبلیغات آیپی ها هستند ولی ممکن است نام کاربری هم بسازند و با نام کاربری اقدام به خرابکاری کنند. در هر صورت از کاربران دارای ویرایش مفید و سازنده دعوت میکنم با خرابکاران مبارزه کنند. [[کاربر:Vivairan2|Vivairan2]] ([[بحث کاربر:Vivairan2|بحث]]) ۵ ژوئیهٔ ۲۰۲۶، ساعت ۰۷:۳۶ (UTC)
==اگر قصد ایجاد کتاب جدیدی دارید ...==
{{جعبه هشدار|پیش از اینکه کتاب جدیدی در ویکیکتاب ایجاد کنید حتما سری به [[ویکیکتاب:ایبوکها بر حسب وضعیت تکمیلشدگی|این صفحه]] بزنید. اگر کتابی هست که موضوعی شبیه به موضوع دلخواه شما داشت میتونید محتوای خودتون رو به اون کتاب اضافه کنید. کتاب هایی که در جدول فهرست شدهاند هنوز تکمیل نشدهاند و در انتظار تکمیل شدن به دست کاربران ویکیکتاب چون شما هستند.}} [[کاربر:Vivairan2|Vivairan2]] ([[بحث کاربر:Vivairan2|بحث]]) ۵ ژوئیهٔ ۲۰۲۶، ساعت ۰۷:۴۰ (UTC)
== نکاتی برای درج تصویر و میانویکی ==
برای افزودن میانویکی به صفحات و زیر صفحات [[ویکیکتاب:همکاری با ویکیداده|این راهنما]] رو مطالعه کنید. میانویکیها در [[d:Wikidata:Main_Page|ویکیداده]] باید افزوده بشه.
برای افزودن تصویر [[ویکیکتاب:خودآموز/اضافه کردن عکس|این راهنما]] رو مطالعه کنید. تصویرها در [[w:fa:ویکیانبار|ویکیانبار]] یا ویکیکتاب باید بارگذاری بشه. [[کاربر:Vivairan2|Vivairan2]] ([[بحث کاربر:Vivairan2|بحث]]) ۵ ژوئیهٔ ۲۰۲۶، ساعت ۰۷:۴۳ (UTC)
== Request for comment (the future of Abstract Wikipedia) ==
<bdi lang="en" dir="ltr" class="mw-content-ltr">
Apologies if this has not yet been translated into your wiki's language. {{int:Please-translate}}
You are invited to voice your opinions in a [[:m:Requests for comment/The future of Abstract Wikipedia|request for comment about the future of Abstract Wikipedia]]. {{Int:Feedback-thanks-title}}
[[:m:User:Kowal2701|Kowal2701]] ([[:m:User talk:Kowal2701|talk]]) ۲۴ ژوئیهٔ ۲۰۲۶، ساعت ۱۲:۲۴ (UTC)
</bdi>
<!-- پیام توسط کاربر:DreamRimmer@metawiki با استفاده از فهرست در https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=30513860 ارسال شده است -->
q0ezvlgurnmblxqhi4rennc0ki5d8t3
تاریخ علم (نشریه)
0
42015
134500
134488
2026-07-25T06:45:52Z
Ələddin.Məlikov
21420
134500
wikitext
text/x-wiki
'''تاریخ علم (نشریه)'''
* [[/مجله علمی پژوهشی تاریخ علم - سال ۲۰۲۰/]]
* [[/مجله علمی پژوهشی تاریخ علم - سال ۲۰۲۱/]]
* [[/مجله علمی پژوهشی تاریخ علم - سال ۲۰۲۲/]]
[[رده:تاریخ علم (نشریه)]]
5bh8iy5gkxidvd7sykyr2xy0buuil62
متافیزیکا (نشریه)
0
42016
134491
134487
2026-07-25T06:16:38Z
Ələddin.Məlikov
21420
134491
wikitext
text/x-wiki
'''متافیزیکا (نشریه)'''
* [[/مجله بینالمللی متافیزیکا - سال ۲۰۱۸/]]
* [[/مجله بینالمللی متافیزیکا - سال ۲۰۱۹/]]
* [[/مجله بینالمللی متافیزیکا - سال ۲۰۲۰/]]
* [[/مجله بینالمللی متافیزیکا - سال ۲۰۲۱/]]
nt2bmed6fenw6nu8a6ncw276h9z68ts
134494
134491
2026-07-25T06:22:51Z
Ələddin.Məlikov
21420
134494
wikitext
text/x-wiki
'''متافیزیکا (نشریه)'''
* [[/مجله بینالمللی متافیزیکا - سال ۲۰۱۸/]]
* [[/مجله بینالمللی متافیزیکا - سال ۲۰۱۹/]]
* [[/مجله بینالمللی متافیزیکا - سال ۲۰۲۰/]]
* [[/مجله بینالمللی متافیزیکا - سال ۲۰۲۱/]]
[[رده:متافیزیکا (نشریه)]]
4aja2obu7gygbudw5kqgdf9j1zrp7cq
متافیزیکا (نشریه)/مجله بینالمللی متافیزیکا - سال ۲۰۱۸
0
42017
134492
2026-07-25T06:19:20Z
Ələddin.Məlikov
21420
صفحهای تازه حاوی «{{سرصفحه | عنوان =مجله بینالمللی متافیزیکا - سال ۲۰۱۸ | قسمت = | قبلی = | بعدی = [[متافیزیکا (نشریه)/مجله بینالمللی متافیزیکا - سال ۲۰۱۸|مجله بینالمللی متافیزیکا - سال ۲۰۱۹]] | یادداشت = [[متافیزیکا (نشریه)]] }} [[رده:متافیزیکا (نشریه)]]» ایجاد کرد
134492
wikitext
text/x-wiki
{{سرصفحه
| عنوان =مجله بینالمللی متافیزیکا - سال ۲۰۱۸
| قسمت =
| قبلی =
| بعدی = [[متافیزیکا (نشریه)/مجله بینالمللی متافیزیکا - سال ۲۰۱۸|مجله بینالمللی متافیزیکا - سال ۲۰۱۹]]
| یادداشت = [[متافیزیکا (نشریه)]]
}}
[[رده:متافیزیکا (نشریه)]]
qsk8gk6ysjcjta8oybgc17sgj2h679f
134495
134492
2026-07-25T06:24:05Z
Ələddin.Məlikov
21420
134495
wikitext
text/x-wiki
{{سرصفحه
| عنوان =مجله بینالمللی متافیزیکا - سال ۲۰۱۸
| قسمت =
| قبلی =
| بعدی = [[متافیزیکا (نشریه)/مجله بینالمللی متافیزیکا - سال ۲۰۱۹|مجله بینالمللی متافیزیکا - سال ۲۰۱۹]]
| یادداشت = [[متافیزیکا (نشریه)]]
}}
[[رده:متافیزیکا (نشریه)]]
06kih32tojnf6ga8miw64kwflbln0jv
رده:متافیزیکا (نشریه)
14
42018
134493
2026-07-25T06:22:27Z
Ələddin.Məlikov
21420
ایجاد صفحه خالی
134493
wikitext
text/x-wiki
phoiac9h4m842xq45sp7s6u21eteeq1
متافیزیکا (نشریه)/مجله بینالمللی متافیزیکا - سال ۲۰۱۹
0
42019
134496
2026-07-25T06:25:30Z
Ələddin.Məlikov
21420
صفحهای تازه حاوی «{{سرصفحه | عنوان =مجله بینالمللی متافیزیکا - سال ۲۰۱۹ | قسمت = | قبلی = [[متافیزیکا (نشریه)/مجله بینالمللی متافیزیکا - سال ۲۰۱۸|مجله بینالمللی متافیزیکا - سال ۲۰۱۸]] | بعدی = متافیزیکا (نشریه)/مجله بینالمللی متافیزیکا - سال ۲۰۲۰|مجله بینالم...» ایجاد کرد
134496
wikitext
text/x-wiki
{{سرصفحه
| عنوان =مجله بینالمللی متافیزیکا - سال ۲۰۱۹
| قسمت =
| قبلی = [[متافیزیکا (نشریه)/مجله بینالمللی متافیزیکا - سال ۲۰۱۸|مجله بینالمللی متافیزیکا - سال ۲۰۱۸]]
| بعدی = [[متافیزیکا (نشریه)/مجله بینالمللی متافیزیکا - سال ۲۰۲۰|مجله بینالمللی متافیزیکا - سال ۲۰۲۰]]
| یادداشت = [[متافیزیکا (نشریه)]]
}}
[[رده:متافیزیکا (نشریه)]]
dnx6seny5hptzb6l438wyz14hc83rzo
متافیزیکا (نشریه)/مجله بینالمللی متافیزیکا - سال ۲۰۲۰
0
42020
134497
2026-07-25T06:26:48Z
Ələddin.Məlikov
21420
صفحهای تازه حاوی «{{سرصفحه | عنوان =مجله بینالمللی متافیزیکا - سال ۲۰۲۰ | قسمت = | قبلی = [[متافیزیکا (نشریه)/مجله بینالمللی متافیزیکا - سال ۲۰۱۹|مجله بینالمللی متافیزیکا - سال ۲۰۱۹]] | بعدی = متافیزیکا (نشریه)/مجله بینالمللی متافیزیکا - سال ۲۰۲۱|مجله بینالم...» ایجاد کرد
134497
wikitext
text/x-wiki
{{سرصفحه
| عنوان =مجله بینالمللی متافیزیکا - سال ۲۰۲۰
| قسمت =
| قبلی = [[متافیزیکا (نشریه)/مجله بینالمللی متافیزیکا - سال ۲۰۱۹|مجله بینالمللی متافیزیکا - سال ۲۰۱۹]]
| بعدی = [[متافیزیکا (نشریه)/مجله بینالمللی متافیزیکا - سال ۲۰۲۱|مجله بینالمللی متافیزیکا - سال ۲۰۲۱]]
| یادداشت = [[متافیزیکا (نشریه)]]
}}
[[رده:متافیزیکا (نشریه)]]
668qcvo601ycqcsma7ikqcxu9mf1yec
متافیزیکا (نشریه)/مجله بینالمللی متافیزیکا - سال ۲۰۲۱
0
42021
134498
2026-07-25T06:28:34Z
Ələddin.Məlikov
21420
اصلاح ارقام
134498
wikitext
text/x-wiki
{{سرصفحه
| عنوان =مجله بینالمللی متافیزیکا - سال ۲۰۲۱
| قسمت =
| قبلی = [[متافیزیکا (نشریه)/مجله بینالمللی متافیزیکا - سال ۲۰۲۰|مجله بینالمللی متافیزیکا - سال ۲۰۲۰]]
| بعدی = [[متافیزیکا (نشریه)/مجله بینالمللی متافیزیکا - سال ۲۰۲۳|مجله بینالمللی متافیزیکا - سال ۲۰۲۳]]
| یادداشت = [[متافیزیکا (نشریه)]]
}}
[[رده:متافیزیکا (نشریه)]]
fpdnaxxmoqiuxwoajg26trttr1dyhhb
134499
134498
2026-07-25T06:28:58Z
Ələddin.Məlikov
21420
اصلاح ارقام
134499
wikitext
text/x-wiki
{{سرصفحه
| عنوان =مجله بینالمللی متافیزیکا - سال ۲۰۲۱
| قسمت =
| قبلی = [[متافیزیکا (نشریه)/مجله بینالمللی متافیزیکا - سال ۲۰۲۰|مجله بینالمللی متافیزیکا - سال ۲۰۲۰]]
| بعدی = [[متافیزیکا (نشریه)/مجله بینالمللی متافیزیکا - سال ۲۰۲۲|مجله بینالمللی متافیزیکا - سال ۲۰۲۲]]
| یادداشت = [[متافیزیکا (نشریه)]]
}}
[[رده:متافیزیکا (نشریه)]]
12b16hwae951ytu4yb9qa1ll0qagefm
رده:تاریخ علم (نشریه)
14
42022
134501
2026-07-25T06:46:19Z
Ələddin.Məlikov
21420
ایجاد صفحه خالی
134501
wikitext
text/x-wiki
phoiac9h4m842xq45sp7s6u21eteeq1
تاریخ علم (نشریه)/مجله علمی پژوهشی تاریخ علم - سال ۲۰۲۰
0
42023
134502
2026-07-25T06:48:01Z
Ələddin.Məlikov
21420
اصلاح ارقام
134502
wikitext
text/x-wiki
{{سرصفحه
| عنوان =مجله علمی پژوهشی تاریخ علم - سال ۲۰۲۰
| قسمت =
| قبلی =
| بعدی = [[ تاریخ علم (نشریه)/مجله علمی پژوهشی تاریخ علم - سال ۲۰۲۱|مجله علمی پژوهشی تاریخ علم - سال ۲۰۲۱]]
| یادداشت = [[تاریخ علم (نشریه)]]
}}
[[رده:تاریخ علم (نشریه)]]
s394b53rs9nljc7d4poc0xntp5obmk9