الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

هل يمكنك كتابة كود مناسب لحل هذه المشلكة !؟

بدأه khaled_prg في 26 نوفمبر 2010 · 20 رد · 1,377 مشاهدة · في الأسئلة المجابة
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم

اكتب برنامج يطلب من المستخدم إدخال عدد صحيح و آخر حقيقي و حرف و جملة (تحتوي على مسافة) ثم يخزن هذه المُدخلات الأربعة في structure.

ملاحظة : المستخدم غير مُلزم بإدخال المُعطيات بالترتيب السابق بل يمكنه إدخال البيانات بالتريب الذي يحلو له, لذلك لا نعلم (وقت الإدخال) ما نوع البيانات التي سيتم إدخالها ! ,, هنا تكمن الفكرة ... :wink:

بانتظاركم يا معشر المبرمجين :cool:

ملاحظة : الحل مطلوب بلغة السي :)

#2

السلام..

من السهل جدا كتابة ما طلبت في بيئة الدوت نت .. وبدون أي عناء ..(لوجود متحول يستطيع أن يقبل كل

ما تسند اليه من المتحولات المختلفة )

لكن في لغة C أعتقد أن الامر يحتاج الى كتابة شروط لتفّحص القيمة المدخلة قبل عملية الاسناد والحفظ ..

#3

هلق اي , يمكنني كتابة كود ,

الفكرة : إنشاء char [] temp للإدخال

1- أتفحص السلسلة المحرفية اذا كان رقم الأسكي ضمن مجال الأعداد الصحيحة في كل السلسلة فهيا int و أضعها في متحول int

2- اذا كان فيها محرف '.' فبعمل متغير bool و بعد ما أخلص حلقة for بتحقق من كون المتغير البولياني true فهو اذا float

3- اذا كان طول السلسلة 1 و كان من ضمن مجال الأسكي للحروف فهو حرف

4- غير ذلك فهو جملة

1
#4
اقتباس
من السهل جدا كتابة ما طلبت في بيئة الدوت نت .. وبدون أي عناء ..(لوجود متحول يستطيع أن يقبل كل ما تسند اليه من المتحولات المختلفة )

جميل جدا هذه الخاصية, يا ريت لو تكون في السي خاصية مشابهة ! :)

اقتباس
الفكرة : إنشاء char [] temp للإدخال

1- أتفحص السلسلة المحرفية اذا كان رقم الأسكي ضمن مجال الأعداد الصحيحة في كل السلسلة فهيا int و أضعها في متحول int

2- اذا كان فيها محرف '.' فبعمل متغير bool و بعد ما أخلص حلقة for بتحقق من كون المتغير البولياني true فهو اذا float

3- اذا كان طول السلسلة 1 و كان من ضمن مجال الأسكي للحروف فهو حرف

4- غير ذلك فهو جملة

فكرة رائعة :) و لكن لا أظن أنها مناسبة فقد تتسبب بحدوث الـ Overflow :blush:

هل يمكنك تحويل الفكرة إلى كود بالسي أو السي++ ؟ :)

تم تعديل هذه المشاركة بواسطة khaled_prg في 27 نوفمبر 2010 في 01:30

#5
 
#include "stdafx.h"
#include <iostream>
#include<math.h>
using namespace std;

bool isInt(char x)
{
return ((int)x>=48 && (int)x<=57)?1:0;
}
int ConvertToInt(char x[],int size)
{
	int temp=0;
	for(int i=0;i<size;i++)
	{
	temp+=(int)(((int)x-(int)'0')*pow(10.0,(double)(size-i-1)));
	}
	return temp;
}
float ConvertToFloat(char x[],int size,int point)
{
	float temp=0;
	int k=0;
	for(int i=0;i<size;i++)
	{
	if(i==point)
		k=1;
	else
		temp+=(((int)x-(int)'0')*pow(10.0,(double)(point-i-1+k)));
	}
	return temp;
}
void main(){
char temp[100];
cin>>temp;
int size=strlen(temp);
int ok_int=0;
int ok_float=0;
int point_index=0;
for(int i=0;i<size;i++)
{
if(isInt(temp))
	ok_int++;
if((int)temp==46)
	{
	point_index=i;
	ok_float++;
	}
}
//u can make here your attridues in the structer ane make a loop for enter the data like 4 freq
int a1=0;
float a2=0.0;
char a3=' ';
char a4[100];
//here is the IFs
if(ok_int==size)
	a1=ConvertToInt(temp,size);
else if(ok_int + ok_float == size)
	a2=ConvertToFloat(temp,size,point_index);
else if(size == 1)
	a3=temp[0];
else
	strcpy(a4,temp);
//print
cout<<endl<<"a1= "<<a1<<endl<<"a2= "<<a2<<endl<<"a3= "<<a3<<endl<<"a4= "<<a4<<endl;
//for pause
cin.ignore();
int ii;cin>>ii;
}

تفضل أخي الغالي

1 −1
#6

قبل أن أكتب رأيي حول حلك .. لدي ملاحظتان سأضعهما لك :

  • لماذا قمتُ بتضمين المكتبة stdafx.h !؟ و ما فائدتها !؟
  • لماذا كتبت void main مع أنك تعلم أنها غير قياسية و لا يُنصح بها !؟ :)

الكود لا يؤدي المطلوب !, عندما أُدخل له الكلمة khaled, يُظهر لي :

a1 = 0
a2 = 0
a3 = 
a4 = khaled

و المفروض أنه يطلب مني ثلاث إدخالات أخرى حتى أُعطيه جميع البيانات و من ثم يخزنها في المتغيرات المناسبة.

بانتظار تعليقك.

#7

هناك أشياء لا يمكن التفريق فيها ، فـ5 يمكن ان يكون عدد صحيح او حقيقي او حرف .

1 −1
#8
اقتباس
هناك أشياء لا يمكن التفريق فيها ، فـ5 يمكن ان يكون عدد صحيح او حقيقي او حرف .

نحن نتحدث عن الحالة العامة, يعني العدد الحقيقي يحتوي على أرقام بعد الفاصلة و الحرف هو أحد الحروف الهجائية و الجملة تحتوي على مسافة و هكذا ...

#9

تجربة على السريع (لم استخدم ++C هنا) :

#define MAX_STRING_SIZE 256
#define FLG_CHAR        1
#define FLG_INT         2
#define FLG_REAL        4
#define FLG_SENTENCE    8
#define FLG_ALL         (FLG_CHAR | FLG_INT | FLG_REAL | FLG_SENTENCE)

int main ()
{
    size_t length, k;
    unsigned long flags;
    char *ptr_exp, *str_exp;
    struct {
        int integer;
        float real;
        char chr;
        char sentence[MAX_STRING_SIZE];
    } result;


    flags = 0;
    while (flags != FLG_ALL)
    {
        ptr_exp = str_exp = (char *)calloc(MAX_STRING_SIZE, sizeof(char));
        fgets(ptr_exp, MAX_STRING_SIZE, stdin);

        // remove spaces
        while (*ptr_exp == ' ')
            ptr_exp++;

        length = strlen(ptr_exp);

        // remove new line
        if (ptr_exp[length - 1] == '\n')
            ptr_exp[--length] = '\0';

        // check if char
        if (!(flags & FLG_CHAR))
        {
            if (ptr_exp[1] == '\0' && isalpha(ptr_exp[0]))
            {
                result.chr = ptr_exp[0];
                flags |= FLG_CHAR;
                goto __clean;
            }
        }

        // check if integer
        if (!(flags & FLG_INT))
        {
            for (k = 0; k < length; k++)
                if (!isdigit(ptr_exp[k]) && ptr_exp[k] != '+' && ptr_exp[k] != '-')
                    break;
            if (k == length)
            {
                if (ptr_exp[0] == '-' || ptr_exp[0] == '+')
                    sscanf_s(ptr_exp, "%d", &result.integer);
                else
                    sscanf_s(ptr_exp, "%u", &result.integer);
                flags |= FLG_INT;
                goto __clean;
            }
        }

        // check if real
        if (!(flags & FLG_REAL))
        {
            for (k = 0; k < length; k++)
                if (!isdigit(ptr_exp[k]) && ptr_exp[k] != '+' && ptr_exp[k] != '-' && ptr_exp[k] != '.' && ptr_exp[k] != 'e' && ptr_exp[k] != 'E')
                    break;
            if (k == length)
            {
                sscanf_s(ptr_exp, "%g", &result.real);
                flags |= FLG_REAL;
                goto __clean;
            }
        }

        if (!(flags & FLG_SENTENCE))
        {
            if (length > 1)
            {
                for (k = 0; k < length; k++)
                {
                    if (ptr_exp[k] == ' ' && ptr_exp[k + 1] != ' ' && ptr_exp[k + 1] != '\0')
                        break;
                }
                if (k < length)
                {
                    strcpy_s(result.sentence, _countof(result.sentence), ptr_exp);
                    flags |= FLG_SENTENCE;
                }
            }
        }

__clean:
        free(str_exp);
    }

    printf("chr = %c \r\n", result.chr);
    printf("integer = %d \r\n", result.integer);
    printf("real = %g \r\n", result.real);
    printf("sentence = %s \r\n", result.sentence);

    return 0;
}
1
#10

كود جميل (مع أنه يحتوي على أكثر من 100 سطر .. كنتُ أريد حل أبسط للمبتدئين أمثالي)

تمت تجربة الكود و لم يتعرف المترجم على :

sscanf_s
strcpy_s
_countof

و بعد بعض التعديلات .. كانت النتائج قريبة من الصحة.

  • أرجو منك شرح الكود بشيء من التفصيل و هل يمكن اختزال الكود من أجل التبسيط !؟
  • هل بإمكان كودك تخطي مشكلة الـ Oveflow !؟ و كيف !؟

تم تعديل هذه المشاركة بواسطة khaled_prg في 27 نوفمبر 2010 في 14:07

#11

يتم اولا قراءة المدخلات عن طريق الدالة fgets وهي تأخذ حجم للـbuffer لذلك لن يحدث overflow في هذه الجزئية ، الدالة تنسخ المدخلات في البفر الى ان نصل الى سطر جديد او نصل لنهاية حجم البفر .

fgets(ptr_exp, MAX_STRING_SIZE, stdin);

بعد ذلك يتم تخطي المسافات الزيادة في اول المدخلات :

while (*ptr_exp == ' ')
    ptr_exp++;

يتم بعد ذلك التعرف على نوع المدخلات ، لدينا flag لكل نوع اذا تم العثور عليه لا يتم التعرف عليه مرة اخرى .

للتعرف على الحرف اذا كان الحرف الاول ابجدي (a-z/A-Z) والحرف الذي يليه هو صفر (نهاية النص) .

if (!(flags & FLG_CHAR))
{
    if (ptr_exp[1] == '\0' && isalpha(ptr_exp[0]))
    {
    result.chr = ptr_exp[0];

    flags |= FLG_CHAR;
    goto __clean;
    }
}

يتم التعرف على العدد الصحيح اذا كان النص يحتوي على اعداد فقط (0-9) او الرمز +/- :

if (!(flags & FLG_INT))
{
    for (k = 0; k < length; k++)
    if (!isdigit(ptr_exp[k]) && ptr_exp[k] != '+' && ptr_exp[k] != '-')
        break;
    if (k == length)
    {
        if (ptr_exp[0] == '-' || ptr_exp[0] == '+')
            sscanf_s(ptr_exp, "%d", &result.integer);
        else
            sscanf_s(ptr_exp, "%u", &result.integer);
        flags |= FLG_INT;
        goto __clean;
    }
}

التعرف على العدد الحقيقي مثل العدد الصحيح باستثناء انه يسمح برموز اخرى كالفاصلة و e/E :

if (!(flags & FLG_REAL))
    {
    for (k = 0; k < length; k++)
    if (!isdigit(ptr_exp[k]) && ptr_exp[k] != '+' && ptr_exp[k] != '-' && ptr_exp[k] != '.' && ptr_exp[k] != 'e' && ptr_exp[k] != 'E')
    	break;
    if (k == length)
    {
    sscanf_s(ptr_exp, "%g", &result.real);
    flags |= FLG_REAL;
    goto __clean;
    }
}

يتم استخدام sscanf لترجمة النص الى القيمة المقابلة له وهي دالة شبيهة بـscanf باستثناء انها تأخد المدخلات من سلسلة نصية بخلاف scanf التي تأخذ المدخلات من stdin وهي أكثر عرضة للـbuffer overflow ، دائماً افضل استخدام fgets مع sscanf بدلا من scanf .

يتم استخدام secure version من CRT للحد من امكان حدوث overflow .

sscanf_s
strcpy_s

موجودة كـsecured version للـCRT في VS .

_countof ترجع عدد عناصر مصفوفة ما .

#define _countof(__array) (sizeof(__array) / sizeof(__array[0]))

تم تعديل هذه المشاركة بواسطة KiSubvertSystem في 27 نوفمبر 2010 في 14:50

1
#12
اقتباس
يتم اولا قراءة المدخلات عن طريق الدالة fgets

كنت أظن أن استخدام هذه الدالة يقتصر على الملفات !, حسب علمي/جهلي فإن :

الدالة fgets مُختصرة من file get string و لها ثلاثة وسائط, الأول لاسم السلسلة الحرفية و الثاني لحجم السلسلة و الثالث لمؤشر ملف الإدخال, تقوم هذ الدالة بوضع سلسلة حروف الملف بحجم الوسيط الثاني في الوسيط الأول. هل هذا صحيح !؟

ما هو stdin !؟ أرجو أن يكون الشرح بالعربية أو الفرنسية لو سمحت.

اقتباس
وهي تأخذ حجم للـbuffer لذلك لن يحدث overflow في هذه الجزئية

أعلم ذلك و لكنني أتحدث عن حدوث الـ Overflow عند تحويل العدد من string إلى نوع المتغير العددي, ماذا لو كان المقدار المُحول أكبر من القيمة العظمى أو أقل من القيمة الصغرى !؟

اقتباس
بعد ذلك يتم تخطي المسافات الزيادة في اول المدخلات

لم أفهم !, عن أي مسافات تتحدث ؟

اقتباس
يتم بعد ذلك التعرف على نوع المدخلات ، لدينا flag لكل نوع اذا تم العثور عليه لا يتم التعرف عليه مرة اخرى .

للتعرف على الحرف اذا كان الحرف الاول ابجدي (a-z/A-Z) والحرف الذي يليه هو صفر (نهاية النص) .

لم أفهم هذا الشرط :

flags & FLG_CHAR

و هذه العملية أيضا :

flags |= FLG_CHAR;

اقتباس
يتم استخدام secure version من CRT للحد من امكان حدوث overflow .

ممكن توضح أكثر لو سمحت ؟

اقتباس

sscanf_s
strcpy_s

موجودة كـsecured version للـCRT في VS .

أنا أستخدم المترجم dev و لم يتعرف عليهم !, هل من حل !؟

اقتباس
_countof ترجع عدد عناصر مصفوفة ما .

#define _countof(__array) (sizeof(__array) / sizeof(__array[0]))

عندما وضعت هذا الماكرو في الكود, ظهرت لي الأخطاء التالية :

94 Z:\exo.cpp invalid conversion from `unsigned int' to `const char*' 
45 C:\Dev-Cpp\include\string.h too many arguments to function `char* strcpy(char*, const char*)' 
94 Z:\exo.cpp at this point in file

بانتظار التوضيح.

تم تعديل هذه المشاركة بواسطة khaled_prg في 27 نوفمبر 2010 في 16:04

#13
اقتباس
كنت أظن أن استخدام هذه الدالة يقتصر على الملفات !, حسب علمي/جهلي فإن :

الدالة fgets مُختصرة من file get string و لها ثلاثة وسائط, الأول لاسم السلسلة الحرفية و الثاني لحجم السلسلة و الثالث لمؤشر ملف الإدخال, تقوم هذ الدالة بوضع سلسلة حروف الملف بحجم الوسيط الثاني في الوسيط الأول. هل هذا صحيح !؟

ما هو stdin !؟ أرجو أن يكون الشرح بالعربية أو الفرنسية لو سمحت.

نعم كلامك صحيح بالنسبة لعمل الدالة ، fgets تعمل مع الملفات بالطبع كما ان stdin ترمز لملف ايضاً .

stdin اختصار لـStandard Input ، وهو الـstream الذي يمثل المدخلات في شاشة الكونسول .

يوجد ايضا stdout وهو يمثل الخرج :)

اقتباس
أعلم ذلك و لكنني أتحدث عن حدوث الـ Overflow عند تحويل العدد من string إلى نوع المتغير العددي, ماذا لو كان المقدار المُحول أكبر من القيمة العظمى أو أقل من القيمة الصغرى !؟

لا يتم التأكد من هذه الجزئية ، الامر متروك للدالة sscanf لتقوم بتحويل النص الى القيمة المقابلة له .

اقتباس
لم أفهم !, عن أي مسافات تتحدث ؟

في حال ادخل المستخدم مسافات قبل النص يتم قصها ، مثلا :

اقتباس
" 6.5 "

بالنسبة للـFlags فلدينا متغير من نوع unsigned long اي بحجم 32 بت ، اذا كان كل بت يمثل حالة معينة فلدينا 32 حالة يمكن تمثيلها عن طريق هذا المتغير .

اذا تم وضع البت الاول فيدل هذا على اننا وجدنا الـحرف .

اذا تم وضع البت الثاني فهذا يدل على اننا وجدنا العدد وهكذا ...

هل درست logics ؟

المعامل & (bitwise AND) يقوم باختبار كل بت مقابل البت المقابل فان كان كلاهما بواحد يقوم بارجاع واحد .

10111001
11011101
AND----------
10011001

في حين ان المعامل | (bitwise OR) يختبر كل بت بالمقابل له ويقوم بارجاع 1 اذا كان اي منهما 1 .

في الكود يوجد اربع حالات يمثلها البت 1/2/3/4 .

بالنسبة للـsecured CRT version فلا اعرف ان كانت standard ام لا (فليفيدنا احد الاخوة) .

يمكنك استخدام strncpy بدلا من strcpy عموما .

اقتباس

عندما وضعت هذا الماكرو في الكود, ظهرت لي الأخطاء التالية :

اعتقد انك مررت ثلاث معاملات الى الدالة strcpy وهي تستقبل معاملين فقط ، استخدم :

strcpy(result.sentence, ptr_exp);

او افضل :

strncpy(result.sentence, ptr_exp, _countof(result.sentence));
1
#14

أشكرك أخي الكريم على المتابعة و أسأل الله سبحانه و تعالى أن يوفقك في الدارين و يزيدك من فضله, إنه ولي ذلك و القادر عليه :)

اقتباس
نعم كلامك صحيح بالنسبة لعمل الدالة ، fgets تعمل مع الملفات بالطبع كما ان stdin ترمز لملف ايضاً .

stdin اختصار لـStandard Input ، وهو الـstream الذي يمثل المدخلات في شاشة الكونسول .

يوجد ايضا stdout وهو يمثل الخرج :)

ما فائدة الملف stdin و ما هو امتداده !؟

اقتباس
لا يتم التأكد من هذه الجزئية ، الامر متروك للدالة sscanf لتقوم بتحويل النص الى القيمة المقابلة له .

الدالة sscanf تسند قيمة مُخزنة في سلسة نصية إلى متغير عددي و لكن ماذا لو كانت القيمة المخزنة في string كبيرة جدا مثل 34590237629076272684736892 !؟, هنا سيحدث overflow لأن المتغير العددي لا يمكنه حفظ هذه القيمة !, ما رأيك !؟

اقتباس
هل درست logics ؟

سبق و أن درست الـ bitwise مثل <<,>>,|,&,^ و ما إلى ذلك ...

اقتباس
اذا تم وضع البت الاول فيدل هذا على اننا وجدنا الـحرف .

اذا تم وضع البت الثاني فهذا يدل على اننا وجدنا العدد وهكذا ...

كيف نعرف أنه تم وضع البت !؟

تم تعديل هذه المشاركة بواسطة khaled_prg في 27 نوفمبر 2010 في 17:08

#15
اقتباس
ما فائدة الملف stdin و ما هو امتداده !؟

هو ليس ملف بحد ذاته ولكنه يرمز لملف ، فائدته هو التعامل مع المدخلات والمخرجات في الكنسول بشكل مباشر .

اقتباس
الدالة sscanf تسند قيمة مُخزنة في سلسة نصية إلى متغير عددي و لكن ماذا لو كانت القيمة المخزنة في string كبيرة جدا مثل 34590237629076272684736892 !؟, هنا سيحدث overflow لأن المتغير العددي لا يمكنه حفظ هذه القيمة !, ما رأيك !؟

كلام صحيح ، كما قلت سابقا لم يتم اختبار هذه الجزئية وتركتها لـsscanf والتي بدورها لا تختبر وجود overflow .

يمكن استبدالها بـstrtoul/strtol/strtod لتحويل int/float ، في حالة حدوث overflow او underflow يتم وضع errno بـERANGE .

اقتباس

كيف نعرف أنه تم وضع البت !؟

نقوم بعمل AND للـflags مع قيمة البت المراد اختباره ، اذا كان الناتج هو نفسه قيمة البت اذا فقد تم وضعه :

#define MY_BIT1 (1 << 0) // البت الاول
#define MY_BIT2 (1 << 1) // البت الثاني
#define MY_BIT3 (1 << 2) // البت الثالث
#define MY_BIT4 (1 << 3) // البت الرابع

او

#define MY_BIT1 1 // البت الاول
#define MY_BIT2 2 // البت الثاني
#define MY_BIT3 4 // البت الثالث
#define MY_BIT4 8 // البت الرابع


if ((flags & MY_BIT4) == MY_BIT)
	// set البت موضوع
else
	// clear البت غير موضوع

تم تعديل هذه المشاركة بواسطة KiSubvertSystem في 27 نوفمبر 2010 في 18:37

1
#16
اقتباس
هو ليس ملف بحد ذاته ولكنه يرمز لملف ، فائدته هو التعامل مع المدخلات والمخرجات في الكنسول بشكل مباشر .

ماذا تقصد بالتعامل مع المُدخلات !؟

اقتباس
يمكن استبدالها بـstrtoul/strtol/strtod لتحويل int/float ، في حالة حدوث overflow او underflow يتم وضع errno بـERANGE .

ممكن مثال لو سمحت ؟

#17
اقتباس
ماذا تقصد بالتعامل مع المُدخلات !؟

تخيل انك تريد قراءة المدخلات جملة واحدة دون اعتبار وجود سطر جديد ، اي قراءة اكثر من سطر بنفس الوقت ، وتريد ارسال المدخلات الى برنامج اخر عن طريق pipe او حفظها في ملف لمعالجتها في وقت لاحق :

char buffer[21] = "";
fread(buffer, sizeof(char), 20, stdin);
FILE *stream = fopen("input.txt", "w");
fwrite(buffer, sizeof(char), strlen(buffer), stream);
fclose(stream);

اقتباس
ممكن مثال لو سمحت ؟

char str[21], *endptr;
unsigned long integer;
double real;

printf("enter integer :\r\n");
fgets(str, 20, stdin);
fflush(stdin);
if (str[strlen(str) - 1] == '\n') 
	str[strlen(str) - 1] = '\0';
integer = strtoul(str, &endptr, 10);
if (errno == ERANGE)
	printf("%s overflows\r\n", str);
else if (*endptr)
	printf("invalid format\r\n");

printf("enter float :\r\n");
fgets(str, 20, stdin);
fflush(stdin);
if (str[strlen(str) - 1] == '\n') 
	str[strlen(str) - 1] = '\0';
real = strtod(str, &endptr);
if (errno == ERANGE)
	printf("%s overflows\r\n", str);
else if (*endptr)
	printf("invalid format\r\n");
1
#18

مستواك البرمجي يُضاعف مستواي عشرات المرات .. لذلك أجد صعوبة بالغة في فهم أفكارك ! :blush:

اقتباس
تخيل انك تريد قراءة المدخلات جملة واحدة دون اعتبار وجود سطر جديد ، اي قراءة اكثر من سطر بنفس الوقت ، وتريد ارسال المدخلات الى برنامج اخر عن طريق pipe او حفظها في ملف لمعالجتها في وقت لاحق

لم أفهم من هذه الفقرة سوى 0.0000000001% !

ما هو الـ pipe !؟

مالفرق بين الـ buffer و stdin !؟

ممكن توضح أكثر !؟

char buffer[21] = "";
fread(buffer, sizeof(char), 20, stdin);
FILE *stream = fopen("input.txt", "w");
fwrite(buffer, sizeof(char), strlen(buffer), stream);
fclose(stream);

:blink: :wacko:

ما هذه الدالة ! :blink: :wacko: :

fflush(stdin);

تم تعديل هذه المشاركة بواسطة khaled_prg في 28 نوفمبر 2010 في 00:30

#19
ما هو الـ pipe !؟

الـpipe عبارة عن قناة/مجرى للبيانات ، يمكننا الـpipe من القراءة والكتابة اليها وتستخدم لمشاركة البيانات بين عمليتين مختلفتين ، يمكنك مجازا اعتبارها ملف بدون وجود فيزيائي على القرص الصلب .

مالفرق بين الـ buffer و stdin !؟

الـbuffer هي جزء من الذاكرة لقراءة البيانات او حفظها ، stdin عبارة stream مثلها مثل الملفات ، بخلاف انها تمثل المدخلات في شاشة الكونسول ، فعند قراءة احد المدخلات عن طريق scanf مثلا او cin يتم القراءة فعليا من stdin .

fflush تقوم بانعاش الذاكرة المرتبطة بالـstream ، عندما تقوم بالكتابة الى ملف مثلا فان ما سيتم كتابته يخزن اولا في buffer خاص ثم تتم الكتابة الفعلية اذا امتلأ هذا البفر او اذا تم اغلاق الـstream او البرنامج وذلك للتقليص من عدد مرات الكتابة الفعلية على القرص الصلب .

وعندما يكون الـstream خاص بالادخال كـstdin فان fflush تقوم بمحو او بيانات موجودة بالبفر الخاص بالـstream .

في الكود السابق من الضروري استعمال fflush بعد fgets كي يتم تحرير اي ذاكرة اضافية لم يتم قرائتها في fgets لزيادة طولها عن عدد البايتات المقروئة مثلا .

جرب ادخال حروف اكثر من 20 ، سيتم قراءة اول 20 حرف في اول استدعاء لـfgets وسيبقى باقي الحروف المدخلة في buffer خاص بالـsteram ، عند استدعاء fgets للمرة الثانية لن ينتظر من المستخدم ادخال حروف جديدة بل سينسخ الحروف المتبقية في البفر الى ان يصل الى سطر جديد او الحد الاقصى للبايتات المقروءة .

لذلك يجب استعمال fflush كي يتم تحرير اي حروف متبقية في البفر الخاص بالـstream بعد القراءة .

#20
اقتباس
الـbuffer هي جزء من الذاكرة لقراءة البيانات او حفظها ، stdin عبارة stream مثلها مثل الملفات ، بخلاف انها تمثل المدخلات في شاشة الكونسول ، فعند قراءة احد المدخلات عن طريق scanf مثلا او cin يتم القراءة فعليا من stdin .

  • كيف تكون البيانات مُخزنة في الـ buffer و مع ذلك تُقرأ من stdin !؟
    سمعتُ البعض يقول :
  • غالبا مايتم تخزين الناتج الخاص بجمل الطباعه على ال stdout قبل طباعتها و ذلك بغرض تحسين الأداء (buffering و خلافه) فعندما تريد أن يتم كتابة الناتج مباشره دون الإنتظار , قم بعمل flush, ممكن توضح أكثر !؟
  • الدالة endl تقوم بإضافة سطر جديد ثم تقوم بعمل flushing للـ output stream أما \n فيطبع سطر جديد داخل output stream فقط !!!, ما هي عملية flushing و ما فائدتها !؟
  • الدالة printf تقوم بالكتابة داخل standard output stream للبرنامج و ليس الشاشة, كيف يعني !؟

اقتباس
fflush تقوم بانعاش الذاكرة المرتبطة بالـstream ، عندما تقوم بالكتابة الى ملف مثلا فان ما سيتم كتابته يخزن اولا في buffer خاص ثم تتم الكتابة الفعلية اذا امتلأ هذا البفر او اذا تم اغلاق الـstream او البرنامج وذلك للتقليص من عدد مرات الكتابة الفعلية على القرص الصلب .

وعندما يكون الـstream خاص بالادخال كـstdin فان fflush تقوم بمحو او بيانات موجودة بالبفر الخاص بالـstream .

في الكود السابق من الضروري استعمال fflush بعد fgets كي يتم تحرير اي ذاكرة اضافية لم يتم قرائتها في fgets لزيادة طولها عن عدد البايتات المقروئة مثلا .

جرب ادخال حروف اكثر من 20 ، سيتم قراءة اول 20 حرف في اول استدعاء لـfgets وسيبقى باقي الحروف المدخلة في buffer خاص بالـsteram ، عند استدعاء fgets للمرة الثانية لن ينتظر من المستخدم ادخال حروف جديدة بل سينسخ الحروف المتبقية في البفر الى ان يصل الى سطر جديد او الحد الاقصى للبايتات المقروءة .

لذلك يجب استعمال fflush كي يتم تحرير اي حروف متبقية في البفر الخاص بالـstream بعد القراءة .

حسب ما فهمت من كلامك فإن الدالة fflush هي المسؤولة عن تنظيف الـ buffer و يقابلها التابع cin.sync في السي++, صح !؟

تم تعديل هذه المشاركة بواسطة khaled_prg في 28 نوفمبر 2010 في 11:48

مواضيع مشابهة

عدد الزوار حالياً

المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية

—الإجمالي—أعضاء مسجّلون—زوار بدون تسجيل

جارٍ التحقق من المتواجدين…