Çözüldü C/C++ Dilinde int değerine bir harf yazılırsa hata yazma

Bu konu çözüldü olarak işaretlenmiştir. Çözülmediğini düşünüyorsanız konuyu rapor edebilirsiniz.

CezzoN

Hectopat
Katılım
17 Ekim 2021
Mesajlar
18
Daha fazla  
Cinsiyet
Erkek
Arkadaşlar bu sorunu aşamıyorum. Size şöyle anlatayım;

Mesela benden bir sayı girmemi istiyor. Fakat ben sayı girdiğim zaman bir sıkıntı yok. Fakat ben sayı girilmediği zaman hata almak istiyorum. Örneğin "Bir sayı giriniz" dediği zaman ben harf veya sayı dışında bir şey yazdığımda "Ltfen geçerli bir sayı giriniz" demesini istiyorum. Öyle bir şey yapma imkanım var mı?

Altta örnek bir kod veriyorum.

C:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
/*
    Kullanicidan alinan [0, 100] aralağında 4 ogrenci tam sayi notunun aritmetik ortalamasini bulan kodu yaziniz.
*/

int main(void){
    int sinavNotu;
    int ogrenciSira = 0;
    int toplam = 0;

    printf("*** Sinif not ortalamasi bulma ***");
    while(ogrenciSira < 4){
        printf("\nLutfen bir not giriniz: ");
        scanf("%d", &sinavNotu);
        if(sinavNotu <= 100 && sinavNotu >= 0){
            toplam = toplam + sinavNotu;
            ogrenciSira = ogrenciSira + 1;
            printf("\nSinif not ortalamasi: %f", toplam/(float)ogrenciSira);
        }
        else{
            printf("Gecersiz not girdiniz!\n");
        }
    }
}

Üsteki kodda sadece 0 ile 100 arasında bir sayı girilmediği zaman hata veriyor. Ben bunu harf yazıldığı zaman da "geçersiz not girdiniz" yazısını da yazmasını istiyorum.
 
Çözüm
scanf("%d", &sinavNotu); yerine char sinavNotuRaw[3]; scanf("%3s", &sinavNotuRaw); yaparsin.

C:
int is_integer(const char *number) {
    if (strlen(number) == 0) return 0; 
    for (unsigned int i = 0; number[i] != '\0'; i++) {
        if (number[i] < '0' || number[i] > '9') return 0;
    }
    return 1;
}

Yukaridaki gibi bir kontrol fonksiyonuyla kontrol edersin integer mi girilen deger diye. Sonra atoi yada sscanf kullan integer'a donustur validate ettikten sonra.

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

int is_integer(const char *number) {
    if (strlen(number) == 0) return 0;
    for (unsigned int i = 0; number[i] != '\0'; i++) {
        if (number[i] < '0' || number[i] > '9') return 0;
    }
    return 1;
}

int main(void) {
    int sinavNotu, ogrenciSira = 0, toplam = 0;
    char sinavNotuRaw[10];

    printf("*** Sinif not ortalamasi bulma ***\n");

    while (ogrenciSira < 4) {
        printf("Lutfen bir not giriniz: ");
        // burada scanf yerine fgets kullanmamin sebebi daha guvenli olmasi. buffer overflowun onune gecmek icin yani ref: https://cplusplus.com/reference/cstdio/fgets/
        if (!fgets(sinavNotuRaw, sizeof(sinavNotuRaw), stdin)) {
            printf("\nGecersiz giris!\n");
            continue;
        }
        // strcspn sagdaki stringin ilk ornegine kadar olan boyutu dondurur. 
        // \n gelecek fgets'ten eger boyutun altinda input gelirse kullanici enter bastigindan \n de gelecek.
        // onu aradan cikarip null terminatora ceviriyoruz ki early termination  yapsin (zaten datanin sonu) ref: https://cplusplus.com/reference/cstring/strcspn/
        sinavNotuRaw[strcspn(sinavNotuRaw, "\n")] = 0;
        // burasi asil kisim kontrol ettigimizde integer olmayan bir sey geldiyse devam ediyoruz ta ki integer gelene kadar.
        if (!is_integer(sinavNotuRaw)) {
            printf("\nLutfen sadece 0 ile 100 arasinda bir sayi giriniz\n");
            continue;
        }
        // strtol kullanarak integera donusturdum. ref: https://cplusplus.com/reference/cstdlib/strtol/
        sinavNotu = strtol(sinavNotuRaw, NULL, 10);

        if (sinavNotu >= 0 && sinavNotu <= 100) {
            toplam += sinavNotu;
            ogrenciSira++;
            printf("Sinif not ortalamasi: %.2f\n", toplam / (float)ogrenciSira);
        } else {
            printf("Gecersiz not girdiniz!\n");
        }
    }
}
scanf("%d", &sinavNotu); yerine char sinavNotuRaw[3]; scanf("%3s", &sinavNotuRaw); yaparsin.

C:
int is_integer(const char *number) {
    if (strlen(number) == 0) return 0; 
    for (unsigned int i = 0; number[i] != '\0'; i++) {
        if (number[i] < '0' || number[i] > '9') return 0;
    }
    return 1;
}

Yukaridaki gibi bir kontrol fonksiyonuyla kontrol edersin integer mi girilen deger diye. Sonra atoi yada sscanf kullan integer'a donustur validate ettikten sonra.

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

int is_integer(const char *number) {
    if (strlen(number) == 0) return 0;
    for (unsigned int i = 0; number[i] != '\0'; i++) {
        if (number[i] < '0' || number[i] > '9') return 0;
    }
    return 1;
}

int main(void) {
    int sinavNotu, ogrenciSira = 0, toplam = 0;
    char sinavNotuRaw[10];

    printf("*** Sinif not ortalamasi bulma ***\n");

    while (ogrenciSira < 4) {
        printf("Lutfen bir not giriniz: ");
        // burada scanf yerine fgets kullanmamin sebebi daha guvenli olmasi. buffer overflowun onune gecmek icin yani ref: https://cplusplus.com/reference/cstdio/fgets/
        if (!fgets(sinavNotuRaw, sizeof(sinavNotuRaw), stdin)) {
            printf("\nGecersiz giris!\n");
            continue;
        }
        // strcspn sagdaki stringin ilk ornegine kadar olan boyutu dondurur. 
        // \n gelecek fgets'ten eger boyutun altinda input gelirse kullanici enter bastigindan \n de gelecek.
        // onu aradan cikarip null terminatora ceviriyoruz ki early termination  yapsin (zaten datanin sonu) ref: https://cplusplus.com/reference/cstring/strcspn/
        sinavNotuRaw[strcspn(sinavNotuRaw, "\n")] = 0;
        // burasi asil kisim kontrol ettigimizde integer olmayan bir sey geldiyse devam ediyoruz ta ki integer gelene kadar.
        if (!is_integer(sinavNotuRaw)) {
            printf("\nLutfen sadece 0 ile 100 arasinda bir sayi giriniz\n");
            continue;
        }
        // strtol kullanarak integera donusturdum. ref: https://cplusplus.com/reference/cstdlib/strtol/
        sinavNotu = strtol(sinavNotuRaw, NULL, 10);

        if (sinavNotu >= 0 && sinavNotu <= 100) {
            toplam += sinavNotu;
            ogrenciSira++;
            printf("Sinif not ortalamasi: %.2f\n", toplam / (float)ogrenciSira);
        } else {
            printf("Gecersiz not girdiniz!\n");
        }
    }
}
 
Çözüm
Kodu denedim. Gayet de iyi çalıştı. Fakat sınırları test ederken 1000000000'dan büyük bir değer yazdığım zaman kod hem hata veriyor hem de değer satırına girip ortalamayı 0.00 olarak gösteriyor. Bunun sebebi nedir? Sadece öğrenmek istiyorum.
scanf("%d", &sinavNotu); yerine char sinavNotuRaw[3]; scanf("%3s", &sinavNotuRaw); yaparsin.

C:
int is_integer(const char *number) {
    if (strlen(number) == 0) return 0;
    for (unsigned int i = 0; number[i] != '\0'; i++) {
        if (number[i] < '0' || number[i] > '9') return 0;
    }
    return 1;
}

Yukaridaki gibi bir kontrol fonksiyonuyla kontrol edersin integer mi girilen deger diye. Sonra atoi yada sscanf kullan integer'a donustur validate ettikten sonra.

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

int is_integer(const char *number) {
    if (strlen(number) == 0) return 0;
    for (unsigned int i = 0; number[i] != '\0'; i++) {
        if (number[i] < '0' || number[i] > '9') return 0;
    }
    return 1;
}

int main(void) {
    int sinavNotu, ogrenciSira = 0, toplam = 0;
    char sinavNotuRaw[10];

    printf("*** Sinif not ortalamasi bulma ***\n");

    while (ogrenciSira < 4) {
        printf("Lutfen bir not giriniz: ");
        // burada scanf yerine fgets kullanmamin sebebi daha guvenli olmasi. buffer overflowun onune gecmek icin yani ref: https://cplusplus.com/reference/cstdio/fgets/
        if (!fgets(sinavNotuRaw, sizeof(sinavNotuRaw), stdin)) {
            printf("\nGecersiz giris!\n");
            continue;
        }
        // strcspn sagdaki stringin ilk ornegine kadar olan boyutu dondurur.
        // \n gelecek fgets'ten eger boyutun altinda input gelirse kullanici enter bastigindan \n de gelecek.
        // onu aradan cikarip null terminatora ceviriyoruz ki early termination  yapsin (zaten datanin sonu) ref: https://cplusplus.com/reference/cstring/strcspn/
        sinavNotuRaw[strcspn(sinavNotuRaw, "\n")] = 0;
        // burasi asil kisim kontrol ettigimizde integer olmayan bir sey geldiyse devam ediyoruz ta ki integer gelene kadar.
        if (!is_integer(sinavNotuRaw)) {
            printf("\nLutfen sadece 0 ile 100 arasinda bir sayi giriniz\n");
            continue;
        }
        // strtol kullanarak integera donusturdum. ref: https://cplusplus.com/reference/cstdlib/strtol/
        sinavNotu = strtol(sinavNotuRaw, NULL, 10);

        if (sinavNotu >= 0 && sinavNotu <= 100) {
            toplam += sinavNotu;
            ogrenciSira++;
            printf("Sinif not ortalamasi: %.2f\n", toplam / (float)ogrenciSira);
        } else {
            printf("Gecersiz not girdiniz!\n");
        }
    }
}
 

Dosya Ekleri

  • Ekran görüntüsü 2025-02-20 114642.png
    Ekran görüntüsü 2025-02-20 114642.png
    5,8 KB · Görüntüleme: 28
Verdigim bufferin boyu 10 karakter. fgets'de 10 karakter bekliyor.

10 karakterden fazla verdiginde, (atiyorum 15 karakter verdin), sadece ilk 10 karakteri alir, isleme sokar, sonrasinda ikinci sefer fgets geldiginde bu sefer bufferda kalan 5 karakteri okur ardindan onlari isleme sokar. Bunu buffer bosalana kadar yapar. Bunun onune gecmek icin input aldiktan sonra stdin bufferini bosaltabilirsin.

Basit bir flush fonksiyonu yazabilirsin soyle;
C:
void flush() {
    int c;
    while ((c = getchar()) != '\n' && c != EOF);
}
Yukaridaki kod \n yada EOF gorene kadar getchar() yaparak bufferi tuketecek.
fgets olan kismi soyle duzenlersen;
C:
if (!fgets(sinavNotuRaw, sizeof(sinavNotuRaw), stdin)) {
    printf("\nGecersiz giris!\n");
    continue;
}
if (sinavNotuRaw[strlen(sinavNotuRaw) - 1] != '\n') flush();
Eger kullanici fazla karakter girerse beklenenden hepsini tuketmis olacak.
 
Çok teşekkür ederim. Daha öğrenecek çok şeyim var.😄
Verdigim bufferin boyu 10 karakter. fgets'de 10 karakter bekliyor.

10 karakterden fazla verdiginde, (atiyorum 15 karakter verdin), sadece ilk 10 karakteri alir, isleme sokar, sonrasinda ikinci sefer fgets geldiginde bu sefer bufferda kalan 5 karakteri okur ardindan onlari isleme sokar. Bunu buffer bosalana kadar yapar. Bunun onune gecmek icin input aldiktan sonra stdin bufferini bosaltabilirsin.

Basit bir flush fonksiyonu yazabilirsin soyle;
C:
void flush() {
    int c;
    while ((c = getchar()) != '\n' && c != EOF);
}
Yukaridaki kod \n yada EOF gorene kadar getchar() yaparak bufferi tuketecek.
fgets olan kismi soyle duzenlersen;
C:
if (!fgets(sinavNotuRaw, sizeof(sinavNotuRaw), stdin)) {
    printf("\nGecersiz giris!\n");
    continue;
}
if (sinavNotuRaw[strlen(sinavNotuRaw) - 1] != '\n') flush();
Eger kullanici fazla karakter girerse beklenenden hepsini tuketmis olacak.
 

Technopat Haberler

Geri
Yukarı