Tanda tangan fungsi Anda harus:
const char * myFunction()
{
return "My String";
}
Latar Belakang:
Ini sangat mendasar untuk C & C ++, tetapi sedikit lebih banyak diskusi harus dilakukan.
Dalam C (& C ++ dalam hal ini), string hanyalah array byte yang diakhiri dengan byte nol - maka istilah "string-nol" digunakan untuk mewakili rasa string tertentu ini. Ada jenis string lain, tetapi di C (& C ++), rasa ini secara inheren dipahami oleh bahasa itu sendiri. Bahasa lain (Java, Pascal, dll.) Menggunakan metodologi berbeda untuk memahami "string saya".
Jika Anda pernah menggunakan Windows API (yang ada di C ++), Anda akan melihat parameter fungsi yang cukup teratur seperti: "LPCSTR lpszName". Bagian 'sz' merepresentasikan gagasan 'string-zero' ini: array byte dengan terminator null (/ nol).
Klarifikasi:
Demi 'intro' ini, saya menggunakan kata 'bytes' dan 'characters' secara bergantian, karena cara ini lebih mudah dipelajari. Ketahuilah bahwa ada metode lain (karakter lebar, dan sistem karakter multi-byte ( mbcs )) yang digunakan untuk menangani karakter internasional. UTF-8 adalah contoh mbcs. Demi intro, saya diam-diam 'melewatkan' semua ini.
Penyimpanan:
Ini berarti bahwa string seperti "string saya" sebenarnya menggunakan 9 + 1 (= 10!) Byte. Hal ini penting untuk diketahui saat Anda akhirnya bisa mengalokasikan string secara dinamis.
Jadi, tanpa 'penghentian nol' ini, Anda tidak memiliki string. Anda memiliki serangkaian karakter (juga disebut buffer) yang berkeliaran di memori.
Data umur panjang:
Penggunaan fungsinya seperti ini:
const char * myFunction()
{
return "My String";
}
int main()
{
const char* szSomeString = myFunction(); // Fraught with problems
printf("%s", szSomeString);
}
... umumnya akan membuat Anda mendapatkan kesalahan acak tidak tertangani / segmen dan sejenisnya, terutama 'di jalan'.
Singkatnya, meskipun jawaban saya benar - 9 kali dari 10 Anda akan mendapatkan program yang macet jika Anda menggunakannya seperti itu, terutama jika menurut Anda 'praktik yang baik' untuk melakukannya dengan cara itu. Singkatnya: Biasanya tidak.
Misalnya, bayangkan suatu saat nanti, string sekarang perlu dimanipulasi dengan cara tertentu. Umumnya, pembuat kode akan 'mengambil jalan yang mudah' dan (mencoba) menulis kode seperti ini:
const char * myFunction(const char* name)
{
char szBuffer[255];
snprintf(szBuffer, sizeof(szBuffer), "Hi %s", name);
return szBuffer;
}
Artinya, program Anda akan macet karena kompiler (mungkin / mungkin tidak) telah melepaskan memori yang digunakan szBufferpada saat printf()in main()dipanggil. (Kompiler Anda juga harus memperingatkan Anda tentang masalah seperti itu sebelumnya.)
Ada dua cara untuk mengembalikan string yang tidak akan mudah muntah.
- mengembalikan buffer (statis atau dialokasikan secara dinamis) yang aktif untuk sementara waktu. Dalam C ++ gunakan 'kelas pembantu' (misalnya,
std::string) untuk menangani umur panjang data (yang memerlukan perubahan nilai kembalian fungsi), atau
- meneruskan buffer ke fungsi yang diisi dengan informasi.
Perhatikan bahwa tidak mungkin menggunakan string tanpa menggunakan pointer di C. Seperti yang telah saya tunjukkan, string itu sama. Bahkan di C ++ dengan kelas template, selalu ada buffer (yaitu pointer) yang digunakan di latar belakang.
Jadi, untuk menjawab dengan lebih baik (pertanyaan yang sekarang dimodifikasi). (Pasti ada berbagai 'jawaban lain' yang dapat diberikan.)
Jawaban yang Lebih Aman:
Contoh 1, menggunakan string yang dialokasikan secara statis:
const char* calculateMonth(int month)
{
static char* months[] = {"Jan", "Feb", "Mar" .... };
static char badFood[] = "Unknown";
if (month<1 || month>12)
return badFood; // Choose whatever is appropriate for bad input. Crashing is never appropriate however.
else
return months[month-1];
}
int main()
{
printf("%s", calculateMonth(2)); // Prints "Feb"
}
Apa yang dilakukan 'statis' di sini (banyak pemrogram tidak menyukai jenis 'alokasi' ini) adalah string dimasukkan ke dalam segmen data program. Artinya, dialokasikan secara permanen.
Jika Anda pindah ke C ++, Anda akan menggunakan strategi serupa:
class Foo
{
char _someData[12];
public:
const char* someFunction() const
{ // The final 'const' is to let the compiler know that nothing is changed in the class when this function is called.
return _someData;
}
}
... tapi mungkin lebih mudah menggunakan kelas helper, seperti std::string, jika Anda menulis kode untuk Anda gunakan sendiri (dan bukan bagian dari pustaka untuk dibagikan dengan orang lain).
Contoh 2, menggunakan buffer yang ditentukan pemanggil:
Ini adalah cara yang lebih 'sangat mudah' untuk menyebarkan string. Data yang dikembalikan tidak tunduk pada manipulasi oleh pihak yang menelepon. Artinya, contoh 1 dapat dengan mudah disalahgunakan oleh pihak yang menelepon dan membuat Anda terkena kesalahan aplikasi. Dengan cara ini, jauh lebih aman (meskipun menggunakan lebih banyak baris kode):
void calculateMonth(int month, char* pszMonth, int buffersize)
{
const char* months[] = {"Jan", "Feb", "Mar" .... }; // Allocated dynamically during the function call. (Can be inefficient with a bad compiler)
if (!pszMonth || buffersize<1)
return; // Bad input. Let junk deal with junk data.
if (month<1 || month>12)
{
*pszMonth = '\0'; // Return an 'empty' string
// OR: strncpy(pszMonth, "Bad Month", buffersize-1);
}
else
{
strncpy(pszMonth, months[month-1], buffersize-1);
}
pszMonth[buffersize-1] = '\0'; // Ensure a valid terminating zero! Many people forget this!
}
int main()
{
char month[16]; // 16 bytes allocated here on the stack.
calculateMonth(3, month, sizeof(month));
printf("%s", month); // Prints "Mar"
}
Ada banyak alasan mengapa metode kedua lebih baik, terutama jika Anda menulis perpustakaan untuk digunakan oleh orang lain (Anda tidak perlu mengunci skema alokasi / deallokasi tertentu, pihak ketiga tidak dapat memecahkan kode Anda, dan Anda tidak perlu menautkan ke pustaka manajemen memori tertentu), tetapi seperti semua kode, terserah Anda tentang apa yang paling Anda sukai. Oleh karena itu, kebanyakan orang memilih misalnya 1 sampai mereka terbakar berkali-kali sehingga mereka menolak untuk menulis seperti itu lagi;)
Penolakan:
Saya pensiun beberapa tahun yang lalu dan nilai C saya agak berkarat sekarang. Kode demo ini harus dikompilasi dengan baik dengan C (meskipun demikian, tidak masalah untuk kompiler C ++).