آموزش ورودی و خروجی در C؛ از printf تا کار با فایل‌ها

5 بازدید
۱۴۰۵-۰۶-۰۴
12 دقیقه
  • نویسنده: Alireza Abbasi
  • درباره نویسنده: ---

در قسمت های قبلی دوره، با چالش‌های خروجی ساده روی کنسول روبرو شدیم. اما با وجود سیستم‌عامل در این بخش، مدیریت ورودی و خروجی بسیار ساده‌تر شده است.

دلیل این امر، پنهان شدن پیچیدگی‌های این فرآیند توسط سیستم‌عامل است. به این صورت که شما فقط کافیست عبارت  Hello World\n را بنویسید و سیستم‌عامل به‌طور خودکار اطلاعات را به محل مورد نظر ارسال می‌کند.

در این فصل، به بررسی سیستم I/O زبان C می‌پردازیم. این سیستم شامل تابع printf برای خروجی و همچنین توابعی برای خواندن و نوشتن فایل‌های روی دیسک به روشی کارآمد و انعطاف‌پذیر می‌شود.

تابع printf در C

ما قبلاً چند بار از تابع printf برای خروجی ساده استفاده کرده‌ایم. فرمت کلی این تابع به صورت زیر است:

رشته فرمت(format-string) به printf می‌گوید که چه چیزی را چاپ کند. هر کاراکتری به جز % مستقیماً چاپ می‌شود. کاراکتر % نشان‌دهنده‌ی یک مشخصه فیلد (field specification) است. این مشخصه به printf می‌گوید که به لیست آرگومان‌ها (argument list) مراجعه کند و آرگومان بعدی را بر اساس مشخصه فیلد چاپ کند.برای مثال:

مشخصه فیلد %d می‌تواند با یک عدد اصلاح شود:

در این مثال‌ها، %3d به printf می‌گوید که از حداقل سه کاراکتر برای چاپ عدد استفاده کند. فیلد %-3d به printf می‌گوید که عدد را با حداقل سه کاراکتر چاپ کند و آن را چپ‌چین (left-justify) کند.

کاراکترهای تبدیل (Conversion Characters):

تاکنون فقط با کاراکتر تبدیل d آشنا شدیم که برای تبدیل یک آرگومان عدد صحیح به متن در جهت چاپ استفاده می‌شود. جدول 34-1 کاراکترهای تبدیل اصلی را نشان می‌دهد.

جدول 34-1: کاراکترهای تبدیل اصلی در C

کاراکتر تبدیل

نوع آرگومان

توضیحات

%d

عدد صحیح

انواع char و short int هنگام ارسال به عنوان پارامتر به int ارتقا پیدا می‌کنند، بنابراین این فرمت برای این سه نوع نیز کار می‌کند.

%c

کاراکتر

به دلیل ارتقا، این کاراکتر تبدیل در واقع یک آرگومان عدد صحیح را می‌گیرد و آن را به عنوان یک کاراکتر چاپ می‌کند.

%o

عدد صحیح

به صورت اُکتالی چاپ می‌کند.

%x

عدد صحیح

به صورت هگزادسیمالی چاپ می‌کند.

%f

دابل

برای هر دو نوع float و double کار می‌کند زیرا همه پارامترهای float هنگام ارسال به عنوان آرگومان به double ارتقا پیدا می‌کنند.

%l

عدد صحیح بلند

نوع long int به تبدیل خاص خود نیاز دارد زیرا نوع int به طور خودکار به long int ارتقا پیدا نمی‌کند.

نوشتن جدول اسکی (ASCII)

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

کد منبع (ascii.c):

کد 34-1: برنامه‌ای برای ایجاد جدول ASCII

ابتدا، رشته فرمت %c کاراکتر را به صورت یک کاراکتر چاپ می‌کند. سپس، کاراکتر را به عنوان یک عدد سه رقمی دهدهی (%3d ) چاپ می‌کنیم. برای دقت، نوع آرگومان یک کاراکتر است و به یک عدد صحیح ارتقا پیدا می‌کند. به دلیل عدد ۳ در مشخصه آرگومان، این عدد شامل سه کاراکتر خواهد بود. پس از آن، با استفاده از فرمت %02x به صورت هگزادسیمالی چاپ می‌کنیم. صفر (0) به printf می‌گوید که در صورت نیاز، خروجی را با صفرها پر کند تا به عرض دلخواه (که در اینجا ۲ است) برسد. در نهایت، با رشته %03o به صورت اکتالی چاپ می‌کنیم.

لیست 34-2 خروجی این برنامه را نشان می‌دهد.

لیست 34-2: خروجی کد 34-1 (ascii.c)

تابع printf ستون اصلی سیستم I/O زبان C است. این تابع به ما کمک می‌کند انواع مختلفی از داده‌ها را روی کنسول چاپ کنیم. اما همانطور که در بخش‌های بعدی خواهیم دید، این تنها جایی نیست که می‌توانیم بنویسیم.

نوشتن به فایل‌های از پیش تعریف‌شده

هنگامی که یک برنامه شروع می‌شود، سیستم‌عامل سه فایل از پیش تعریف‌شده را باز می‌کند:

  • stdin (استاندارد این): ورودی معمولی برنامه
  • stdout (استاندارد اوت): برای خروجی معمولی برنامه
  • stderr (استاندارد ارور): برای خروجی خطا

به طور پیش‌ فرض، این فایل‌ها به کنسول متصل هستند، اما مترجم خط فرمان شما می‌تواند آن‌ها را به فایل‌های روی دیسک یا موارد دیگر وصل کند.

تابع fprintf داده‌ها را به یک فایل خاص ارسال می‌کند. برای مثال:

شاید برای شما مفید باشد:
سرویس‌های ارتباطی KLine و مدیریت خطا در سیستم‌های ECU

تابع printf صرفاً یک تابع میانبر است که جایگزین fprintf(stdout, …) می‌شود.

خواندن داده‌ها

تابع‌هایی که برای خواندن داده‌ها طراحی شده‌اند ساده به نظر می‌رسند، اما متأسفانه این‌طور نیست. تابع scanf همتای printf است که وظیفه خواندن داده را برعهده دارد. برای مثال:

در ابتدا، به آمپرسندهای (&) جلوی آرگومان‌ها توجه کنید. scanf نیاز به تغییر دادن آرگومان‌ها دارد، به همین دلیل از & استفاده می‌کنیم ؛ بنابراین، آرگومان‌ها باید بر اساس آدرس (address) پاس داده شوند.

رشته فرمت فرستاده‌شده در scanf بسیار شبیه به رشته فرمت برای printf است، اما یک مشکل بزرگ با scanf همراه است ( مگر اینکه یک متخصص حرفه‌ای باشید): هرگز نمی‌دانید scanf چگونه با فاصله (whitespace) برخورد می‌کند. بنابراین، ما از آن استفاده نمی‌کنیم.

به جای آن، از تابع fgets برای گرفتن یک خط واحد از ورودی و سپس از sscanf برای تجزیه رشته حاصل استفاده می‌کنیم:

فرم کلی fgets به صورت زیر است:

که در آن:

result اشاره به رشته‌ای است که به تازگی خوانده شده (buffer) یا در صورت رسیدن به انتهای فایل (EOF) مقدار NULL خواهد داشت.

buffer یک آرایه کاراکتری است که خط در آن قرار می‌گیرد.

file یک نشانگر فایل (file handle) است که نشان می‌دهد کدام فایل را باید خواند (در حال حاضر stdin تنها فایلی است که می‌شناسیم).

در buffer همیشه خاتمه‌دهنده صفر (0\) وجود خواهد داشت، بنابراین حداکثر size-1 کاراکتر در buffer قرار خواهد گرفت. (کل یک خط خوانده می‌شود، حتی اگر buffer به اندازه کافی برای نگه‌داشتن آن بزرگ نباشد.)

تابع sscanf بسیار شبیه به تابع scanf است، با این تفاوت که اولین آرگومان آن اکنون یک رشته است. سایر آرگومان‌ها مشابه هستند. تابع sscanf تعداد آیتم‌هایی را که تبدیل کرده است برمی‌گرداند.

کد قبلی فرض می‌کند که همه چیز به درستی کار می‌کند. بیایید آن را دوباره بنویسیم و این بار خطاها را بررسی کنیم:

اگر اولین فراخوانی به fgets مقدار NULL برگرداند، مشکلی پیش آمده است. سپس یک پیام خطا به فایل از پیش تعریف‌شده برای خطاها (stderr) چاپ می‌کنیم و یک کد خطا به فراخواننده (caller) برمی‌گردانیم. در مرحله بعد، یک sscanf انجام می‌دهیم که باید دو عدد صحیح پیدا کند. اگر این کار را انجام ندهد، دوباره یک پیام خطا چاپ می‌کنیم و یک کد خطا برمی‌گردانیم.

تابع خطرناک gets

تابع fgets یک تابع اختصاری مشابه برای خواندن داده از stdin دارد. این تابع gets نامیده می‌شود و فرم کلی آن به صورت زیر است:

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

اخطار

استفاده از تابع gets خطرناک است. از آن استفاده نکنید. این تابع در اوایل دوران محاسبات، زمانی که کامپیوترها کمیاب بودند و فرض می‌شد هرکسی که از آن‌ها استفاده می‌کند باهوش و صادق است، ساخته شد. از آن زمان به بعد، شرایط تغییر کرده است و صداقت افراد بسیار کمتر شده است. هکرها به سرعت کشف کردند چگونه برنامه‌هایی که از gets استفاده می‌کنند را با ارسال داده‌ای بیش از ظرفیت buffer خراب کنند. این حمله، حمله سرریز پشته

 (stack smashing attack) نامیده می‌شود. برای مدتی، gets رایج‌ترین حفره امنیتی شناخته‌شده بود.

کامپایلر فعلی GCC استفاده از gets را دشوار می‌کند. اول، stdio.h آن را تعریف نمی‌کند مگر اینکه یک ماکرو کامپایل شرطی (conditional compilation macro) را به درستی تعریف کنید. هنگامی که برنامه را کامپایل می‌کنید، کامپایلر به شما هشدار می‌دهد و سپس هنگام لینک شدن برنامه، لینکر نیز به شما هشدار می‌دهد.

لیست 34-3 نشان می‌دهد که هنگام کامپایل کردن یک برنامه با استفاده از gets چه اتفاقی می‌افتد:

لیست 34-3: تلاش برای استفاده از gets

از حجم خروجی می‌توانید ببینید که کامپایلر GCC چقدر تلاش می‌کند تا شما را از استفاده از gets منصرف کند.

حالا به چند موردی که نباید از آن‌ها استفاده کنیم نگاهی انداختیم، بیایید به چیزهایی که باید استفاده کنیم نگاهی بیندازیم.

باز کردن فایل‌ها

فایل‌های از پیش تعریف‌شده stdin, stdout, و stderr نشانگرهای فایل (file handles) هستند. تابع fopen به شما امکان ایجاد نشانگرهای فایل را می‌دهد. کد 34-4 یک مثال ساده را نشان می‌دهد.

file.c

شاید برای شما مفید باشد:
استفاده از PROGMEM و متغیرهای Static برای کاهش حجم

کد 34-4: نسخه فایلی “Hello World”

اول، اعلان FILE* (1) یک نشانگر فایل جدید را تعریف می‌کند. تمام عملیات روی فایل به یک نشانگر فایل نیاز دارند. سپس فراخوانی fopen (2) را داریم که فرم کلی آن به صورت زیر است:

mode (حالت) می‌تواند یکی از موارد زیر باشد:

r فقط خواندنی

w فقط نوشتنی

r+ خواندنی و نوشتنی

a الحاق (نوشتن و شروع از انتهای فایل)

b همراه با سایر حالت‌ها برای فایل‌های باینری (در بخش بعدی توضیح داده می‌شود) استفاده می‌شود.

احتیاط با نام‌گذاری فایل‌های مایکروسافت

از قرارداد نام‌گذاری مایکروسافت که از بک‌اسلش (\) به عنوان جداکننده استفاده می‌کند، مراقب باشید. اگر می‌خواهید فایلی را در بالاترین سطح دایرکتوری به نام root با نام فایل file.txt در لینوکس یا macOS بنویسید، از دستور زیر استفاده می‌کنید:

در سیستم‌های مایکروسافت، روش زیر کار نمی‌کند:

زیرا بک‌اسلش (\) کاراکتر فرار (escape character) است و چون \r کاراکتر <return> و \f کاراکتر

 <form-feed> هستند، در واقع سعی می‌کنید فایل زیر را بنویسید:

آنچه می‌خواهید این است:

با فرار از کاراکتر فرار، یک بک‌اسلش واقعی در مسیر به دست می‌آورید.

حالا که فایل‌ها را باز کردیم، می‌توانیم به خواندن و نوشتن در آن‌ها بپردازیم. متن را می‌توان با fprintf نوشت و با fgets خواند. در بخش بعدی، به نوع دیگری از فایل‌ها یعنی فایل‌های باینری نگاهی خواهیم انداخت.

ورودی/خروجی باینری

تا الان خودمان را به فایل‌های متنی محدود کرده‌ایم، اما سیستم I/O زبان C می‌تواند از طریق توابع fread و fwrite فایل‌های باینری را مدیریت کند.

فرم کلی تابع fread به صورت زیر است:

در اینجا:

buffer یک اشاره گر به بافر داده‌ای است که داده‌ها در آن قرار خواهند گرفت.

elementSize همیشه ۱ است (برای توضیح به باکس زیر مراجعه کنید).

size اندازه بافر است که معمولاً برابر با sizeof(buffer) می‌باشد و inFile فایلی است که باید خوانده شود.

این تابع تعداد آیتم‌های خوانده‌شده را برمی‌گرداند که به دلیل اینکه elementSize برابر با ۱ است، تعداد بایت‌های خوانده‌شده را نشان می‌دهد. مقدار ۰ برای پایان فایل و یک عدد منفی برای خطای I/O برگردانده می‌شود.

ELEMENTSIZE

قصد اولیه این بود که elementSize اندازه یک عنصر در آرایه بافر باشد و size تعداد عناصری باشد که باید خوانده شود. نتیجه، تعداد عناصر خوانده‌شده بود. با این حال، با گذشت زمان، تقریباً همه برنامه‌ها می‌خواستند تعداد معینی از بایت‌ها را بخوانند، نه تعداد معینی از عناصر. بنابراین، در دنیای واقعی، elementSize برابر با ۱ است و size تعداد بایت‌های قابل خواندن است.

من در طول ۴۰ سال برنامه‌نویسی، فقط دو بار کدی را دیده‌ام که در آن elementSize برابر با ۱ نبوده است. این اتفاق بسیار نادر است.

تابع fwrite ساختاری مشابه دارد:

همه چیز یکسان است، به جز اینکه داده نوشته می‌شود به جای اینکه خوانده شود.

کپی کردن یک فایل

ما از فراخوانی‌های fread و fwrite برای کپی کردن یک فایل استفاده می‌کنیم. از آنجایی که هنوز نحوه‌ی پاس دادن آرگومان‌ها روی خط فرمان را یاد نگرفته‌ایم (به فصل ۱۵ مراجعه کنید)، نام فایل‌های کد ‌سخت (hardcoded) شده به infile.bin و outfile.bin تنظیم شده‌اند. کد 34-5 کد این کار را نشان می‌دهد.

copy.c

کد 34-5: کپی کردن یک فایل

اول، به فراخوانی fopen (1) توجه کنید. ما فایل را با مد(mode) rb باز می‌کنیم، که به سیستم می‌گوید ما قصد خواندن فایل (r) را داریم و آن فایل باینری است(b).

حالا به فراخوانی fread (2) نگاهی بیندازیم. مقدار برگشتی این تابع ssize_t است که یک نوع استاندارد است و به اندازه‌ای بزرگ است که بتواند اندازه بزرگ‌ترین شیء (ساختار، آرایه، Union) که ممکن است وجود داشته باشد را نگه دارد. همچنین می‌تواند مقدار ۱- را برای نشان دادن خطا نگه دارد.

شاید برای شما مفید باشد:
آموزش جامع کار با سمبل‌ها در KiCad | راهنمای گام‌به‌گام

اگر تمام داده‌ها را از فایل خوانده باشیم، fread مقدار ۰ را برمی‌گرداند. وقتی این اتفاق می‌افتد، کار ما تمام شده است، بنابراین از حلقه اصلی خارج می‌شویم (خروج از حلقه در بخش  (3) مشخص شده است).

حالا به فراخوانی fwrite (4) می‌رسیم که مقدار size_t را برمی‌گرداند. این یک نوع بدون علامت است که اندازه بزرگ‌ترین شیء قابل قرارگیری در یک برنامه را نگه می‌دارد، اما چون بدون علامت است، نمی‌تواند مقدار خطا را نگه دارد. چه اتفاقی می‌افتد وقتی fwrite هنگام نوشتن چیزی دچار خطا می‌شود؟ تا جایی که می‌تواند می‌نویسد و تعداد بایت‌های نوشته‌شده را برمی‌گرداند، بنابراین هرگز کد خطا را برنمی‌گرداند. (فقط یک نوشتن کوتاه)

توجه داشته باشید که fread یک مقدار از نوع ssize_t برمی‌گرداند در حالی که fwrite مقدار size_t را برمی‌گرداند. دلایل خوبی برای این تفاوت وجود دارد، اما به این معنی است که اگر بخواهیم بررسی کنیم تعداد بایت‌هایی که سعی کرده‌ایم بنویسیم با تعداد بایت‌هایی که واقعاً از fwrite خواسته‌ایم یکی باشد، یک هشدار کامپایلر دریافت می‌کنیم:

این هشدار به خاطر مقایسه‌ی یک مقدار با علامت (readSize) با یک مقدار بدون علامت (fwrite که size_t برمی‌گرداند) است.

رفع هشدار کامپایلر:

برای رفع این هشدار، نیاز به قرار دادن یک کست (cast) داریم تا به کامپایلر C بگوییم: بله، می‌دانم که در حال ترکیب کردن انواع با علامت و بدون علامت هستیم، اما به دلیل نحوه‌ی تعریف توابع fread و fwrite مجبور به این کار هستم:

با قرار دادن (size_t) جلوی readSize، به کامپایلر اعلام می‌کنیم که به طور موقت، readSize را به نوع size_t تبدیل کنیم تا مقایسه‌ی درستی انجام شود.

استفاده از readSize در fwrite:

همچنین توجه داشته باشید که در آخرین خواندن، احتمالاً ۵۱۲ بایت کامل دریافت نمی‌کنیم. به همین دلیل است که از readSize در دستور fwrite به جای sizeof(buffer) استفاده می‌کنیم. زیرا readSize نشان‌دهنده‌ی تعداد واقعی بایت‌های خوانده‌شده در آخرین تکرار حلقه است.

بافرگیری و تخلیه (Buffering and Flushing)

سیستم I/O زبان C از I/O بافرینگ استفاده می‌کند، یعنی هنگامی که شما از printf یا fwrite استفاده می‌کنید، داده‌ها ممکن است بلافاصله به دستگاه خروجی ارسال نشوند. در عوض، آن‌ها تا زمانی که سیستم به اندازه‌ی کافی داده برای کارایی بهتر داشته باشد، در حافظه ذخیره خواهند شد.

داده‌هایی که به کنسول می‌روند بافرگیری خطی (line buffered) دارند، یعنی اگر بخشی از یک خط را چاپ کنید، ممکن است تا زمانی که بقیه‌ی خط ارسال نشود، خارج نشود. بیایید ببینیم چگونه این موضوع می‌تواند ما را در برنامه‌ی کد 34-6 دچار مشکل کند.

کد 34-6: تقسیم بر صفر

هنگام اجرای این برنامه، انتظار دارید خروجی زیر را ببینید:

اما چیزی که واقعاً می‌بینید این است:

اولین فکر شما ممکن است این باشد که printf اجرا نشده است، اما اجرا شده است. داده‌ها وارد یک بافر شده و در زمان خروج برنامه (abort) در بافر باقی ماندند و این باعث ایجاد تصور اشتباه مبنی بر عدم کارکرد printf شد.

توجه:

تقسیم عدد صحیح بر صفر منجر به خطای ممیز شناور (floating-point exception) و خروج برنامه

 (core dumped) می‌شود. تقسیم ممیز شناور بر صفر باعث می‌شود که مقدار NaN به نتیجه اختصاص داده شود و برنامه خارج نخواهد شد. در مورد این رفتار، سابقه‌ی زیادی وجود دارد. اصطلاح core dumped باقی مانده‌ی زمانی است که حافظه‌ی رایانه واقعاً از هسته‌های فریت (ferrite cores) تشکیل شده بود. در مورد خطای ممیز شناور برای تقسیم‌های صحیح، زمانی که شروع به برنامه‌نویسی کردم یک مورد عجیب قدیمی بود و هنوز نمی‌دانم چرا کارها به این شکل انجام می‌شدند.

برای رفع این مشکل، باید به سیستم I/O بگوییم «داده‌های بافر شده را اکنون بنویس»، که این کار با تابع fflush انجام می‌شود:

تخلیه‌ی داده‌ها تضمین می‌کند که می‌توانیم آن‌ها را ببینیم. از طرف دیگر، نمی‌خواهیم بعد از هر نوشتن، تخلیه انجام دهیم، زیرا این کار باعث بی‌اثر شدن هدف بافرگیری که کارآمدتر کردن I/O است، می‌شود.

بستن فایل‌ها

در نهایت، پس از اینکه کارمان با یک فایل تمام شد، باید به C اطلاع دهیم که دیگر به آن نیاز نداریم. این کار را با استفاده از تابع fclose انجام می‌دهیم:

در اینجا file نشان‌دهنده‌ی فایل (از نوع FILE*) است که می‌خواهیم ببندیم و result نیز مقدار برگشتی تابع است که در صورت موفقیت ۰ و در صورت بروز خطا غیرصفر خواهد بود.

خلاصه

در دنیای سیستم‌های امبدد (embedded systems)، I/O کار دشواری است زیرا باید کدی برای کار مستقیم با دستگاه بنویسید و برای هر نوع دستگاه متفاوتی به کد جداگانه‌ای نیاز دارید.

سیستم I/O زبان C برای پنهان کردن تمام این جزئیات از شما طراحی شده است. همچنین ویژگی‌های مفیدی مانند فرمت‌بندی، بافرگیری و استقلال از دستگاه را ارائه می‌دهد. سیستم I/O بافرینگ برای اکثر برنامه‌های عمومی به خوبی کار می‌کند.

مسائل برنامه‌نویسی

  • ببینید چه اتفاقی می‌افتد زمانی که پارامترهای زیادی یا خیلی کمی در یک دستور printf قرار می‌دهید.
  • چه اتفاقی می‌افتد زمانی که نوع اشتباهی (مثلاً double به جای int)را قرار می‌دهید؟
  • برنامه‌ای بنویسید که از کاربر دما را بر حسب سانتی‌گراد بپرسد و آن را به فارنهایت تبدیل کند.
  • برنامه‌ای بنویسید که تعداد کلمات موجود در یک فایل را بشمارد. حتماً تعریف «کلمه» را مستند کنید، زیرا ممکن است تعریف برخی افراد از کلمه با تعریف شما متفاوت باشد.
  • برنامه‌ای بنویسید که دو فایل را خط به خط مقایسه کند و خطوطی را که متفاوت هستند، خروجی دهد.

 

اطلاعات
5
0
0
اشتراک و حمایت
profile نویسنده: Alireza Abbasi متخصص الکترونیک

ویراستار: حسین زنجانی زاده
مقالات بیشتر

slide

پالت | بازار خرید و فروش قطعات الکترونیک

قطعات اضافه و بدون استفاده همیشه یکی از سرباره‌‌های شرکتها و طراحان حوزه برق و الکترونیک بوده و هست. پالت سامانه‌ای است که بصورت تخصصی اجازه خرید و فروش قطعات مازاد الکترونیک را فراهم می‌کند. فروش در پالت
family

آیسی | موتور جستجوی قطعات الکترونیک

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

سیسوگ‌شاپ | فروشگاه محصولات Quectel

فروشگاه سیسوگ مجموعه ای متمرکز بر تکنولوژی های مبتنی بر IOT و ماژول های M2M نظیر GSM، GPS، LTE، NB-IOT، WiFi، BT و ... جایی که با تعامل فنی و سازنده، بهترین راهکارها انتخاب می شوند. برو به فروشگاه سیسوگ
family

سیسوگ فروم | محلی برای پاسخ پرسش‌های شما

دغدغه همیشگی فعالان تخصصی هر حوزه وجود بستری برای گفتگو و پرسش و پاسخ است. سیسوگ فروم یک انجمن آنلاین است که بصورت تخصصی امکان بحث، گفتگو و پرسش و پاسخ در حوزه الکترونیک را فراهم می‌کند. پرسش در سیسوگ فرم
family

سیکار | اولین مرجع متن باز ECU در ایران

بررسی و ارائه اطلاعات مربوط به ECU (واحد کنترل الکترونیکی) و نرم‌افزارهای متن باز مرتبط با آن برو به سیکار
become a writer
نویسنده شو !

سیسوگ با افتخار فضایی برای اشتراک گذاری دانش شماست. برای ما مقاله بنویسید.

ارسال مقاله
become a writer
نویسنده شو !

سیسوگ با افتخار فضایی برای اشتراک گذاری دانش شماست. برای ما مقاله بنویسید.

ارسال مقاله

خانواده سیسوگ

سیسوگ‌شاپ

فروشگاه محصولات Quectel

پالت
سیسوگ فروم

محلی برای پاسخ پرسش‌های شما

سیسوگ جابز
سیسوگ
سیسوگ فروم
سی‌کار

اولین مرجع متن باز ECU در ایران

سیسوگ مگ
آی‌سی

موتور جستجوی قطعات الکترونیکی

سیسوگ آکادمی
پالت

بازار خرید و فروش قطعات الکترونیک

دیدگاه ها

become a writer
نویسنده شو !

سیسوگ با افتخار فضایی برای اشتراک گذاری دانش شماست. برای ما مقاله بنویسید.

ارسال مقاله
become a writer
نویسنده شو !

سیسوگ با افتخار فضایی برای اشتراک گذاری دانش شماست. برای ما مقاله بنویسید.

ارسال مقاله