עבור לתוכן

בעיה ב C - על דריסת הזיכרון ש�ל gets

Featured Replies

פורסם

חברי הפורום שלום.

אני צריך להגיש תוכנה ב C (למכללה) שקולטת מחרוזת מהמשתמש, ומדפיסה אותה כך שכל מילה תופיע בשורה בנפרד. גודל המחרוזת צריך להיות 100 תוuים, ואם הוכנסו יותר - צריך להציג אזהרה ולבקש שוב מחרוזת. סיום התוכנית - הכנסת מחרוזת ריקה. אסור לנו להשתמש בפונקציות הספריה של string.h. הקימפול מתבצע ב borland C ל DOS (מה לעשות, זה מה שהם רוצים).

את כל זה עשיתי, הבעיה שלי היא עם קליטת המחרוזת עצמה - אני לא מכיר דרך אחרת לקליטת מחרוזת עם רווחים וטאבים ללא שימוש ב gets, אבל הבעיה היא ש gets מאפשרת להכניס מחרוזת גדולה יותר מהמחזורת שהוגדרה כמערך. כתוצאה מכך, אם אני קולט מחרוזת ארוכה מדיי, ואז מנסה לצאת מהתוכנית ע"י הכנסת מחרוזת ריקה (לחיצת enter), התוכנה נתקעת או גורמת לקריסת ה NTVDM של windows. לי זה ברור שאני כנראה דורס זיכרון חיוני ע"י הכנסת מחרוזת גדולה יותר מ 100 תווים, ולכן יש את הקריסה הזו, אבל אני פשוט לא יודע איך להתגבר על הבעיה הזו.

הנה קוד התוכנית, למקרה שמישהו מתעניין:

#include <stdio.h>
#define STRING_SIZE 100

/* This function gets the values for the string from the user.
It returns 0 if an empty string is entered */
int GetInputFromUser (char string[], int size);
// This function prints a string, each word in a line
void PrintString(char string[]);
// This function returns the length of a string
int MyStrlen(char string[]);
// This function checks returns 1 if the char is a space or a tab
int checkSpaceTab(char ch);

int main()
{
char str[STRING_SIZE+1];
printf("Enter a string:\n");
while (GetInputFromUser(str,STRING_SIZE)!=0)
{
printf("\nYour string is:\n");
PrintString(str);
printf("\nstring size is %d\n",MyStrlen(str));
printf("\nEnter a string:\n");
}
printf("You have entered an empty string - ending program\n"); // if string size is 0
getch();
return 0;
} // end main

int GetInputFromUser (char string[], int size)
{
int reEnterInput=0;
do
{
flushall();
gets(string); // gets the string until "\n"
if (MyStrlen(string) == 0) return 0;
if (MyStrlen(string) > size)
{
printf("Warrning - your string is too long\nPlease enter another string:\n");
reEnterInput=1;
} // end if - string too long
else reEnterInput=0; // if string is the right size
} while (reEnterInput==1);
return 1;
} // end GetInputFromUser function

void PrintString(char string[])
{
int i, IsThereAFirstGoodChar=0;
for (i=0; string[i]!='\0'; i++) // run until end of string
{
if (checkSpaceTab(string[i])==0) // if current char is not space or tab
{
printf("%c",string[i]); // print it
IsThereAFirstGoodChar=1;
} // end if - current char is not a space/tab
else // if current char is a space or a tab
if ((string[i+1]!='\0')) // if the next char is not the end of the string
if (checkSpaceTab(string[i+1])==0) // and the next char is not a space/tab
if (IsThereAFirstGoodChar!=0) // and there has been a non space char before
printf("\n"); // start a new line
} // end for
} // end PrintString function

int MyStrlen(char string[])
{
int counter;
for (counter=0;string[counter]!='\0';counter++);
return counter;
} // end MyStrlen function

int checkSpaceTab(char ch)
{
if (ch=='\t') return 1;
else if (ch==' ') return 1;
return 0;
} // end of checkSpaceTab function

הבעיה היא כנראה בפונקציה GetInputFromUser שמשתמשת ב gets.

אגב, אם אני מקמפל בקומפיילר אחר (אני משתמש ב Code::Blocks, שאצלי משתמשת ב DEV-C כקומפיילר), שמיועד ל windows, אז הכל עובד בצורה תקינה ואין קריסות.

כל עזרה תתקבל בברכה.

בתודה,

שי

פורסם

תקרא על fgets. זו הפונקציה שאתה צריך.

פורסם
  • מחבר

תודה, אבל הבעיה היא שאני צריך לגלות אם יש חריגה מאורך המחרוזת (ואז להציג הודעת שגיאה, ולבקש מהמשתמש להכניס שוב את המחרוזת) , ו fgets לא תיתן לי לחרוג מאורך המחרוזת שאני מגדיר, כך שלא יהיה אפשר לבדוק אם יש חריגה, גם אם בפועל הכנסתי יותר תווים מהמותר (הם פשוט "מקוצצים").

אני מניח שאין ממש פיתרון לבעיה הזו, אלה פשוט להגדיר מערך תווים גדול מספיק, כך שכל חריגה מעל 100 תווים מותרים לא תדרוס נתונים קיימים בזיכרון.

פורסם

אתה יכול לקרוא כל תו בנפרד (נדמה לי עם getc() אבל אני כבר קצת חלוד), לצרף אותו כל פעם למערך בגודל קבוע, ואם אתה חורג מהגודל הזה, להפסיק לצרף את התו למערך.

פורסם

אז תקלוט תו אחד יותר ממה שאתה צריך ותבדוק אם יש בו ערך.

פורסם
  • מחבר

תודה על התגובות. עם fgets לא למדנו לעבוד, אז עדיף שאני לא אשתמש בו בשלב זה. לגבי הקליטה עם getche - חשבתי על זה, אבל אז אין אפשרות למחוק תו שהוכנס (ברגע שלוחצים על מקש במקלדת הוא נקלט - אין צורך בהכנסת תו אחר). בסופו של דבר פשוט הגדרתי את גודל מערך התווים (המחרוזת) ל 128 תווים, מכיוון שלא ניתן להכניס ב DOS יותר מ 127 תווים, ואז בטוח שלא תהיה גלישה לזיכרון לא מורשה.

בעתיד אני אשתמש במה שהוצע לי כאן.

תודה על העזרה.

ארכיון

דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.

דיונים חדשים