انجمن‌های فارسی اوبونتو

لطفاً به انجمن‌ها وارد شده و یا جهت ورود ثبت‌نام نمائید

لطفاً جهت ورود نام کاربری و رمز عبورتان را وارد نمائید


ارائه ۲۴٫۱۰ اوبونتو منتشر شد 🎉

نویسنده موضوع: توضیح حروف خوانده نشده(Unread characters) در زبان C (حل شد)  (دفعات بازدید: 99 بار)

0 کاربر و 1 مهمان درحال مشاهده موضوع.

آفلاین 🇬🇧بریتانیای کبیر🇬🇧

  • High Hero Member
  • *
  • ارسال: 2762
  • جنسیت : پسر
  • GOD SAVE THE KING/QUEEN
صفحه زیر دقیقا داره چی رو توظیح میده؟ متوجه نمیشم.

https://sourceware.org/glibc/manual/2.40/html_node/How-Unread.html
« آخرین ویرایش: امروز ساعت 04:34 ق‌ظ توسط 🇬🇧بریتانیای کبیر🇬🇧 »
🇬🇧🏴󠁧󠁢󠁥󠁮󠁧󠁿🏴󠁧󠁢󠁷󠁬󠁳󠁿🏴󠁧󠁢󠁳󠁣󠁴󠁿🇬🇧

آفلاین جادی

  • عضو کاربران ایرانی اوبونتو
  • *
  • ارسال: 1628
    • در دفاع از آزادی بیان
توی زبان سی یه تابع هست به اسم getc که باهاش یه کاراکتر رو از یه استریم می‌خونه. به فرض اگر برنامه تو در حال اجرا است و یکی یه کلید رو روی کیبرد می زنه، تو می تونی با این دستور بخونیش. اما یه وقتی هست که به هر دلیلی از این خوندن پشیمون شدی ((: می تونی با ungetc کاراکتر رو به استریم برگردونی. مثالی که زده اینه که کاراکترها رو می خونی و وقتی یه چیزی به جز اسپیس بود بر می گردونیش تا بعدا دوباره خونده بشه.
آزادی کیبورد حق هر انسان است - جادی

آفلاین esmaeelE

  • ناظر انجمن
  • *
  • ارسال: 1305
  • جنسیت : پسر
برای فهم بهتر این مثال‌ها می‌تونید یک برنامه ساده براش بنویسید.

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


/*
Run
$ gcc -Wall run.c -o run; ./run
*/

void skip_whitespace(FILE *stream) {
  int c;
  do {
    /* No need to check for EOF because it is not
       isspace, and ungetc ignores EOF.  */
    c = getc(stream);
    printf("read: %c, %d\n", c, c);
    //} while (!isspace(c));
  } while (isspace(c));
  int b = ungetc(c, stream);
  printf("put: %c, %d\n", b, b);
}

int main(void) {

  // printf("Hell world!\n");
  // char str[] = "  simple text";
  // printf("%s\n", str);

  FILE *fptr = fopen("test.txt", "r");

  char string[100] = "";
  fgets(string, 100, fptr);
  // print the file content
  printf("stream:\n%slen: %ld\n", string, strlen(string));

  // move pointer to start position
  rewind(fptr);
  skip_whitespace(fptr);
  char string2[100] = "";
  fgets(string2, 100, fptr);
  printf("stream:\n%slen: %ld\n", string2, strlen(string2));

  // close the file
  fclose(fptr);

  return 0;
}


این یک نمونه از اجرای برنامه روی فایلی با محتویات متن هست. همانطور که می‌بینید کاراکترهای فاصله را که در ابتدا قرار دارند از جریان داده fptr حذف کرده.

$ gcc -Wall run.c -o run; ./run
stream:
  simple
len: 9
read:  , 32
read:  , 32
read: s, 115
put: s, 115
stream:
simple
len: 7


« آخرین ویرایش: امروز ساعت 06:42 ق‌ظ توسط esmaeelE »

آفلاین 🇬🇧بریتانیای کبیر🇬🇧

  • High Hero Member
  • *
  • ارسال: 2762
  • جنسیت : پسر
  • GOD SAVE THE KING/QUEEN
فقط من نفهمیدم چطوری ungetc بدون ویرایش پرونده یک حرفی که درون پرونده نیستو میتونه به جای یک حرف دیگه که درون پرونده هست بذاره تا اون حرف اصلیه خوانده نشه. اون حرف جدیده کجا ذخیره میشه؟
حله
تو همون بافر ذخیره میشه. بعد از rewine یا fseek پاک میشه.
« آخرین ویرایش: امروز ساعت 06:31 ق‌ظ توسط 🇬🇧بریتانیای کبیر🇬🇧 »
🇬🇧🏴󠁧󠁢󠁥󠁮󠁧󠁿🏴󠁧󠁢󠁷󠁬󠁳󠁿🏴󠁧󠁢󠁳󠁣󠁴󠁿🇬🇧

آفلاین esmaeelE

  • ناظر انجمن
  • *
  • ارسال: 1305
  • جنسیت : پسر
سعی می‌کنم روال برنامه را توضیح بدم.

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

(البته بهتر بود در برنامه صحت باز کردن فایل را هم چک می‌کردیم که اشاره گر از نوع NULL نباشد)

در ادامه کار تابع fgets به میزان حداکثر صد کاراکتر از جایی که fptr به آن اشاره می‌کنه می‌خونه و داخل یک آرایه از جنس کاراکتر ذخیره می‌کنه. که عملا میشه خوندن تمام محتویات فایل تا انتها.
(با خود فایل روی دیسک کاری نداریم فقط ازش خوندیم)

و بعد این آرایه کارکتری را چاپ کردیم تا داخلش را ببینیم.

(در C یک آرایه از کاراکترها که به کاراکتر 0 ختم بشه رشته یا string نامیده میشه.)

چون fgets اشاره گر فایل را به انتها حرکت داده rewind را اجرا کردیم تا برگرده سرجای اول خودش یعنی ابتدای فایل.

و در ادامه fptr به تابع skip_whitespace پاس داده شده تا روی آن عملیات انجام بده.

در حلقهٔ درونی این تابع از محل اشاره گر فایل یک کاراکتر یک کاراکتر توسط تابع getc خوانده شد.
کاراکتر خونده شده به همراه کد ASCII معادل اون را چاپ کردیم تا کار واضح‌تر باشه.

حلقه تا زمانی که کاراکتر خوانده شده space باشه ادامه پیدا می‌کنه. به عبارت دیگه وقتی دیگه کاراکتر space نباشه کار حلقه تموم شده است.

حالا آخرین کاراکتر (غیر space) داخل متغیر c قرار دارد.

در اینجا ungetc اجرا میشه. و متغیر c را به درون stream یا همان چیزی که اشاره‌گر fptr به آن اشاره می‌کنه بر می‌گردونه.

و در ادامه اون کاراکتر را هم چاپ می‌کنه.
اجرای تابع به اتمام رسیده و کار تمام است.

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

عملا با این کار باعث شدیم که تمام کاراکترهای space را از ابتدای stream حذف کنیم.

ما با ساخت یک اشاره‌گر فایل یعنی fptr از محتویات فایل test.txt یک جریان یا stream ساختیم.

توجه کنید که تمام این حرکات هیچ اثری روی خود فایل اصلی که روی دیسک قرار دارد، ندارد و محتویات آن دست نخورده باقی مانده است. چون  صرفا محتوای فایل را روی حافظه بارگذاری کردیم و یکسری عملیات روی آن انجام دادیم.



این دو صفحه را ببینید.

man ascii
man fgetc



آفلاین esmaeelE

  • ناظر انجمن
  • *
  • ارسال: 1305
  • جنسیت : پسر
فقط من نفهمیدم چطوری ungetc بدون ویرایش پرونده یک حرفی که درون پرونده نیستو میتونه به جای یک حرف دیگه که درون پرونده هست بذاره تا اون حرف اصلیه خوانده نشه. اون حرف جدیده کجا ذخیره میشه؟
حله
تو همون بافر ذخیره میشه. بعد از rewine یا fseek پاک میشه.

قبل از اینکه skip_whitespace اجرا بشه rewind را اجرا کردیم. این به خاطر این است که اشاره گر برگرده به ابتدای فایل چون با fgets رفته آخر.

می‌تونید این دستور rewind را حذف کنید و همزمان fgets قبلی را هم حذف کنید. باز هم برنامه درست کار می‌کنه.