سؤال

أنا أكتب برنامج الذي من المفترض أن قراءة سلسلتين التي يمكن أن تحتوي على فواصل الأسطر ومختلف الشخصيات الأخرى.لذلك أنا باستخدام EOF (Ctrl-Z أو Ctrl-D) إلى نهاية السلسلة.

هذا يعمل بشكل جيد مع المتغير الأول ، ولكن مع المتغير الثاني ، ومع ذلك ، يبدو أن إشكالية كما يبدو شيء عالق في مخزن الإدخال المؤقت المستخدم لا اكتب في أي شيء.

حاولت تنظيف العازلة مع while (getchar() != '\n'); عدة مشابهة الاختلافات ولكن لا يبدو أن تساعد.كل تنظيف محاولات أسفرت عن حلقة لا نهائية و دون تنظيف ، إضافة المتغير الثاني هو مستحيل.

الشخصيات لكل من المتغيرات قراءة في حلقة من هذا القبيل: while((c = getchar()) != EOF), التي تشير إلى أنها EOF ما لدي عالقة في المخزن المؤقت.أو أنها لا تؤثر على سلوك البرنامج في بعض طريقة أخرى ؟ هل هناك شيء خاطئ مع المنطق الذي أستخدمه ؟

أنا بدأت محاولة يائسة بعد صراع مع هذا لساعات.

[تحرير:إضافة التعليمة البرمجية أدناه]

[تحرير 2:clearerr() يبدو لجعل هذا EOF الحل العمل بعد كل شيء.

تبدو في شكلها الأصلي مثل ما المقصود لينكس ، كنت أحاول مع ويندوز أمس.]

كود:

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

int main(void)
{
    int x = 0;
    int c;
    char a[100];
    char b[100];

    printf("Enter a: ");
    while((c = getchar()) != EOF)
    {
        a[x] = c;
        x++;
    }
    a[x] = '\0';
    x = 0;

    /*while (getchar() != '\n'); - the non-working loop*/

    printf("\nEnter b: ");
    while((c = getchar()) != EOF)
    {
        b[x] = c;
        x++;
    }
    b[x] = '\0';

    printf("\n\nResults:\na: %s\n", a);
    printf("b: %s\n", b);

    return(0);
}

[عدل 3:]

الذاكرة الديناميكية المسألة:

برنامجي هو أيضا من المفترض أن التعامل مع سلاسل أطول من 100 حرف.أصلا أنا المقصود من حل هذا عن طريق تخصيص الذاكرة الديناميكية ، ولكن عندما كان لدي مشاكل مع حلقة لانهائية هو موضح أعلاه و المتعلقة بالذاكرة تعطل تركتها و تحول إلى شار[100].

أعتقد أن ما حاولت عموما شيء من هذا القبيل:

while((c = getchar()) != EOF)
{
  a = malloc(sizeof(char));
  a[x] = c;
  x++;
}

هل هذا ممكن (أو معقولة) طريقة لفعل ذلك ؟ أنا أحاول أن تخصيص المزيد من الذاكرة لكل حرف أن يجري التعامل معها هناك.بشكل فردي.مع رمز من هذا القبيل (هذا المثال يحتوي على الارجح أخطاء في بناء الجملة) لقد شهدت حوادث, لذلك يبدو لي malloc قد لا يكون الحق في وظيفة هنا ، أو أحاول ذلك الخطأ.لنفترض حتى أنه من الممكن.

هل كانت مفيدة؟

المحلول

بعد أن تلقى EOF من المحطة ، لن تتلقى أي بيانات إضافية.لا توجد وسيلة من الامم المتحدة EOF-ing المدخلات نهاية الملف هو الغاية.

لذلك يجب أن تحدد أن كل متغير هو الإدخال على سطر منفصل ، و المستخدمين اضغط enter بدلا من EOF.لا تزال تحتاج إلى التحقق من ما إذا كنت قد تلقيت eof, لأن ذلك يعني أن المستخدم فعلا كتبته EOF و لن ترى أي شيء آخر - في هذه الحالة تحتاج إلى الخروج من حلقة طباعة رسالة خطأ.

نصائح أخرى

EOF ليس حرف - أن قيمة هذا الإدخال وظائف العودة إلى الشرط, أن "نهاية الملف" على أن تيار الإدخال تم التوصل إليه.كما مارتن الخامس.Löwis يقول مرة أن "نهاية الملف" حالة حدوث ذلك يعني أنه لا مزيد من المدخلات سوف تكون متاحة على تيار.

الإشكال لأن:

  • كثير من محطة التعرف على أنواع خاصة المفاتيح للإشارة إلى "نهاية الملف" عند "ملف" تفاعلية محطة (على سبيل المثال.Ctrl-Z أو Ctrl-D) ؛ و
  • على EOF قيمة واحدة من القيم التي يمكن إرجاعها من قبل getchar() الأسرة من الوظائف.

سوف تحتاج إلى استخدام فعلي حرف قيمة منفصلة المدخلات - ASCII nul حرف '\0' قد يكون خيارا جيدا إذا كان هذا لا يمكن أن تظهر قيمة صحيحة ضمن المدخلات أنفسهم.

وأنا تشغيل التعليمات البرمجية على مربع لينكس بلدي، وهنا هو النتيجة:

Enter a: qwer
asdf<Ctrl-D><Ctrl-D>
Enter b: 123
456<Ctrl-D><Ctrl-D>

Results:
a: qwer
asdf
b: 123
456

وكانت هناك حاجة اثنين على Ctrl-D لأن المخزن المؤقت إدخال محطة ليست فارغة.

هل يمكن استخدام حرف فارغة ('\0') للفصل بين المتغيرات. مختلف الأدوات UNIX (على سبيل المثال find) قادرة على فصل عناصر الانتاج في هذا الطريق، والتي من شأنها أن تشير إلى أنها طريقة موحدة إلى حد ما.

وهناك ميزة أخرى لهذا هو أنه يمكنك قراءة دفق في مخزن مؤقت واحد ثم قم بإنشاء مجموعة من char*s للإشارة إلى سلاسل الفردية، وسيتم بشكل صحيح '\0' إنهاء-كل سلسلة دون الحاجة لتغيير أي شيء في المخزن المؤقت يدويا. وهذا يعني أقل من الذاكرة تخصيص النفقات العامة، الأمر الذي قد يجعل البرنامج تشغيل أسرع بشكل ملحوظ اعتمادا على عدد المتغيرات كنت تقرأ. بالطبع، هذا أمر ضروري فقط إذا كنت بحاجة إلى استيعاب كافة المتغيرات في الذاكرة في نفس الوقت - إذا كنت تتعامل معهم واحد في واحد في الوقت، كنت لا تحصل على هذه الميزة معينة

.

وماذا كنت تحاول المستحيل جوهريا مع EOF.

وعلى الرغم من أنه يتصرف وكأنه واحد في بعض النواحي، EOF ليس حرف في تيار ولكن ماكرو المعرفة من قبل البيئة التي تمثل <م> نهاية للتيار. أنا لم أر التعليمات البرمجية الخاصة بك، ولكن جمع تفعلونه هو شيء من هذا القبيل:

while ((c=getchar()) != EOF) {
    // do something
}
while ((c=getchar()) != EOF) {
    // do something else
}

عند كتابة الحرف EOF أول مرة، لإنهاء السلسلة الأولى، يتم إغلاق تيار لا رجعة فيه. وهذا هو، وضع تيار هو أن يتم إغلاقه.

وهكذا، فإن محتويات الثانية في حين حلقة يتم تشغيل أبدا.

وبدلا من وقف إدخال القراءة في EOF - على وهي ليست شخصية - يمكنك التوقف عند ENTER

.
while((c = getchar()) != '\n')
{
    if (c == EOF) /* oops, something wrong, input terminated too soon! */;
    a[x] = c;
    x++;
}

وEOF هو إشارة إلى أن مساهمة إنهاء. كنت تقريبا مضمونة أن جميع مدخلات من المستخدم النهائي مع '\ ن': هذا هو مفتاح الماضي قام المستخدم بكتابة!


وتحرير: ما زال بإمكانك استعمال Ctrl + D وclearerr() لإعادة دفق الإدخال

.
#include <stdio.h>

int main(void) {
  char a[100], b[100];
  int c, k;

  printf("Enter a: "); fflush(stdout);
  k = 0;
  while ((k < 100) && ((c = getchar()) != EOF)) {
    a[k++] = c;
  }
  a[k] = 0;

  clearerr(stdin);

  printf("Enter b: "); fflush(stdout);
  k = 0;
  while ((k < 100) && ((c = getchar()) != EOF)) {
    b[k++] = c;
  }
  b[k] = 0;

  printf("a is [%s]; b is [%s]\n", a, b);
  return 0;
}
$ ./a.out
Enter a: two
lines (Ctrl+D right after the next ENTER)
Enter b: three
lines
now (ENTER + Ctrl+D)
a is [two
lines (Ctrl+D right after the next ENTER)
]; b is [three
lines
now (ENTER + Ctrl+D)
]
$
<اقتباس فقرة>   

وكيف تدخل فارغة في البرنامج؟

ويمكنك تنفيذ وظيفة -print0 باستخدام:

putchar(0);

وهذا سوف طباعة حرف ASCII NUL '\ 0' لsdtout.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top