Kiat Pemrograman

Siswa di junior- dan tingkat senior kelas CS diharapkan mengetahui beberapa informasi latar belakang tentang C , Unix , dan perangkat lunak pengembangan . Halaman ini menjelaskan beberapa latar belakang ini dan menyarankan beberapa latihan .

C

  1. C memungkinkan Anda untuk mendeklarasikan variabel di luar prosedur apapun. Variabel ini disebut variabel global .
    1. Sebuah variabel global dialokasikan sekali ketika program dijalankan dan tetap dalam memori sampai program berakhir.
    2. Sebuah variabel global dapat dilihat oleh semua prosedur dalam file yang sama.
    3. Anda dapat membuat variabel global dideklarasikan dalam file Ac terlihat oleh semua prosedur dalam beberapa file lainnya Bc, Cc, Dc, ... dengan menyatakan dengan pengubahekstern dalam file Bc, Cc, Dc, ... seperti dalam contoh ini:

      extern int theVariable

      Jika Anda memiliki banyak file berbagi variabel, Anda harus mendeklarasikan extern dalam file header Foo.h (dijelaskan di bawah ) dan menggunakan Foo.h # include dalam file Bc, Cc, Dc, ... . Anda harus mendeklarasikan variabel persis satu file tanpa extern pengubah atau tidak pernah akan dialokasikan sama sekali.
    4. Ini bukan ide yang baik untuk menggunakan terlalu banyak variabel global, karena Anda tidak dapat melokalisasi tempat di mana mereka diakses. Tetapi ada situasi di mana variabel global memungkinkan Anda untuk menghindari melewati banyak parameter untuk fungsi.
  2. String adalah pointer ke array karakter null-dihentikan.
    1. Anda menyatakan string sebagai char * variableName .
    2. Jika string Anda adalah konstan, Anda hanya dapat menetapkan string literal untuk itu:

      char * myString = "Ini adalah string sampel"; 

    3. String kosong baru saja null terminator:

      myString = ""; // String kosong, panjang 0, mengandung nol

    4. Sebuah pointer null bukan nilai string yang valid:

      myString = NULL; // String yang tidak valid

      Anda mungkin menggunakan nilai tersebut untuk menunjukkan akhir dari array string:

      argv [0] = "progname";
      argv [1] = "firstParam";
      argv [2] = "secondParam";
      argv [3] = NULL; // terminator

    5. Jika string dihitung pada saat runtime, Anda perlu untuk cadangan cukup ruang untuk menahannya. Ruangan harus cukup untuk menahan nol di akhir:

      char * myString;
      myString = (char *) malloc (strlen (someString) + 1); // Mengalokasikan ruang
      strcpy (myString, someString); // Copy someString ke myString

    6. Untuk menghindari kebocoran memori, Anda harus akhirnya kembali ruang yang Anda mengalokasikan dengan malloc dengan menggunakan gratis . Parameter yang harus menjadi awal dari ruang dikembalikan oleh malloc :

      gratis ((void *) myString);

      Untuk menjaga kode Anda bersih dan mudah dibaca, Anda harus memanggil free () dalam prosedur yang sama di mana Anda menelepon malloc () ; Anda dapat memanggil prosedur lain antara dua titik untuk memanipulasi string Anda.
    7. Jika Anda menyalin string, Anda harus sangat berhati-hati untuk tidak menyalin lebih byte dari struktur data tujuan dapat terus. Buffer overflows adalah penyebab paling umum dari kelemahan keamanan dalam program. Secara khusus, pertimbangkan untuk menggunakan strncpy () dan strncat () bukan strcpy () dan strcat () .
    8. Jika Anda menggunakan C ++, Anda perlu mengkonversi Anda tali benda ke string C-gaya sebelum melewati mereka dalam sebuah sistem.

      String myString // deklarasi ini hanya bekerja di C ++
      ...
      someCall (myString.c_str ())

      Sayangnya, c_str () mengembalikan sebuah string berubah. Jika Anda membutuhkan string bisa berubah, Anda dapat menyalin data menggunakan strcpy () (seperti di atas) atau Anda dapat melemparkan jenis:

      someCall (const_cast (myString.c_str ()))

      Casting tidak seaman menyalin, karena someCall () mungkin benar-benar memodifikasi string, yang akan membingungkan setiap bagian dari program yang mengasumsikan bahwamyString konstan, yang merupakan perilaku yang biasa C ++ string.
  3. Sebuah penyangga adalah daerah memori bertindak sebagai wadah untuk data. Meskipun data mungkin memiliki interpretasi (seperti array struct dengan berbagai bidang), program yang membaca dan menulis buffer sering memperlakukan mereka sebagai array dari byte. Array byte tidak sama sebagai string, meskipun mereka berdua dinyatakan char * atau arang [] .
    1. Mereka mungkin tidak berisi karakter ASCII dan mereka mungkin tidak null-dihentikan.
    2. Anda tidak dapat menggunakan strlen () untuk menemukan panjang data dalam buffer (karena buffer mungkin berisi nol byte). Sebaliknya, Anda perlu mengetahui panjang data dengan nilai kembali dari sistem panggilan (biasanya baca ) yang dihasilkan data.
    3. Anda tidak dapat menggunakan strcpy () , strcat () , atau rutinitas yang terkait pada buffer byte; sebaliknya, Anda harus menggunakan memcpy () atau bcopy () .
    4. Anda menulis buffer dari 123 byte ke file menggunakan kode seperti ini:

      char * fileName = "/ tmp / foo"
      #define BUFSIZE 4096
      Char buf [BUFSIZE]; // Buffer yang mengandung paling BUFSIZE byte
      ...
      int outfile; // File descriptor, kecil bulat
      int bytesToWrite; // Jumlah byte masih akan ditulis
      char * outPtr = buf;
      ...
      If ((OUTFILE = creat (nama file, 0660)) <0) {// kegagalan
      // melihat hak akses file untuk memahami 0660
      perror (fileName); // Cetak penyebab
      exit (1); // Dan keluar
      }
      bytesToWrite = 123; // Inisialisasi; 123 adalah hanya sebuah contoh
      sementara ((bytesWritten = write (OUTFILE, outPtr, bytesToWrite)) // tidak semua byte telah ditulis belum
      if (bytesWritten <0) {// kegagalan
        perror ( "menulis");
        exit (1);
      }
      OutPtr + = bytesWritten;
      bytesToWrite - = bytesWritten;
      }

    5. Untuk mendapatkan compiler untuk mengalokasikan ruang untuk buffer, Anda harus menyatakan buffer dengan ukuran yang kompilator dapat menghitung, seperti di

      #define BUFSIZE 1024
      Char buf [BUFSIZE];

      Jika Anda hanya menyatakan buffer tanpa ukuran:

      char di buf [];

      maka ia memiliki ukuran yang tidak diketahui dan C tidak mengalokasikan ruang apapun. Itu diterima jika buf adalah parameter formal (yaitu, muncul di header prosedur); parameter aktual (disediakan oleh pemanggil) memiliki ukuran. Tapi itu tidak bisa diterima jika buf adalah variabel. Jika Anda tidak tahu ukuran buffer pada waktu kompilasi, Anda harus menggunakan kode seperti ini:

      char * buf = (char *) malloc (bufferSize);

      mana bufferSize adalah hasil runtime dari beberapa perhitungan.
  4. Anda dapat secara dinamis mengalokasikan dan deallocate memori.
    1. contoh individu dari jenis apa pun:

      typedef ... myType;
      myType * myVariable = (myType *) malloc (sizeof (myType));
      // Anda sekarang dapat mengakses * myVariable.
      ...
      Gratis ((void *) myVariable);

      Sekali lagi, itu adalah praktek pemrograman yang baik untuk memohon gratis () dalam rutinitas yang sama di mana Anda menelepon malloc () .
    2. array satu dimensi dari jenis apa pun:

      myType * myArray = (myType *) malloc (arrayLength * sizeof (myType));
      // MyArray [0] .. myArray [arrayLength - 1] sekarang dialokasikan.
      ...
      Gratis ((void *) myArray);

    3. array dua dimensi yang diwakili oleh sebuah array dari pointer, masing-masing menunjuk ke array:

      myType ** myArray = (myType **) malloc (numRows * sizeof (myType *));
      int rowIndex;
      untuk (rowIndex = 0; rowIndex myArray [rowIndex] = (myType *) malloc (numColumns * sizeof (myType));
      }
      // MyArray [0] [0] .. myArray [0] [numColumns-1] .. myArray [numRows-1] [numColumns-1]
      // sekarang dialokasikan. Anda mungkin ingin menginisialisasi mereka.
      ...
      Untuk (rowIndex = 0; rowIndex gratis ((void *) myArray [rowIndex]);
      }
      Bebas ((void *) myArray);

    4. Jika Anda menggunakan C ++, tidak mencampur baru / menghapus dengan malloc / gratis untuk struktur data yang sama. Keuntungan dari baru / menghapus untuk contoh kelas adalah bahwa mereka secara otomatis memanggil konstruktor, yang mungkin menginisialisasi data, dan destructors, yang dapat menyelesaikan data. Bila Anda menggunakan malloc / gratis , Anda harus secara eksplisit menginisialisasi dan menyelesaikan.
  5. Bilangan bulat
    1. C biasanya merupakan bilangan bulat dalam 4 byte. Misalnya, jumlah 254.235 direpresentasikan sebagai bilangan biner 00000000,00000011,11100001,00011011.
    2. Di sisi lain, teks ASCII mewakili nomor seperti karakter lain, dengan satu byte per digit menggunakan pengkodean standar. Dalam ASCII, jumlah 254.235 direpresentasikan sebagai 00110010, 00110101, 00110110, 00110010, 00110011, 00110101.
    3. Jika Anda perlu menulis file bilangan bulat, umumnya lebih efisien dalam ruang dan waktu untuk menulis versi 4-byte dari mengkonversikannya ke string ASCII dan menulis mereka. Berikut adalah cara untuk menulis satu bilangan bulat ke file terbuka:

      menulis (outfile, & MyInteger, sizeof (MyInteger))

    4. Anda dapat melihat byte individu integer dengan casting sebagai struktur empat byte:

      int IPAddress; // Disimpan sebagai integer, dipahami sebagai 4 bytes
      typedef struct {
      Char Byte1, byte2, byte3, byte4;
      } IPDetails_t;
      IPDetails_t * rincian = (IPDetails_t *) (& IPAddress);
      printf ( "byte 1 adalah% o, byte 2 adalah% o, byte 3 adalah% o, byte 4 adalah% o \ n",
      rincian-> Byte1, rincian-> byte2, rincian-> byte3, rincian-> byte4) ;

    5. Bilangan bulat multi-byte dapat diwakili berbeda pada mesin yang berbeda. Beberapa (seperti Sun SPARCStation) menempatkan byte paling signifikan pertama; orang lain (seperti Intel i80x86 dan turunannya) menempatkan byte paling signifikan pertama. Jika Anda menulis data integer yang mungkin dibaca pada mesin lain, mengkonversi data ke "jaringan" order byte oleh htons ()atau htonl () . Jika Anda membaca data integer yang mungkin telah ditulis pada mesin lain, mengkonversi data dari order "jaringan" untuk urutan byte lokal dengan ntohs () atau ntohl () .
  6. Anda dapat memprediksi letak memori dari struct dan nilai yang sizeof () akan kembali. Contohnya,

    struct foo {
    char; // Menggunakan 1 byte
      // C menyisipkan pad 3-byte sini sehingga b dapat mulai pada 4-byte batas
    int b; // Menggunakan 4 byte
    unsigned short c; // Menggunakan 2 byte
    unsigned char d [2]; // Menggunakan 2 bytes
    };

    Oleh karena itu, sizeof (struct foo ) mengembalikan 12. prediktabilitas ini (untuk arsitektur tertentu) adalah mengapa beberapa panggilan C "bahasa assembler portable". Anda perlu untuk memprediksi tata letak struct saat membuat data yang harus mengikuti format tertentu, seperti header pada paket jaringan.
  7. Anda dapat mendeklarasikan pointer di C untuk jenis dan menetapkan mereka nilai titik itu ke objek dari tipe tersebut.
    1. Secara khusus, C memungkinkan Anda untuk membangun pointer ke bilangan bulat:

      int someInteger;
      int * IntPtr = & someInteger; // Mendeklarasikan variabel pointer bernilai dan memberikan nilai pointer yang sesuai
      someCall (IntPtr); // Melewati pointer sebagai parameter aktual
      someCall (& someInteger); // Memiliki efek yang sama seperti di atas

    2. AC prosedur perpustakaan yang membutuhkan pointer ke nilai yang paling mungkin memodifikasi bahwa nilai (itu menjadi "keluar" atau "keluar" parameter). Dalam contoh di atas, sangat mungkin bahwa someCall memodifikasi nilai integer someInteger .
    3. Anda dapat membangun pointer ke array bilangan bulat dan menggunakannya untuk langkah melalui array.

      #define ARRAY_LENGTH 100
      int intArray [ARRAY_LENGTH];
      int * intArrayPtr;
      ...
      Int sum = 0;
      untuk (intArrayPtr = intArray; intArrayPtr sum + = * intArrayPtr;
      }

    4. Anda dapat membangun pointer ke array struct dan menggunakannya untuk langkah melalui array.

      #define ARRAY_LENGTH 100
      typedef struct {int foo, bar;} pair_t; // Pair_t adalah jenis baru
      pair_t structArray [ARRAY_LENGTH]; // StructArray adalah array dari elemen ARRAY_LENGTH pair_t
      pair_t * structArrayPtr; // StructArrayPtr poin ke elemen pair_t
      ...
      int sum = 0;
      untuk (structArrayPtr = structArray; structArrayPtr sum + = structArrayPtr-> foo + structArrayPtr-> bar;
      }

    5. Bila Anda menambahkan sebuah integer untuk pointer, pointer maju dengan banyak elemen, tidak peduli seberapa besar unsur-unsur yang. compiler tahu ukuran dan melakukan hal yang benar.
  8. Keluaran
    1. Anda memformat output dengan printf atau varian, fprintf .
    2. Format string menggunakan % d , % s , % f untuk menunjukkan bahwa integer, string, atau sebenarnya adalah untuk ditempatkan di output.
    3. Format string menggunakan \ t dan \ n untuk menunjukkan tab dan baris baru.
    4. Contoh:

      printf ( "Saya berpikir bahwa nomor% d yaitu% s \ n", 13, "beruntung");

    5. Pencampuran printf () , fprintf () , dan pengadilan tidak dapat mencetak elemen dalam urutan yang Anda harapkan. Mereka menggunakan area pementasan independen ( "buffer") bahwa mereka mencetak ketika mereka penuh.
  9. Utama () rutin mengambil parameter fungsi yang mewakili parameter baris perintah .
    1. Salah satu cara umum untuk menulis utama rutin ini:

      int main (int argc, char * argv []);

      Di sini, argc adalah jumlah parameter, dan argv adalah array dari string, yaitu, sebuah array dari pointer ke array karakter null-dihentikan.
    2. Dengan konvensi, elemen pertama dari argv adalah nama dari program itu sendiri.

      int main (int argc, char * argv []);
      printf ( "Saya memiliki% d parameter; nama saya% s, dan parameter pertama saya adalah% s \ n",
      argc, argv [0], argv [1]);

  10. Berguna fitur bahasa
    1. Anda dapat kenaikan integer atau memiliki titik pointer ke objek berikutnya dengan menggunakan ++ operator. Hal ini biasanya terbaik untuk menempatkan Operator ini setelah variabel: myInt ++ . Jika Anda menempatkan ++ sebelum variabel, maka variabel bertambah sebelum itu dievaluasi, yang jarang apa yang Anda inginkan.
    2. Anda dapat membangun sebuah tugas dimana variabel sisi kiri berpartisipasi sebagai bagian pertama dari ekspresi di sisi kanan:

      Myint - = 3; // Setara dengan Myint Myint = - 3
      myInt * = 42; // Setara dengan Myint Myint = * 42
      Myint + = 1; // Setara dengan dan mungkin lebih baik untuk myInt ++

    3. Anda dapat mengekspresikan angka dalam desimal, oktal (dengan awalan dengan angka 0 , seperti pada 0453 ), atau hex (dengan awalan dengan 0x , seperti di 0xffaa ).
    4. Anda dapat memperlakukan integer sebagai satu set bit dan melakukan operasi bitwise:

      Myint = myInt | 0444; // Bitwise OR; 0444 adalah di oktal
      myInt & = 0444; // Bitwise DAN dengan tugas singkatan
      myInt = sesuatu ^ apapun; // Bitwise XOR

    5. C dan C ++ memiliki ekspresi kondisional. Alih-alih menulis

      if (a <7)
      a = someValue
      lain
      a = someOtherValue;

      kamu bisa menulis

      a = a <7? someValue: someOtherValue;

    6. Tugas mengembalikan nilai dari sisi kiri, sehingga Anda dapat menyertakan tugas dalam ekspresi yang lebih besar seperti conditional. Tapi Anda harus mengikuti konvensi yang tugas tersebut selalu dikelilingi oleh kurung untuk menunjukkan baik untuk seseorang membaca kode Anda dan untuk compiler bahwa Anda benar-benar berarti tugas, bukan tes kesetaraan. Misalnya, menulis

      if ((s = socket (...)) == -1)

      tidak

      jika (s = socket (...) == -1)

      Versi kedua adalah baik sulit untuk membaca dan, dalam kasus ini, tidak benar, karena operator kesetaraan == memiliki hak lebih tinggi dari operator penugasan = .
  11. Program yang tidak sepele pendek biasanya harus didekomposisi menjadi beberapa file sumber , masing-masing dengan nama yang diakhiri dengan c (untuk program C) atau .cpp (untuk C ++ program).
    1. Cobalah untuk fungsi kelompok yang memanipulasi struktur data yang sama atau telah terkait tujuan ke dalam file yang sama.
    2. Semua jenis, fungsi, variabel global, dan konstanta nyata yang dibutuhkan oleh lebih dari satu file sumber juga harus dinyatakan dalam file header , dengan nama berakhiran .h .
    3. Kecuali untuk fungsi inline, tidak menyatakan tubuh fungsi (atau apa pun yang menyebabkan compiler untuk menghasilkan kode atau mengalokasikan ruang) dalam file header.
    4. Setiap file sumber harus merujuk kepada orang-file header yang dibutuhkan dengan #include line.
    5. Tidak pernah #include sebuah .c berkas.
  12. Bila Anda memiliki beberapa file sumber, Anda perlu menghubungkan bersama-sama semua file objek dikompilasi bersama dengan perpustakaan yang membutuhkan program Anda.
    1. Cara termudah adalah dengan menggunakan C compiler, yang tahu tentang perpustakaan C:

      gcc * .o -o myprogram

      Perintah ini meminta compiler untuk menghubungkan semua file objek dengan library C (yang secara implisit termasuk) dan menempatkan hasil dalam file myprogram , yang menjadi executable.
    2. Jika program Anda membutuhkan perpustakaan lain, Anda harus menentukan mereka setelah file objek, karena linker hanya mengumpulkan rutinitas dari perpustakaan yang sudah tahu itu membutuhkan, dan link file dalam urutan yang Anda tentukan. Jadi jika Anda perlu perpustakaan seperti libxml2 , perintah menghubungkan Anda harus sesuatu seperti ini:

      gcc * .o -lxml2 -o myprogram

      Compiler tahu bagaimana untuk mencari berbagai direktori standar untuk versi saat libxml2 .
  13. Debugging program C
    1. Jika Anda mendapatkan kesalahan segmentasi, Anda kemungkinan besar memiliki indeks di luar jangkauan, sebuah pointer diinisiasi, atau null pointer.
    2. Anda dapat menempatkan laporan cetak dalam program Anda untuk membantu Anda melokalisasi kesalahan.
    3. Debugging cenderung paling sukses jika Anda menggunakan gdb (dijelaskan di bawah ) untuk mencari tahu di mana kesalahan Anda.
    4. Program yang dijalankan untuk waktu yang lama harus berhati-hati untuk membebaskan semua memori mereka mengalokasikan, atau akhirnya mereka kehabisan memori. Untuk kebocoran memori debug anda mungkin mempertimbangkan artikel ini pada debugging kebocoran C memori dan C ++ kebocoran memori .

Unix

  1. Dengan konvensi, setiap proses dimulai dengan tiga file standar terbuka: standar input, output standar, dan standard error, yang terkait dengan file deskriptor 0, 1, dan 2.
    1. input standar biasanya terhubung ke keyboard Anda. Apa pun yang Anda ketik masuk ke program.
    2. output standar biasanya dihubungkan ke layar Anda. Apapun program output menjadi terlihat.
    3. Standard error juga biasanya dihubungkan ke layar Anda.
    4. Anda dapat menggunakan shell untuk memohon program sehingga output standar satu program secara langsung terkait ( "pipa") ke standar input dari program lain:

      ls | toilet

    5. Anda dapat menggunakan shell untuk memohon agar program standard input dan / atau output dihubungkan ke file:

      ls> lsOutFile
      wc semacam u sortedFile

    6. Secara umum, program tidak tahu atau peduli apakah shell telah diatur ulang arti dari file standar mereka.
  2. Perintah Unix
    1. Perintah hanya nama-nama file executable. The PATH variabel lingkungan memberitahu shell di mana untuk mencari mereka. Biasanya, variabel ini memiliki nilai seperti / bin: / usr / bin: / usr / local / bin :. .
    2. Untuk melihat di mana shell menemukan program tertentu, misalnya, vim , mengatakan di mana vim .
  3. Sistem panggilan dan panggilan perpustakaan mengikuti beberapa konvensi penting.
    1. Nilai kembali dari panggilan biasanya menunjukkan apakah panggilan berhasil (biasanya nilai adalah 0 atau positif) atau gagal (biasanya nilai -1).
    2. Selalu memeriksa nilai kembali dari panggilan perpustakaan. Ketika sistem panggilan gagal, perror () fungsi dapat mencetak apa kesalahan itu (untuk standard error):

      int fd;
      char * filename = "myfile";
      if ((fd = open (filename, O_RDONLY)) <0) {
      perror (nama file); // Mungkin mencetak "myfile: Tidak ada berkas atau direktori"
      }

    3. Sebuah halaman buku panduan untuk panggilan sistem atau perpustakaan rutin mungkin daftar tipe data yang tidak mendefinisikan, seperti size_t atau time_t atau O_RDONLY . Jenis ini biasanya didefinisikan dalam file header yang disebutkan dalam halaman manual; Anda perlu menyertakan semua file header dalam program C Anda.
  4. Hak akses file di Unix biasanya dinyatakan dengan angka oktal.
    1. Dalam contoh creat () di atas, 0.660 adalah angka oktal (itulah yang 0 berarti terkemuka), yang mewakili biner 110.110.000. Ini hibah nomor oktal membaca dan menulis perizinan, tetapi tidak melaksanakan hak akses, pemilik file dan grup file, tetapi tidak ada izin untuk pengguna lain.
    2. Anda mengatur hak akses ketika Anda membuat file dengan parameter untuk creat () panggilan.
    3. Perintah ls-l menunjukkan izin dari file.
    4. Anda dapat mengubah hak akses dari file yang sudah menggunakan chmod Program.
    5. Semua proses Anda memiliki disebut umask karakteristik, biasanya direpresentasikan sebagai bilangan oktal. Ketika sebuah proses menciptakan sebuah file, bit dalam umask tersebut dihapus dari izin yang ditentukan dalam creat () panggilan. Jadi jika umask Anda adalah 066, maka orang lain tidak bisa membaca atau menulis file yang Anda buat, karena 066 mewakili hak akses baca dan tulis untuk grup Anda dan untuk orang lain. Anda dapat memeriksa dan memodifikasi umask Anda dengan menggunakan umask program, yang biasanya Anda menjalankan dalam skrip startup shell Anda (tergantung pada shell Anda, ~ / .login atau ~ / .profile ).

 

Perangkat lunak pengembangan

  1. Gunakan editor teks untuk membuat, memodifikasi, dan memeriksa program anda. Ada beberapa wajar teks editor yang tersedia.
    1. The vim Editor dan antarmuka grafis, gvim , mengambil beberapa upaya untuk belajar, tetapi mereka memberikan kualitas yang sangat tinggi set alat untuk file program editing, termasuk sintaks, kurung yang cocok, kata selesai, lekukan otomatis, mencari oleh tag (yang bergerak Anda dengan cepat dari tempat di mana program memanggil fungsi ke tempat di mana fungsi didefinisikan), dan pencarian manual-halaman yang terintegrasi. Vim dirancang untuk digunakan Keyboard; Anda tidak pernah perlu menggunakan mouse jika Anda tidak ingin. Hal ini secara bebas tersedia untuk sistem operasi Unix, Win32, dan Microsoft. Ini adalah versi yang paling sangat berkembang dari seri editor yang meliputi ed , mantan , vi , dan elvis . Anda dapat membaca dokumentasi online untuk vim dan mendapatkan bantuan segera melalui vim 's : membantu perintah.
    2. The emacs editor, jika ada, lebih fitur-sarat dari vim . Ini juga membutuhkan upaya yang signifikan untuk belajar. Hal ini juga secara bebas tersedia untuk sistem operasi kedua Unix dan Microsoft. Anda dapat menemukan dokumentasi di sini .
    3. Ada banyak editor teks lain yang tersedia, tetapi umumnya mereka tidak memberikan dua fitur yang paling berguna yang Anda butuhkan untuk membuat program-program: lekukan otomatis dan sintaks. Namun, editor teks ini sering memiliki keuntungan menjadi lebih mudah untuk belajar, sesuai dengan kemampuan mereka yang terbatas. Di antaranya berkualitas rendah editor teks (untuk Unix) pico , gedit , dan joe dan (untuk Microsoft) notepad dan kata .
    4. Anda mungkin akrab dengan lingkungan pengembangan terpadu (IDE) seperti Eclipse, Kode Warrior, atau NET. lingkungan ini umumnya memiliki editor teks yang terintegrasi dengan debugger dan kompiler. Jika Anda menggunakan IDE seperti itu, masuk akal untuk menggunakan editor teks terkait.
  2. gdb adalah debugger yang memahami variabel dan struktur program.
    1. Anda dapat menemukan dokumentasi di sini .
    2. Untuk menggunakan gdb efektif, Anda harus lulus g bendera ke C atau C ++ compiler.
    3. Jika program Anda myprogram telah gagal meninggalkan sebuah file yang bernama inti , kemudian mencoba gdb myprogram inti .
    4. Anda juga dapat menjalankan program Anda dari awal di bawah kendali gdb : myprogram gdb .
    5. Semua perintah untuk gdb dapat disingkat awalan yang unik.
    6. The bantuan perintah ini sangat berguna.
    7. The mana perintah menunjukkan panggilan stack, termasuk nomor baris yang menunjukkan di mana setiap rutin. Ini adalah perintah pertama Anda harus mencoba ketika Anda debug file inti.
    8. Untuk mencetak nilai dari beberapa ekspresi (Anda mungkin termasuk variabel dan operator C biasa), jenis cetak ekspresi , seperti di

      print (Myint + 59) & 0444;

    9. Untuk melihat program Anda, coba daftar myFunction atau daftar myFile.c: 38 .
    10. Untuk rekor aktivasi yang berbeda lancar, gunakan up (untuk yang lebih baru) atau turun (kurang baru) perintah.
    11. Anda dapat mengatur breakpoint pada setiap baris file apapun. Misalnya, Anda dapat mengatakan istirahat foo.p: 38 untuk mengatur breakpoint pada baris 38 dalam file foo.p . Setiap kali program Anda hits baris yang sementara itu dijalankan, itu akan berhenti dan gdb akan meminta Anda untuk perintah. Anda dapat melihat variabel, misalnya, atau melangkah maju melalui program ini.
    12. The berikutnya perintah langkah maju satu pernyataan (memanggil dan kembali dari prosedur apapun jika diperlukan).
    13. The Langkah perintah langkah maju satu pernyataan, tetapi jika pernyataan itu melibatkan panggilan prosedur, itu langkah ke prosedur dan berhenti pada pernyataan pertama di sana.
    14. Jika Anda memasukkan perintah anak set tindak garpu-mode , maka ketika program Anda mengeksekusi fork () panggilan, gdb akan terus debug anak, bukan orang tua.
    15. Tinggalkan gdb dengan memasukkan berhenti perintah.
    16. Anda mungkin lebih memilih untuk menggunakan ddd grafis front end untuk gdb .
  3. Selalu memberikan compiler program gcc atau g ++ yang Wall bendera untuk mengaktifkan tingkat tinggi peringatan. Demikian pula memberikan javac yang -Xlint: semua bendera. Jangan berubah dalam program yang menghasilkan peringatan apapun saat kompilasi.
  4. Anda dapat membaca petunjuk untuk mendapatkan rincian tentang program, library C, dan panggilan sistem Unix dengan menggunakan manusia Program, seperti pada manusia printf atauman gcc .
    1. Kadang-kadang fungsi yang ingin terletak di bagian tertentu dari manual Unix dan Anda secara eksplisit harus meminta itu: man 2 terbuka atau man 3 printf . Bagian 1 meliputi program, bagian 2 meliputi panggilan sistem, dan bagian 3 meliputi C library, dan bagian 8 meliputi administrasi sistem. Anda kemungkinan besar tidak perlu bagian lain.
    2. Anda dapat menemukan jika program apapun, C library rutin, atau Unix system call relevan dengan beberapa subjek dengan menggunakan -k bendera, seperti dalam cetak man -k .
  5. Gunakan make program untuk mengatur resep untuk mengkompilasi ulang dan relinking program Anda ketika Anda mengubah file sumber.
    1. Lihat tutorial ini atau manual ini untuk rincian.
    2. Jika program Anda terdiri dari beberapa file, Anda dapat mengkompilasi mereka secara terpisah dan kemudian menghubungkan mereka bersama-sama. Anda mengkompilasi dengan bendera -c , dan menggunakan -o bendera untuk menunjukkan file output. Sebuah wajar makefile mungkin terlihat seperti ini:

      SUMBER = driver.c input.c output.c
      BENDA = driver.o input.o output.o
      HEADERS = common.h
      CFLAGS = -g Wall 

      Program: $ (BENDA)
      $ (CC) $ (CFLAGS) $ (BENDA ) -o Program 

      $ (BENDA): $ (HEADERS) 

      testRun: Program
      Program Ini makefile menggunakan built-in definisi CC dan built-in aturan untuk mengkonversi file sumber C seperti driver.c ke dalam file objek mereka. Jika Anda mengubah hanya input.c , kemudian membuat testRun akan menyebabkan compiler untuk membangun kembali input.o , maka menyebabkan compiler untuk relink benda, menciptakan Program , dan kemudian jalankan program yang dengan input standar diarahkan dari file testdata .

    3. Jika Anda memiliki banyak file sumber dan banyak file header, Anda mungkin ingin menggunakan makedepend program untuk secara otomatis membangun Makefile aturan yang menentukan bagaimana file sumber tergantung pada file header. Contoh di atas mengasumsikan bahwa semua file sumber tergantung pada semua file header, yang sering tidak terjadi.
  6. The grep Program dapat dengan cepat mencari untuk definisi atau variabel, terutama dalam menyertakan file:

    grep "struct timeval {" /usr/include/*/*.h

latihan

Lakukan latihan ini di C.

  1. Menulis sebuah program yang disebut atoi yang membuka file data bernama pada baris perintah dan membaca dari itu garis input tunggal, yang harus berisi integer diwakili dalam karakter ASCII.Program ini mengkonversi string yang ke integer, mengalikan bilangan bulat dengan 3, dan mencetak hasil untuk keluar standar. Program ini tidak harus menggunakan atoi () fungsi. Anda harus menggunakan make Program. Anda Makefile harus memiliki tiga aturan: atoi , jalankan (yang menjalankan program Anda pada data uji standar Anda dan mengarahkan output ke file baru), dan bersih (yang menghilangkan file-file sementara). Pastikan program Anda berjalan dengan benar pada data yang buruk dan keluar dengan pesan membantu jika file data yang hilang atau tidak terbaca. Langkah melalui program anda dengan memulai dengan gdb , menempatkan breakpoint pada main () , dan menggunakan langkah perintah berulang kali.
  2. Mencari halaman manual untuk kucing Program. Kode versi Anda sendiri kucing . Versi Anda harus menerima beberapa (atau tidak) parameter berkas-nama. Ini tidak perlu menerima parameter pilihan.
  3. Menulis sebuah program removeSuffix yang mengambil satu parameter: nama file akhiran. The akhiran file memiliki satu baris per entri. Sebuah entri adalah string non-kosong, yang kita sebutakhiran , diikuti oleh> tanda, diikuti oleh tali (mungkin kosong), yang kita sebut pengganti . Program Anda harus menyimpan semua akhiran dan pengganti mereka dalam tabel hash. Gunakan chaining eksternal. Program Anda kemudian harus membaca masukan standar. Untuk setiap kata dipisahkan oleh spasi w di input, menemukan akhiran terpanjang s yang muncul di w , dan memodifikasi w oleh stripping off s dan memasukkan s 'pengganti s, menciptakan w' . Output satu baris per kata dimodifikasi, dalam bentuk w> w ' . Tidak output setiap kata yang tidak dimodifikasi.