Saya mencoba untuk mengumpulkan potongan kode ini dari buku "The C Programming Language" (K & R). Ini adalah versi sederhana dari program UNIX wc
:
#include <stdio.h>
#define IN 1; /* inside a word */
#define OUT 0; /* outside a word */
/* count lines, words and characters in input */
main()
{
int c, nl, nw, nc, state;
state = OUT;
nl = nw = nc = 0;
while ((c = getchar()) != EOF) {
++nc;
if (c == '\n')
++nl;
if (c == ' ' || c == '\n' || c == '\t')
state = OUT;
else if (state == OUT) {
state = IN;
++nw;
}
}
printf("%d %d %d\n", nl, nw, nc);
}
Dan saya mendapatkan kesalahan berikut:
$ gcc wc.c
wc.c: In function ‘main’:
wc.c:18: error: ‘else’ without a previous ‘if’
wc.c:18: error: expected ‘)’ before ‘;’ token
Edisi ke-2 dari buku ini adalah dari tahun 1988 dan saya cukup baru mengenal C. Mungkin ada hubungannya dengan versi kompiler atau mungkin saya hanya berbicara omong kosong.
Saya telah melihat dalam kode C modern penggunaan main
fungsi yang berbeda:
int main()
{
/* code */
return 0;
}
Apakah ini standar baru atau apakah saya masih dapat menggunakan utama tanpa tipe?
|| c = '\t')
. Apakah itu tampak sama dengan kode lain di baris itu?Jawaban:
Masalah Anda ada pada definisi praprosesor Anda
IN
danOUT
:Perhatikan bagaimana Anda memiliki tanda titik koma di belakangnya di masing-masing. Ketika preprocessor mengembangkannya, kode Anda akan terlihat seperti:
Titik koma kedua itu menyebabkan
else
tidak ada sebelumnyaif
sebagai pertandingan, karena Anda tidak menggunakan tanda kurung. Jadi, hapus titik koma dari definisi preprocessor dariIN
danOUT
.Pelajaran yang didapat di sini adalah bahwa pernyataan preprocessor tidak harus diakhiri dengan titik koma.
Selain itu, Anda harus selalu menggunakan kawat gigi!
Tidak ada
else
ambiguitas gantung dalam kode di atas.sumber
Masalah utama dengan kode ini adalah bahwa ini bukan kode dari K&R. Ini mencakup titik koma setelah definisi makro, yang tidak ada dalam buku, yang seperti yang ditunjukkan orang lain mengubah artinya.
Kecuali saat membuat perubahan dalam upaya memahami kode, Anda harus membiarkannya sampai Anda benar-benar memahaminya. Anda hanya dapat mengubah kode yang Anda pahami dengan aman.
Ini mungkin hanya salah ketik di pihak Anda, tetapi itu menggambarkan kebutuhan untuk memahami dan memperhatikan detail saat pemrograman.
sumber
Tidak boleh ada titik koma setelah makro,
dan mungkin seharusnya begitu
sumber
;
itu adalah kesalahan ketik yang tidak memengaruhi masalah, yang berarti kesalahan ketik pada pertanyaan Anda, bukan pada kode yang sebenarnya Anda gunakan.Definisi IN dan OUT akan terlihat seperti ini:
Titik koma menyebabkan masalah! Penjelasannya sederhana: baik IN dan OUT adalah arahan preprocessor, pada dasarnya kompilator akan mengganti semua kemunculan IN dengan 1 dan semua kemunculan OUT dengan 0 di kode sumber.
Karena kode asli memiliki titik koma setelah 1 dan 0, ketika IN dan OUT diganti dalam kode, tanda titik koma tambahan setelah angka menghasilkan kode yang tidak valid, misalnya baris ini:
Akhirnya terlihat seperti ini:
Tapi yang Anda inginkan adalah ini:
Solusi: Hapus titik koma setelah angka dalam definisi aslinya.
sumber
Seperti yang Anda lihat, ada masalah di makro.
GCC memiliki opsi untuk berhenti setelah pra-pemrosesan. (-E) Opsi ini berguna untuk melihat hasil pra-pemrosesan. Faktanya, teknik ini penting jika Anda bekerja dengan basis kode besar di c / c ++. Biasanya makefile akan memiliki target untuk dihentikan setelah pra-pemrosesan.
Untuk referensi cepat: Pertanyaan SO mencakup opsi - Bagaimana cara melihat file sumber C / C ++ setelah preprocessing di Visual Studio? . Ini dimulai dengan vc ++, tetapi juga memiliki opsi gcc yang disebutkan di bawah .
sumber
Bukan masalah, tetapi deklarasi
main()
juga bertanggal, seharusnya seperti ini.Kompilator akan mengasumsikan nilai kembalian int untuk fungsi tanpa fungsi, dan saya yakin kompilator / penaut akan mengatasi kekurangan deklarasi untuk argc / argv dan kurangnya nilai kembalian, tetapi seharusnya ada di sana.
sumber
Coba tambahkan tanda kurung kurawal di sekitar blok kode. Gaya K&R bisa jadi ambigu.
Lihat baris 18. Kompilator memberi tahu Anda di mana masalahnya.
sumber
if
blok Anda nanti, jika Anda lupa menambahkan kurung kurawal karena blok Anda sekarang lebih dari satu baris, perlu beberapa saat untuk men-debug kesalahan itu ...if
klausa dan "lupa" untuk memperbarui tanda kurung kurawal, yah, Anda tidak programmer yang sangat baik.Cara sederhana adalah dengan menggunakan tanda kurung seperti {} untuk masing-masing
if
danelse
:sumber
Seperti jawaban lain yang ditunjukkan, masalahnya ada di
#define
dan titik koma. Untuk meminimalkan masalah ini saya selalu lebih suka mendefinisikan konstanta bilangan sebagaiconst int
:Dengan cara ini Anda menyingkirkan banyak masalah dan kemungkinan masalah. Itu dibatasi hanya oleh dua hal:
Kompilator Anda harus mendukung
const
- yang pada tahun 1988 umumnya tidak benar, tetapi sekarang didukung oleh semua kompiler yang umum digunakan. (AFAIKconst
adalah "dipinjam" dari C ++.)Anda tidak dapat menggunakan konstanta ini di beberapa tempat khusus yang membutuhkan konstanta seperti string. Tapi saya pikir program Anda tidak seperti itu.
sumber
const int
tidak bisa di C.