Menggunakan kode berikut:
char *name = malloc(sizeof(char) + 256);
printf("What is your name? ");
scanf("%s", name);
printf("Hello %s. Nice to meet you.\n", name);
Seorang pengguna dapat memasukkan nama mereka tetapi ketika mereka memasukkan nama dengan spasi seperti Lucas Aardvark
, scanf()
potong saja semuanya Lucas
. Bagaimana cara saya membuat scanf()
ruang kosong
sizeof(char) + 256
kesalahan ketik.Jawaban:
Orang (dan terutama pemula) tidak boleh menggunakan
scanf("%s")
ataugets()
atau fungsi lain yang tidak memiliki perlindungan buffer overflow, kecuali Anda tahu pasti bahwa input akan selalu dari format tertentu (dan mungkin bahkan tidak kemudian).Ingat daripada
scanf
singkatan "scan diformat" dan ada yang berharga sedikit kurang diformat daripada data yang dimasukkan pengguna. Ini ideal jika Anda memiliki kontrol total format data input tetapi umumnya tidak cocok untuk input pengguna.Gunakan
fgets()
(yang memiliki perlindungan buffer overflow) untuk memasukkan input Anda ke string dansscanf()
untuk mengevaluasinya. Karena Anda hanya ingin apa yang dimasukkan pengguna tanpa penguraian, Anda sebenarnya tidak perlusscanf()
dalam hal ini:sumber
fgets()
. Ini sebenarnya terlihat lebih mudah digunakanscanf()
. +1scanf
memiliki perilaku undefined jika konversi numerik meluap ( N1570 7.21.6.2p10 , kalimat terakhir, kata-kata tidak berubah sejak C89) yang berarti tidak ada satuscanf
fungsi dapat dengan aman digunakan untuk konversi numerik input tidak dipercaya.scanf
tugas, mereka salah melakukannya, dan Anda dapat memberi tahu mereka bahwa saya mengatakannya, dan jika mereka ingin berdebat dengan saya tentang hal itu , alamat email saya mudah ditemukan dari profil saya.Mencoba
Semoga itu bisa membantu.
sumber
s
dari akhir string input karena itu berlebihan dan salah dalam kasus-kasus tertentu (seperti yang ditunjukkan dalam komentar sebelumnya).[
apakah itu format specifier sendiri daripada beberapa variasi yangs
satu.Contoh ini menggunakan scanset terbalik, jadi scanf terus menerima nilai sampai menemukan '\ n' - baris baru, jadi spasi juga bisa disimpan
sumber
%20[^\n]s
untuk mencegah buffer overflowss
sana!Anda bisa menggunakan ini
Atau ini
DEMO
sumber
scanf("%19[^\n]", name);
(masih +1 untuk jawaban singkat)sizeof(char)
menurut definisi selalu 1, jadi tidak perlu dikalikan dengan itu.Jangan gunakan
scanf()
untuk membaca string tanpa menentukan lebar bidang. Anda juga harus memeriksa nilai kembali untuk kesalahan:Atau, gunakan
fgets()
:sumber
Anda dapat menggunakan
fgets()
fungsi ini untuk membaca string atau menggunakannyascanf("%[^\n]s",name);
agar pembacaan string akan berakhir setelah bertemu dengan karakter baris baru.sumber
s
bukan milik di sanagetline()
Sekarang bagian dari POSIX, tidak ada yang kurang.
Ini juga menangani masalah alokasi buffer yang Anda tanyakan sebelumnya, meskipun Anda harus menjaga
free
memori.sumber
Jika seseorang masih mencari, inilah yang bekerja untuk saya - untuk membaca panjang string acak termasuk spasi.
Terima kasih banyak poster di web untuk berbagi solusi sederhana & elegan ini. Jika berhasil, kredit diberikan kepada mereka tetapi kesalahan ada pada saya.
sumber
errno
dan membersihkan memori yang dialokasikan juga.s
bukan milik di sana setelah scansetAnda dapat menggunakan
scanf
untuk tujuan ini dengan sedikit trik. Sebenarnya, Anda harus mengizinkan input pengguna hingga pengguna menekan Enter (\n
). Ini akan mempertimbangkan setiap karakter, termasuk ruang . Berikut ini contohnya:Bagaimana ini bekerja? Ketika pengguna memasukkan karakter dari input standar, mereka akan disimpan dalam variabel string hingga ruang kosong pertama. Setelah itu, sisa entri akan tetap dalam aliran input, dan menunggu pemindaian berikutnya. Selanjutnya, kami memiliki
for
loop yang mengambil char by char dari input stream (sampai\n
) dan menyarankan mereka untuk mengakhiri string variabel , sehingga membentuk string lengkap sama seperti input pengguna dari keyboard.Semoga ini bisa membantu seseorang!
sumber
Meskipun Anda benar-benar tidak boleh menggunakannya
scanf()
untuk hal semacam ini, karena ada banyak panggilan yang lebih baik sepertigets()
ataugetline()
, hal itu dapat dilakukan:sumber
gets
tidak digunakan lagi dan dihapus ( stackoverflow.com/questions/30890696/why-gets-is-deprecated ) dari standar. Itu bahkan lebih buruk bahwascanf
karena setidaknya yang terakhir memiliki cara untuk membuatnya aman.sumber
s
bukan milik di sana setelah scanset