עבור לתוכן

שאלה ב- C++

Featured Replies

פורסם

1) מה הדרך הכי יעילה (מבחינת זמן ריצה) להפוך char ל-std::string?

2) האם יש אובייקט "כללי" ב-c++? משהו כמו Object ב-Java?

אם כן אז יש לו פונקציה שדומה ל-toString כדי שאוכל להפוך אותו ל-string?

תודה ושנה אזרחית טובה!

:xyxthumbs:

פורסם

1. יש פורום לשפות תכנות עילית. הועבר.

2. באמצעות הבנאי של string.

3. אתה יכול להגדיר משתנה מטיפוס *void. זה אומר שהמשתנה הוא מצביע, אבל לא אומר לאיזה טיפוס. אחר כך אפשר באמצעות casting להמיר אותו חזרה למה שאתה רוצה.

4. אין ב-++C פונקציה סטנדרטית להפוך אובייקט למחרוזת. אם אתה רוצה להיות מסוגל להדפיס את האובייקט, אתה יכול להגדיר את האופרטור >> של cout להיות מסוגל להדפיס אותו, כמו בדוגמה כאן:

http://www.codeproject.com/KB/cpp/cfraction.aspx?fid=15432&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=10

פורסם
  • מחבר

אז אם האובייקט הכללי הזה הוא הוא בטוח char או string אז אפשר יהיה לעשות לו פשוט cout?

ואתה בטוח שיש ל-string קונסטרקטור מ-char?

הייתי בודק בעצמי אבל כרגע אין לי IDE של C++ על המחשב.. עוד מעט זה יסיים להוריד...

פורסם

ל-string יש constructor מ-char* אל תדאג. מצד שני הוא מבצע הקצת זכרון דינמית, ולכן תלוי במקרה שלך אבל זה לא בהכרח הדרך היעילה ביותר.

אכן ניתן להדפיס עם cout כל char* ו-string. אם אתה רוצה להדפיס Unicode (כלומר wstring או wchar_t*) אז צריך להשתמש ב-wcout.

לגבי נושא הירושה, יש צורך בהבהרה:

ב-C++ בפירוש אין מחלקה שכולם יורשים ממנה, וזו פשוט לא חלק מהפילוסופיה של השפה. הגישה של C++ אומרת שאתה לא משלם על מה שאתה לא צריך, או במילים אחרות: אם רוצים, צריך שאפשר יהיה לייצר עם מחלקות קוד יעיל כמו קוד ללא מחלקות. אם כל האובייקטים היו יורשים מ-"object" ולכולם היתה מתודה וירטואלית של ToString, אז כולם היו משלמים את המחיר, מעבר למה שצריך קוד C רגיל.

בנוסף, קיום מחלקה שכולם יורשים ממנה נקרא לפעמים cosmic hierarchy וזה נחשב לרוב תכנון גרוע ב-C++ עקב הבעיות שהוא מייצר.

אם אתה רוצה, אתה יכול להגדיר בקוד שלך מחלקה ולרשת את שאר המחלקות ממנה.

פורסם
  • מחבר

הקוד הבא גרם להדפסה של התו 'a' ולאחריו כל מיני שטויות.


char c = 'a';
string s(&c);
cout << s << endl;

אז זה לא מתאים לי בשביל להמיר כמו שצריך מתו למחרוזת...

אשמח להצעה אחרת

עריכה:


void* c;
c = new char('a');
cout << *c << endl;

לא מתקמפל. ואם אני מנסה להדפיס את c אז זה פשוט מדפיס כתובת.

אין דרך לפתור את זה? אפשר להניח ש-c מצביע ל-string או ל-char.

פורסם

אחר כך אפשר באמצעות casting להמיר אותו חזרה למה שאתה רוצה.

אי אפשר לעשות dereference ל-*void, כי אין לקומפיילר טיפוס להמיר אליו.

פורסם

הקוד הבא גרם להדפסה של התו 'a' ולאחריו כל מיני שטויות.

כדי שהבנאי של string מתוך char* יעבוד, המחרוזת חייבת להיות null-terminated (כלומר להסתיים ב-0\). במקרה שלך זה לא מתקיים כי אחרי הזכרון שהוקצה לתו a יש זבל אקראי. כדי שזה יעבוד תצטרך להגדיר משהו כמו:


char s[2]={'a','\0'};
string(s);


char c = 'a';
string s(&c);
cout << s << endl;

אז זה לא מתאים לי בשביל להמיר כמו שצריך מתו למחרוזת...

אשמח להצעה אחרת


void* c;
c = new char('a');
cout << *c << endl;

לא מתקמפל. ואם אני מנסה להדפיס את c אז זה פשוט מדפיס כתובת.

אין דרך לפתור את זה? אפשר להניח ש-c מצביע ל-string או ל-char.

אתה לא יכול לעשות dereference ל-*void. הביטוי c* חסר משמעות. על מנת שיהיה בעל משמעות, אתה צריך לעשות casting מפורש:



cout << *(char*)c << endl;

פורסם
  • מחבר

אוקיי.

תודה רבה על העזרה!

פורסם

כמה הערות חשובות מאוד של הקוד של QttP: (מה שהוא אמר זה נכון בגדול):

ניתן לבנות string מתוך char* שהוא NULL-terminated שזה ה-string הסטנדרטי ב-C. ובגלל שהוא הסטנדרטי, לא צריך לעבוד קשה כדי ליצור אותו, הקומפיילר יעשה זאת בשבילך.


char s1[] = "a";
char s2[2] = {'a', '\0'}; /* effectively the same as s1 */
const char *s3 = "a"; /* not the same as s2 but more commond then s2 */
string(s1);
string(s2);
string(s3);

המרה מ-void*:

וכאן אנו רואים בדיוק למה זה מסוכן, ועדיף להמנע מזה אלא כאשר ממש צריך.

באופן כללי, עדיף להמיר ל-const char* אם אין צורך בשינוי המחרוזת, כי אתה לא יודע מאיפה הגיע המצביע, ומה בדיוק עושה הפונקציה שקוראים לה.


void *p = "hello world"; /* allowed in C, not in C++ */
const void *p2 = (const void *)"hello world"; /* allowed in C++ */
...
...
char *s = (char*)p;
s[0] = 'j'; /* OH NOES! We are writing on constant data memory area! This is an error! */
...
char *s2= (char*)p2; /* yes, this is allowed even in C++ */
s2[0] = 'j';/* ERROR! */

פורסם

עוד הערה קטנה אחרונה: כשמבצעים casting ב-++C, נהוג להשתמש באופרטור המתאימים של ++C, ולא בהמרה ה"רגילה" של C. כלומר, להשתמש באחד מהאופרטורים const_cast, static_cast, dynamic_cast ו-reinterpret_cast.

במקרה הספציפי הזה, למיטב זכרוני, צריך להשתמש ב-static_cast.

פורסם

הכתיבה לאיזור זיכרון "ליטרלי", לא רק שהיא שגיאה לוגית בתכנית אלא שבמערכות מסויימות זה יגרום לתכנית לעוף מיידית.

הנה דוגמה על לינוקס:



#include <stdio.h>

int main()
{
char* s = "Pello World";

s[0] = 'H';
puts(s);

return 0;
}

לאחר קומפילצה והרצה נקבל:


$ gcc write_const.c -o wrc
$ ./wrc
Segmentation fault

ארכיון

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

דיונים חדשים