2016-03-23 19 views
0

Kayıtları korumak için küçük bir menü tabanlı program yazmaya çalışıyorum. Kullanıcı, saklanacak toplam kişi sayısı için kullanılacak bir sayı girer (ad, soyadı, skor). Kullanıcı tek bir satıra tümüyle girer, boşluklarla ayrılır ve onları 3 sütuna (ilk ad, soyadı, skor) bölerim, daha sonra presler girer ve maksimum kişi çarpana kadar daha fazla bilgi girmeye devam eder.scanf ve strtok benim için düzgün çalışmıyor

Sorunum, çalıştırdığımda düzgün çalışmıyor; kullanıcı girdisini çalıştırıyor ve kabul ediyor, ancak sadece iki öğrenci için (test durumları için 5'ten büyük rakamlar kullanmam rağmen), program hemen biter (hata kodları yok, sadece biter ...) hatta menüye getirin. Birisi benim kodumda neyin yanlış olduğunu söyleyebilir mi?

int i, j, count, numberPeople, temp, choice; 
char people[15][3], tempArr[20]; 
char *token; 

printf("Please indicate number of records you want to enter (min 5, max 15): "); 
scanf("%d", &temp); 

while ((temp > 15) || (temp < 5)) { 
    printf("\nNumber not in specified range, try again.\n"); 
    printf("Please indicate number of records you want to enter (min 5, max 15): "); 
    scanf("%d", &temp); 
} 


numberPeople = temp; 


printf("\nEnter the first name, last name, and grade (put a space in between each): "); 
    for (i = 0; i < numberPeople; i++) { 
     fgets(tempArr, 20, stdin); 

    token = strtok(tempArr, " "); 

    for (j = 0; j < 3; j++) { 
     while (token != NULL) { 
      people[i][j] = *token; 
      printf("%s\n", token); // this is here to as a test case to see if my data was being stored. 
      token = strtok(NULL, " "); 
     } 
    } 

} 

EDITED: değişmiş scanf scanf()

Ardından, (j=0; j<3; j++) bölümü için gerekmez değil fgets(),

ÇIKIŞ

Please indicate number of records you want to enter (min 5, max 15): 5 

Enter the first name, last name, and grade (put a space in between each): firstname1 lastname1 85 
firstname1 
lastname1 
85 

firstname2 lastname2 84 
firstname2 
lastname2 

Program ended with exit code: 0 
+0

Neden döngü için iç içe geçmiş bir döngü var? – bruceg

+1

'scanf ("% s ")' bir seferde boşluklarla ayrılmış bir 'sözcük' okur. Bütün bir satırı okumak için 'fgets()' ı kullanın ve sonra 'strtok()' ile ayırın. Bilgisayarın okuduktan hemen sonra ne okuduğunu yazdırarak kendinize yardımcı olabilirsiniz; Bu, hata ayıklamanın en temel şeklidir, ancak yine de son derece değerlidir; size neler olduğunu anlatırdı (2 kullanıcı için 6 kelime girersiniz, böylece ikinci sayı okunmadan önce 5'e kadar döngü yapılır). –

cevap

2

Bir problem ilk isim arasında boşluk, soyadı ve notu vardır tüm giriş satırına okumak için scanf() kullandığınız edilir:

for (i = 0; i < numberPeople; i++) { 
    scanf("%s", tempArr); 
} 

scanf("%s", tempArr) okuma kapanıyor yerine aşağıdaki kullanmak İlk boşluğa ulaştığında.

for (i = 0; i < numberPeople; i++) { 
    fgets(tempArr, 20, stdin); 
} 

Ama @Pooya notlar gibi, bu dize boyutu ne yaptığınızı için çok küçük: Bu döngü için, fgets() kullanmak istiyorum.

char people[15][3] 

Eğer yığın yapıyoruz, bu kavramsal olarak üçüncü bir boyut haline gelir: Eğer öğrenci ve bilgi alanlarının iki boyutlu dizi tahsis rağmen, isimlerini ve notları tutmak için dize alanı tahsis asla:

scanf("%d", &temp); 

muhtemelen temizlenmesi gerekir ou: Bu scanf() sonra

char people[15][3][24] 

hala tampon bırakılan bir dönüş karakteri var t. Burada bir probleme @KevinDTimm ve @bruceg ipucu:

for (j = 0; j < 3; j++) { 
    while (token != NULL) { 
     people[i][j] = *token; 

Ama Kevin'in öneri endeksi j hesapları sanmıyorum. @Weather_Vane strtok() ayırıcı dizeye \r\n eklemenizi öneriyor:

token = strtok(NULL, " ") 

Aksi takdirde notu dize (son alan) bir sarkan yeni satır olacaktır. Ayrıca, strtok() tarafından döndürülen jetonun bir kopyasını oluşturmanız gerekir, doğrudan saklamamalısınız.girişinizi yaklaşık 24 karakter alır ama tempArr[20] tanımlı senin ölçümlere göre

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

#define MINIMUM_STUDENTS 5 
#define MAXIMUM_STUDENTS 15 
#define DATA_FIELDS 3 

#define MAXIMUM_LINE_LENGTH 100 
#define MAXIMUM_DATA_LENGTH 50 

int main(int argc, char **argv) { 

    int numberPeople; 
    char people[MAXIMUM_STUDENTS][DATA_FIELDS][MAXIMUM_DATA_LENGTH]; 

    printf("Please indicate number of records you want to enter (min %d, max %d): ", MINIMUM_STUDENTS, MAXIMUM_STUDENTS); 

    scanf("%d", &numberPeople); 

    while ((numberPeople < MINIMUM_STUDENTS) || (numberPeople > MAXIMUM_STUDENTS)) { 
     printf("\nNumber not in specified range, try again.\n"); 
     printf("Please indicate number of records you want to enter (min %d, max %d): ", MINIMUM_STUDENTS, MAXIMUM_STUDENTS); 
     scanf("%d", &numberPeople); 
    } 

    printf("\n"); 

    while ((getchar()) != '\n'); // flush the return (and anything else) after the number input above 

    printf("Enter the first name, last name, and grade (put a space in between each): \n"); 

    for (int i = 0; i < numberPeople; i++) { 
     char tempArr[MAXIMUM_LINE_LENGTH]; 

     fgets(tempArr, MAXIMUM_LINE_LENGTH, stdin); 

     char *token = strtok(tempArr, " "); 

     for (int j = 0; j < DATA_FIELDS && token != NULL; j++) { 
      strncpy(people[i][j], token, MAXIMUM_DATA_LENGTH); 

      // this is here to as a test case to see if my data was being stored. 
      printf("%s\n", people[i][j]); 

      token = strtok(NULL, " \r\n"); 
     } 

    } 

    // do what you need to do with the data here! 

    return 0; 
} 
+0

Her seferinde scanf() 'dönüş değerini kontrol etmeniz gerektiğini unutmayın ('1' olduğundan emin olun) ve' getchar() 'EOF'de EOF'ye dönecek ve bu bir satırsonu değil, dolayısıyla döngü için çalışabilir çok uzun bir zaman. Kaynak dizgisi hedef dizge için çok uzunsa strncpy() 'nin boş sonlandırmayı garanti etmediğini unutmayın. EOF'yi 'fgets()' 'den tespit etmelisiniz. Kullanıcı sadece 'Fred' '' Fred Bloggs 23''ün nerede bekleniyor diye yazarak endişelenmeli mi? Döngü durur (bu iyidir), ancak verilerin eksik olduğunu bildirmez, bu daha iyi olabilir. Bu çok daha iyi, ama hala iyileştirme için yer var. –

+0

@JonathanLeffler, Her sonucun hatalar için kontrol edilmesi gerektiğine katılıyorum - bunun gibi basit bir program bile detaylara acımasız bir dikkat gerektirir. Amacım aslında koşacak ve ihtiyaç duyduğu belleği tahsis edecek bir şey elde etmekti. (C gibi ciddi bir bellek ayırma hatası yapmanın ve hala çalışmaya yakın gibi görünen bir şey elde etmenin nasıl mümkün olduğunu bana gösteriyor! Sigh.) – cdlane

0

Öncelikle fgets kullanmak, Bu strtok tarafından ele alınmıştır.

token = strtok(tempArr, " "); 
while (token != NULL) { 
    people[i][j] = *token; 
    printf("%s\n", token); // this is here to as a test case to see if my data was being stored. 
    token = strtok(NULL, " "); 
} 
+0

'fgets' kullanılıyorsa, ayırıcı dizesine' \ r \ n' eklenir. –

0

:

hep birlikte bu önerileri koymak ve ben koştu başka bir şey sabitleme/temizlik, aşağıdaki rework sunuyoruz. 20 karakterden daha fazla bir şey tararsanız bellekte başka bir şey üzerine yazdığınızdan, tempArr[100] veya testleriniz için anlamlı olan herhangi bir sayıya sahip olmak daha iyidir.