C dilini öğrenmeye çalışıyorum. Aşağıdaki kodlarda input fonksiyonu prompt isimli bir pointer’ı argüman olarak alıyor ve prompt'a yazılan string’i, printf fonksiyonuyla ekrana yazdırabiliyorum.
Ancak scanf fonksiyonuna sadece uzunluğu belli olan bir string verisini argüman olarak verebiliyorum.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void f1(int max, int min, int x, int y){
/*
min’den max’a kadar olan ve
x ile y arasında olmayan sayıları
ekrana yazdıran fonksiyon.
*/
int i;
for(i=min; i < max; i++){
if(x < i && i < y){
continue;
}
printf("%d\n", i);
}
sleep(2);
}
int input(char *prompt){
/*
Python'dakine benzer bir input();
fonksiyonu.
*/
char data[10];
printf("%s", prompt);
scanf("%s", data);
return atoi(data);
}
int main(){
int max = input("Max: ");
int min = input("Min: ");
int x = input("x: ");
int y = input("y: ");
f1(max, min, x, y);
return 0;
}
Konuyu stackoverflow’da araştırırken, bir mesajda stringlerin aşağıda gösterildiği gibi yazılamayacağını okumuştum.
int input(char *prompt){
/*
Python'dakine benzer bir input();
fonksiyonu.
*/
char *data;
printf("%s", prompt);
scanf("%s", data);
return atoi(data);
}
Merak ettiğim şey şu; bir pointer olmasına rağmen, prompt'u, printf'e argüman olarak verdiğimde bir sorun oluşmazken, yine bir pointer olan data'yı scanf'e neden argüman olarak verdiğimde Parçalama arızası (çekirdek döküldü) şeklinde bir hata alıyorum.
Yani, data'yı yalnızca char data[10]; şeklinde yazarak mı scanf'den dönen veriyi tutmasını sağlayabiliriz?
int input(char *prompt){
/*
Python'dakine benzer bir input();
fonksiyonu.
*/
char data[10];
printf("%s", prompt);
gets(data);
return atoi(data);
}
Bahsettiğim şey şununla ilgili:
char data[10], uzunluğu belirtilmiş bir string verisi. char *data ise bir pointer. Ben bu data'yı, tıpkı prompt'u kullandığım gibi kullanamaz mıyım?
Yani aşağıdaki kodlarda prompt bir pointer olmasına rağmen printf fonksiyonuna argüman olarak verdiğimizde, stringin kendisi ekrana yazdırılıyor. Aynı durum neden data için geçerli değil?
int input(char *prompt){
/*
Python'dakine benzer bir input();
fonksiyonu.
*/
char *data;
printf("%s", prompt);
/*scanf("%s", data);*/
gets(data);
return atoi(data);
}
data'yı kullanabilmek için iki yol izleyebiliyorum:
Ya data'yı bir array olarak belirtiyorum:
int input(char *prompt){
/*
Python'dakine benzer bir input();
fonksiyonu.
*/
char data[10];
printf("%s", prompt);
scanf("%s", data);
return atoi(data);
}
Ya da bir _data[10] isminde bir array oluşturuyorum ve onu da *data isimli bir pointer’a atıyorum.
int input(char *prompt){
/*
Python'dakine benzer bir input();
fonksiyonu.
*/
char _data[10];
char *data = _data;
printf("%s", prompt);
scanf("%s", data);
return atoi(data);
}
prompt pointer’ı için herhangi bir array tanımlanmadı ama biz bu pointer’ın string verisini printf ile yazdırabiliyoruz. Aynı durumu data için yapamıyorum, bunun nedenini merak ediyorum.
char *data; olarak tanımladığınızda. data aslında dizini 1. elemanın adresini tutacaktır. Dolayısıyla scanf("%s", data) yazmak ile scanf("%d", &data[0]) yazmak arasında hiç bir fark yoktur. Bu aslında istemediğimiz bir şeydir. Çünkü bir string okumak isterken scanf() kalvyeden gelen veriyi bir char a yazmaya çalısacaktır(data[0]). scanf in stringi okuması için bir char dizisinin pointerini vermek gerekir. Bu da pointerin pointeri olur.
char *data;
scanf("%s", &data);
Ama scanf, sadece EOF, boşuk ve yeni satıra gelinceye kadar klavyeden okuma yapacaktır. gets() klavyeden bir string almak için her zaman iyi bir yoldur.
test.c: In function ‘input’:
test.c:28:10: warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘char **’ [-Wformat=]
scanf("%d", &data);
Yine de çalıştırılabilir dosyayı oluşturuyor fakat rakam girip, enter’a bastıktan sonra aşağıdaki gibi bir hata alıyorum.
test.c: In function ‘input’:
test.c:28:10: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char **’ [-Wformat=]
scanf("%s", &data);
Ve yine enter’a bastıktan sonra aynı hatayı aldım.
Yani benim burada asıl öğrenmek istediğim, prompt da bir pointer fakat biz bu pointer’a string atamadığımız halde, printf("%s", prompt); yazarak prompt argümanını ekrana yazdırabiliyoruz. Aynı durum data için neden geçerli değil?
String uretip maksimum uzunluk almayan hic bir fonksiyonu aslakullanma.
Normal yayin akisimiza donuyoruz:
Hayir. Buradaki sorun ilk data’nin 10’luk bir char array’ine isaret etmesi, ikinci datanin ise hic bir yere isaret etmemesi. Initialize edilmemis deger kullaniyorsun.
Evet ama kullanmamalisin. Manual sayfasindan:
DESCRIPTION
Never use this function.
Hayir, tek pointer (char*) vermek gerekir . scanf(2):
s Matches a sequence of non-white-space characters; the next
pointer must be a pointer to the initial element of a character
array that is long enough to hold the input sequence and the
terminating null byte ('\0'), which is added automatically. The
input string stops at white space or at the maximum field width,
whichever occurs first.
gcc:
a.c:7:13: warning: format ‘%s’ expects argument of type ‘char *’, but
argument 2 has type ‘char **’ [-Wformat=]
scanf("%s", &data);
~^ ~~~~~
(alintilari ekrana sigsin diye formatladim)
Bu arada [] operatorunu makro olarak dusunebilirsin:
x[y] ==> *(x + y)
&data[0]'in data ile ayni olmasinin sebebi bu. &0[data] ile ayni olmasinin sebebi de bu.
Tamam, galiba anlamaya başlıyorum. prompt pointer’ına başka bir fonksiyonda bir değer ataması yapılıyor. Ama data pointer’ına bir değer ataması RunTime esnasında yapılmaya çalışılıyor, o yüzden hata veriyor diye anlıyorum. Yanlış anlıyorsam lütfen düzeltin.