قراءة الملف مع comma delimiter باستخدام fgets () و strtok ()

StackOverflow https://stackoverflow.com/questions/4335640

  •  30-09-2019
  •  | 
  •  

سؤال

لدي ملف نصي مع ثلاثة حقول مفصولة بفواصل. مثال على محتوى ملف النصي الخاص بي: 12345 ، NEWROGERING NEWBIE ، BS ME لتحميل الملف في البرنامج ، استخدمت الرمز أدناه .... مشكلتي هي في بعض الأحيان تعمل الكود وأحيانًا لا (لا (لا تظهر رسالة الخطأ أن البرنامج يغلق نفسه ولا يستمر). لاحظت أيضًا أن الملف النصي فارغ (لا يوجد شيء مكتوب) إنه يغلق نفسه تلقائيًا ولا يستمر. سيكون مساعدتك موضع تقدير كبير. شكرًا!

int read(){
     FILE *stream = NULL;
     int ctr;
     char linebuffer[45];
     char delims[]=", ";
     char *number[3];
     char *token = NULL;
     stream = fopen("student.txt", "rt");
     if (stream == NULL) stream = fopen("student.txt", "wt");
     else {
          printf("\nReading the student list directory. Wait a moment please...");
          while(!feof(stream)){            
                ctr=0;
                fgets(linebuffer, 46, stream);
                token = strtok(linebuffer, delims);
                while(token != NULL){
                  number[ctr] = linebuffer;
                  token = strtok(NULL, delims); 
                  ctr++;
                }
          recordCtr++;                      
          }                     
     recordCtr--;
     }
     fclose(stream);
}    
هل كانت مفيدة؟

المحلول

أنت لا تنسخ token بمجرد العثور عليها. لا يمكنك النسخ linebuffer, ، نظرًا لأن البيانات الموجودة هناك سيتم الكتابة فوقها حيث يتم تحميل السطر التالي.

هذا الخط:

number[ctr] = linebuffer;

يجب الإشارة token لإنقاذ الرمز المميز الذي تم العثور عليه مؤخرًا ، لكنه لا. ربما يجب أن تقرأ شيئًا مثل1:

strcpy(number[ctr], token);

ولكن بعد ذلك ، يجب عليك تغيير الإعلان للتأكد من وجود مساحة:

char number[3][32];

من الواضح أن هذا يقدم خطر التجاوز العازلة ، إذا كان هناك رمز طويل جدًا ، فلن يناسب ذلك. أفضل طريقة للتعامل التي يتم تركها كتمرين. قون

1 لماذا يسمى المتجه المؤقت "الرقم" عند استخدامه لتخزين رقمين وسلسلة واحدة (الاسم) خارج عني.

نصائح أخرى

لك fgets() تحتاج المكالمة إلى تحديد 45 على أنها الحجم أو أنك oveflow المخزن المؤقت عندما يكتب FGETS Terminator NULL. من شأنه أن يعين سلسلة "delims" لتكون سلسلة فارغة.

كما أنك لا تعيد أي قيمة على الرغم من أن إعلان الوظيفة ينص على أنه يعيد int.

لا أعرف ما هو تعريف "طالب الهيكل" الخاص بك ، لكنك قد تفيض المخازن المؤقتة عند استخدامها strcpy(). كما أنك تقلل من "recordCtr". لماذا ا؟ لماذا تفتح الملف للكتابة إذا لم تتمكن من فتحه للكتابة؟ لماذا ا؟ إذا فشل ذلك أيضًا ، فإنك تتصل بـ fclose على مؤشر فارغ. أشك في أن هذا يساعد كثيرا.

لقد لاحظت للتو أنك لا تقوم بتهيئة "الرقم". إذا لم تحصل على ثلاثة أرقام على السطر الأول ، فأنت بعد ذلك strcpy() من مؤشر غير مهتم. من المحتمل أن يكون له قيمة فارغة حتى يتسنى البرنامج.

كما أن لديك مجموعة من الحجم 3 ، ولكن إذا كان الخط الذي تقرأه يحتوي على أكثر من 3 حقول مفصولة بفواصل ، فسوف تتفوق على الصفيف.

ربما هناك العديد من الأخطاء الأخرى أيضًا.

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

هناك الكثير من الأخطاء المحتملة في هذا الرمز. ماذا يحدث إذا كان الخط أكثر من 45 حرفًا؟ أنت لا تجرد الخطوط الجديدة. لا تقوم بتحويل الأوتار إلى أرقام (على الرغم من أن الرقم [1] يبدو أنه بيانات سلسلة ، فلماذا تخزينها في صفيف تسمى "الأرقام"؟) أو تحقق من أن FGTS قد أعادت بالفعل أي بيانات أو تحقق من عدد البيانات التي تقوم بها احصل على.

دع المشتري حذار.

سترتوك قد يكون لديك بعض حالات الحافة للقلق.

"واحد اثنين ثلاثة" سوف تسفر عن 3 رموز.

"واحدة ثلاثة" سوف تسفر عن 2 الرموز.

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