Menghasilkan huruf besar tanpa pointer

Saya mencoba menulis fungsi, huruf besar, yang mengubah semua karakter huruf kecil dalam string menjadi huruf besar yang setara.

Namun, saya mendapatkan kesalahan Bus 10 dalam kode saya. Saya tahu bahwa string literal tidak dapat dimodifikasi di C; jadi, saya tidak yakin apakah ini pendekatan yang tepat.

Kode saya di bawah:

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

int uppercase(char source[])
{
 int i;

 for(i=0; i<=strlen(source); ++i)
    if (source[i]>= 'a' && source[i]<= 'z')
        source[i]= source[i]-'a' +'A';
    else 
        source[i]=source[i];
}

int main(){
    uppercase("cold");

    return 0;
}

Idealnya fungsi ini harus mengembalikan COLD. Saya kira kesalahannya terletak pada seluruh pernyataan if saya.


person Rohit Tigga    schedule 21.12.2013    source sumber
comment
Anda telah menjawab pertanyaan Anda sendiri. Dan apa yang Anda maksud dengan pengembalian?   -  person Kerrek SB    schedule 22.12.2013
comment
Dan apa gunanya source[i] = source[i]??   -  person Kerrek SB    schedule 22.12.2013
comment
Maaf, saya seharusnya lebih jelas. Saya tidak tahu cara memperbaiki kesalahan dalam kasus ini. Intinya adalah tidak melakukan perubahan. Saya kira itu berlebihan?   -  person Rohit Tigga    schedule 22.12.2013
comment
Saya kira Anda juga harus menyertakan fungsi/metode huruf besar().   -  person Doro    schedule 22.12.2013
comment
Terima kasih, Chux. Tapi bisakah Anda memberikan penjelasannya?   -  person Rohit Tigga    schedule 22.12.2013
comment
@XiJiaopin Lainnya telah menyediakan dengan baik.   -  person chux - Reinstate Monica    schedule 22.12.2013


Jawaban (2)


Alasan Anda mengalami error adalah karena kode Anda mengubah literal string. Karakter di dalam literal string ditempatkan di area memori yang dilindungi, dan oleh karena itu tidak boleh diubah: ini disebabkan oleh perilaku yang tidak terdefinisi.

Ganti ini

uppercase("cold");

dengan ini:

char cold[] = "cold";
uppercase(cold);

Sekarang karakter string ditempatkan di area memori yang dapat dimodifikasi, memungkinkan Anda membuat perubahan sesuai kebutuhan.

person Sergey Kalinichenko    schedule 21.12.2013
comment
@XiJiaopin: Selamat datang di SO! Status Anda menunjukkan bahwa Anda belum membaca halaman Tentang; tolong lakukan segera. Untuk saat ini, harap baca Seseorang menjawab pertanyaan saya! Apa yang harus dilakukan sekarang?, dan pertimbangkan untuk menerima salah satu jawaban atas pertanyaan Anda. - person Jongware; 22.12.2013

Anda benar-benar bekerja dengan petunjuk tanpa menyadarinya.

Dalam definisi fungsi Anda

int uppercase(char source[])

char source[] dianggap oleh kompiler sebagai penunjuk ke char (char *source)

Jadi ketika meneruskan string literal ke uppercase() Anda hanya meneruskan alamatnya. Kemudian dalam fungsi Anda, Anda mencoba memodifikasinya yang mengarah ke perilaku tidak terdefinisi.

Anda juga tidak dapat mengembalikan seluruh array sehingga Anda hanya mengembalikan sebuah pointer ke sana.

char *uppercase(char source[])
{
     int i;
     size_t len = strlen(source);
     char *tmp;
     tmp = malloc(len+1);
     if (tmp!=NULL){
         memcpy(tmp, source, len+1);
         for(i=0; i<len; ++i){
            if (tmp[i]>= 'a' && tmp[i]<= 'z'){
                tmp[i]= tmp[i]-'a' +'A';
            }
        }
    }
    return tmp;
}

Kemudian:

int main(){
    char *str = uppercase("cold");
    printf("%s", str);
    free(str);

    return 0;
}

Anda melengkapi kode: http://ideone.com/BJHDIF

person rullof    schedule 21.12.2013
comment
Anda perlu mengalokasikan ruang untuk terminator nol dan harus menambahkan free(tmp); di main - person simonc; 22.12.2013
comment
Bukankah strlen menyertakan terminator nol? mengapa harus membebaskan tmp, ini akan menyebabkan hilangnya karena fungsinya mengembalikannya. - person rullof; 22.12.2013
comment
Tidak, strlen tidak termasuk terminator. Anda tidak dapat memanggil free pada pengembalian yang dialokasikan secara dinamis dari uppercase sampai Anda selesai menggunakannya tetapi Anda harus mengosongkannya suatu saat nanti. Saran Anda membocorkan memori ini; bukan masalah besar dalam program kecil ini tetapi saran yang sangat buruk untuk pemrograman secara umum. - person simonc; 22.12.2013
comment
Anda lupa terminator nol :) - person rullof; 22.12.2013
comment
Saya kira tidak - malloc(len+1) mengalokasikan ruang untuk itu dan strcpy menyalinnya. Saya melewatkan bahwa loop menyelesaikan satu karakter lebih awal - sekarang sudah diperbaiki. - person simonc; 22.12.2013
comment
Karena Anda sudah memiliki panjang menggunakan strcpy berlebihan: gunakan memcpy(tmp, source, len + 1) (saya akan menyalin string dalam siklus sebagai gantinya). Tipe pengembalian strlen() adalah size_t, bukan int, sama untuk tipe argumen malloc. Anda juga melakukan len = strlen(tmp); padahal yang Anda maksud adalah source di sini dan bukan tmp. Dan Anda benar-benar harus memeriksa apakah malloc mengembalikan NULL. - person ZyX; 22.12.2013
comment
@ZyX bagaimana cara memeriksa apakah malloc telah mengembalikan NULL dan mengapa memcpy lebih baik daripada strcpy - person rullof; 22.12.2013
comment
@rullof 1.?! Bagaimana cara memeriksa apakah penunjuknya NULL? Gunakan if (tmp == NULL). 2. strcpy beroperasi pada string yang panjangnya tidak diketahui. Yaitu. ia harus beroperasi pada string sedemikian rupa sehingga ia tidak akan mengakses memori setelah NUL byte. memcpy menyalin potongan memori berkelanjutan dengan posisi awal dan panjang tertentu. Ia tidak perlu memeriksa apakah potongan tertentu berisi byte tertentu, juga tidak perlu memproses memori dari posisi tertentu (yaitu awal potongan) dan dalam arah tertentu (yaitu dari awal hingga akhir) yang berarti bahwa lebih banyak optimasi dapat dilakukan dalam implementasi memcpy . - person ZyX; 22.12.2013
comment
Catatan tentang malloc: ia mengembalikan NULL jika tidak ada memori. Dalam hal ini aplikasi Anda mungkin diharapkan untuk mencoba mengosongkan sebagian memori, namun kemungkinan besar hanya mogok karena tidak adanya memori (jika Anda tidak menambahkan pemeriksaan ini, aplikasi akan mogok tanpa pesan yang mudah dipahami karena Anda mencoba menulis ke alamat 0x0 (NULL )). - person ZyX; 22.12.2013
comment
!==? Ini bukan JavaScript. Anda juga dapat menghapus cabang else: jika tmp == NULL sebenarnya tidak ada perbedaan antara return NULL dan return tmp. Dan main() tidak peduli dengan kasus ketika fungsi uppercase() mengembalikan NULL. - person ZyX; 22.12.2013
comment
Uggg ketinggalan lagi. Aku harus bunuh diri - person rullof; 22.12.2013
comment
Hal utama yang saya tidak suka di C adalah terkadang lebih dari separuh kode melakukan penanganan kesalahan. Lebih dari separuh penanganan kesalahan adalah meneruskan kesalahan dari penerima panggilan ke pemanggil. - person ZyX; 22.12.2013