Di thread ini, kita melihat contoh-contoh dari penggunaan yang baik dari goto
di C atau C++. It's terinspirasi oleh jawaban orang-orang yang terpilih karena mereka pikir aku sedang bercanda.
Ringkasan (label berubah dari aslinya untuk membuat niat bahkan lebih jelas):
infinite_loop:
// code goes here
goto infinite_loop;
Mengapa itu's lebih baik daripada alternatif:
goto
adalah
membangun bahasa yang menyebabkan
tanpa syarat cabang. Alternatif
tergantung pada menggunakan struktur
mendukung cabang bersyarat,
dengan merosot selalu benar
kondisi.istirahat (meskipun itu's masih mungkin untuk berprinsip hacker untuk mensimulasikan
lanjutkandengan dini
goto`).Aturan:
Let's melihat apakah kita bisa bicara tentang hal ini seperti tumbuh up.
Edit
Pertanyaan ini tampaknya selesai sekarang. Itu dihasilkan beberapa kualitas tinggi jawaban. Terima kasih untuk semua orang,
terutama mereka yang mengambil lingkaran kecil contoh yang serius. Paling skeptis yang bersangkutan
oleh kurangnya blok lingkup. Seperti @quinmars kemukakan dalam komentar, anda selalu dapat menempatkan kawat gigi di sekitar
loop tubuh. Saya perhatikan secara sepintas bahwa for(;;)
dan while(true)
don't memberikan kawat gigi
secara gratis baik (dan menghilangkan mereka dapat menyebabkan menjengkelkan bug). Lagi pula, saya tidak't buang lebih
dari kekuatan otak anda pada sepele ini - aku bisa hidup dengan tidak berbahaya dan idiomatik for(;;)
dan while(true)
(sama dengan baik jika saya ingin mempertahankan pekerjaan saya).
Mengingat tanggapan lain, saya melihat bahwa banyak orang melihat goto
sebagai sesuatu yang anda selalu
harus menulis ulang dengan cara lain. Tentu saja anda dapat menghindari goto
dengan memperkenalkan loop,
tambahan bendera, tumpukan bersarang jika, atau apapun, tapi mengapa tidak mempertimbangkan apakah
gotoadalah mungkin alat terbaik untuk pekerjaan itu? Dengan kata lain, berapa banyak keburukan adalah orang-orang siap untuk bertahan untuk menghindari menggunakan built-in fitur bahasa untuk tujuan yang telah ditetapkan? Saya ambil adalah bahwa bahkan menambahkan bendera adalah harga yang terlalu tinggi untuk membayar. Aku suka variabel untuk mewakili hal-hal di masalah atau solusi domain. 'Semata-mata untuk menghindari
goto`' doesn't memotongnya.
I'll menerima jawaban pertama yang memberikan pola C untuk percabangan untuk pembersihan blok. IMO, hal ini membuat terkuat kasus untuk goto
dari semua diposting jawaban, tentu
jika anda mengukurnya dengan gerakan-gerakan pembenci memiliki untuk pergi melalui untuk menghindari itu.
Heres satu trik saya'telah mendengar dari orang-orang yang menggunakan. I've pernah melihat itu di alam liar sekalipun. Dan itu hanya berlaku untuk C karena C++ memiliki RAII untuk melakukan hal ini lebih ideomatik.
void foo()
{
if (!doA())
goto exit;
if (!doB())
goto cleanupA;
if (!doC())
goto cleanupB;
/* everything has succeeded */
return;
cleanupB:
undoB();
cleanupA:
undoA();
exit:
return;
}
Berikut ini's my non-contoh konyol, (dari Stevens APITUE) untuk Unix system call yang dapat terganggu oleh sinyal.
restart:
if (system_call() == -1) {
if (errno == EINTR) goto restart;
// handle real errors
}
Alternatif lain adalah merosot loop. Versi ini berbunyi seperti bahasa inggris "jika sistem panggilan itu terganggu oleh sinyal, restart".
Jika Duff's perangkat doesn't perlu goto, maka tidak seharusnya anda! ;)
void dsend(int count) {
int n;
if (!count) return;
n = (count + 7) / 8;
switch (count % 8) {
case 0: do { puts("case 0");
case 7: puts("case 7");
case 6: puts("case 6");
case 5: puts("case 5");
case 4: puts("case 4");
case 3: puts("case 3");
case 2: puts("case 2");
case 1: puts("case 1");
} while (--n > 0);
}
}
kode di atas dari Wikipedia masuk.
Sangat umum.
do_stuff(thingy) {
lock(thingy);
foo;
if (foo failed) {
status = -EFOO;
goto OUT;
}
bar;
if (bar failed) {
status = -EBAR;
goto OUT;
}
do_stuff_to(thingy);
OUT:
unlock(thingy);
return status;
}
Satu-satunya hal yang pernah saya gunakan goto
adalah untuk melompat ke depan, biasanya dari blok-blok, dan tidak pernah menjadi blok-blok. Hal ini untuk menghindari penyalahgunaan do{}while(0)
dan konstruksi lain yang meningkatkan bersarang, sementara tetap mempertahankan dibaca, kode terstruktur.
Aku punya apa-apa terhadap gotos secara umum, tapi saya bisa memikirkan beberapa alasan mengapa anda tidak't ingin menggunakan mereka untuk loop seperti yang anda sebutkan:
Salah satu tempat yang baik untuk menggunakan goto dalam prosedur yang dapat membatalkan di beberapa titik, masing-masing memerlukan berbagai tingkat pembersihan. Gotophobes selalu dapat menggantikan gotos dengan kode terstruktur dan serangkaian tes, tapi saya pikir ini lebih mudah karena menghilangkan berlebihan lekukan:
jika (!openDataFile()) goto keluar;jika (!getDataFromFile()) goto closeFileAndQuit;
jika (!allocateSomeResources) goto freeResourcesAndQuit;
// Melakukan lebih banyak pekerjaan di sini....
freeResourcesAndQuit: // sumber daya gratis closeFileAndQuit: // menutup file berhenti: // berhenti!
Meskipun saya've tumbuh untuk membenci pola ini dari waktu ke waktu, it's-grained ke COM pemrograman.
#define IfFailGo(x) {hr = (x); if (FAILED(hr)) goto Error}
...
HRESULT SomeMethod(IFoo* pFoo) {
HRESULT hr = S_OK;
IfFailGo( pFoo->PerformAction() );
IfFailGo( pFoo->SomeOtherAction() );
Error:
return hr;
}
I've melihat goto digunakan dengan benar, tetapi situasi ini adalah normaly jelek. Hal ini hanya ketika menggunakan goto
itu sendiri jadi jauh lebih buruk dari yang asli.
@Johnathon Belanda poblem adalah anda're versi ini kurang jelas. orang-orang tampaknya takut variabel lokal:
void foo()
{
bool doAsuccess = doA();
bool doBsuccess = doAsuccess && doB();
bool doCsuccess = doBsuccess && doC();
if (!doCsuccess)
{
if (doBsuccess)
undoB();
if (doAsuccess)
undoA();
}
}
Dan saya lebih suka loop seperti ini, tapi beberapa orang lebih suka while(true)
.
for (;;)
{
//code goes here
}
Saya don't menggunakan goto's diriku, namun aku tidak bekerja dengan sekali orang yang akan menggunakannya dalam kasus-kasus tertentu. Jika saya ingat dengan benar, alasan nya adalah sekitar masalah kinerja - dia juga memiliki aturan-aturan khusus untuk cara. Selalu dalam fungsi yang sama, dan label selalu di BAWAH ini pernyataan goto.
Saya mengeluh tentang ini adalah bahwa anda kehilangan blok pelingkupan; setiap variabel lokal dideklarasikan antara gotos tetap berlaku jika loop pernah rusak dari. (Mungkin anda're asumsi loop berjalan selamanya; I don't berpikir bahwa's yang asli pertanyaan penulis bertanya, meskipun.)
Masalah scoping lebih dari sebuah isu dengan C++, seperti beberapa benda yang mungkin menjadi tergantung pada mereka dtor dipanggil pada waktu yang tepat.
Bagi saya, alasan terbaik untuk menggunakan goto adalah selama multi-langkah inisialisasi proses di mana itu's penting bahwa semua ppatk adalah mundur jika salah satu gagal, yang la:
if(!foo_init())
goto bye;
if(!bar_init())
goto foo_bye;
if(!xyzzy_init())
goto bar_bye;
return TRUE;
bar_bye:
bar_terminate();
foo_bye:
foo_terminate();
bye:
return FALSE;
#include <stdio.h>
#include <string.h>
int main()
{
char name[64];
char url[80]; /*The final url name with http://www..com*/
char *pName;
int x;
pName = name;
INPUT:
printf("\nWrite the name of a web page (Without www, http, .com) ");
gets(name);
for(x=0;x<=(strlen(name));x++)
if(*(pName+0) == '\0' || *(pName+x) == ' ')
{
printf("Name blank or with spaces!");
getch();
system("cls");
goto INPUT;
}
strcpy(url,"http://www.");
strcat(url,name);
strcat(url,".com");
printf("%s",url);
return(0);
}