2017-03-19 2 views
0

Ich schrieb ein Programm in C, das als Eingabe einen Wert und ein geordnetes Array von ganzen Zahlen nimmt und eine ternäre Suche durchführt, um den Wert (wenn es existiert) innerhalb des Arrays zu finden.Doppelte Verwendung von scanf() hängt von Aufrufreihenfolge ab

Ich habe alle möglichen Probleme mit der Verwendung von scanf und den verwandten Themen hier in Stackoverflow gesehen.

Ich habe festgestellt, dass es einen Unterschied gibt, wenn ich die 2 scanf Funktionen in umgekehrter Reihenfolge aufrufen.

Wenn ich den Code verwenden, wie es unten ist. Lesen Sie zuerst den Wert und nach dem Array vom Benutzer funktioniert das Programm und scanf wie erwartet.

printf("Enter the value to be searched in the Array: "); 
int k; 
scanf(" %d", &k); 

printf("Type elements of A(sorted) separated by spaces (type 'end' to stop): "); 

i = 0; 
while(scanf("%d", &A[i]) == 1) { 
    i++; 
}//while 

Obwohl, wenn ich die scanf Eingänge in umgekehrter Reihenfolge verwenden die zweite Scanf hört nie auf Benutzereingaben zu erhalten und Werte links in den Puffer eingelesen.

Ich kann nicht verstehen, was ist der Unterschied in der Reihenfolge aufrufen. Ich habe die in den anderen Threads genannten Lösungen ausprobiert, aber keine funktionierte.

nur als Referenz hier ist der gesamte Code (wie erwartet):

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


int ternarySearch(int A[], int l, int r, int k){ 
int i; 
int first,second; 

if(l>r){ 
    return -1; 
} 

i= (r - l)/3; 

if(i==0){ 
    i++; 
} 

first = i+l-1; 
second = i*2+l-1; 

if(A[first]==k){ 
    return first; 
} 
else if(A[first]>k){ 
    ternarySearch(A, l, first-1, k); 
} 
else 
{ 
    if(A[second]==k) 
     return second; 
    else 
    if(A[second]>k) 
     ternarySearch(A, first+1,second-1, k); 
    else 
     ternarySearch(A, second+1,r, k); 
} 
} 


int main(){ 
const int maxarraylen = 1000; 
int i; 
int n; 
int A[maxarraylen]; 
char string[250]; 

printf("Enter the value to be searched in the Array: "); 
int k; 
scanf(" %d", &k); 

printf("Type elements of A(sorted) separated by spaces (type 'end' to stop): "); 

i = 0; 
while(scanf("%d", &A[i]) == 1) { 
    i++; 
}//while 
n=i-1; 


//We assume the array is sorted otherwise we can use any sorting algorithm e.g. code from task1 

scanf(" %d", &k); 






int result; 
result=ternarySearch(A, 0, n, k); 

if(result==-1){ 
    printf("The value was not found in the Array.\n"); 
} 
else{ 
    printf("The value was found in position no. %d.\n", result); 
} 

return 0; 
} 
+0

Sie sollten Ihren Code einrücken und die Verwendung von anständigen Variablennamen machen Verständnis zu unterstützen. – Attie

+0

Vollständiger Code wird nur als Referenz verwendet, wenn jemand das Programm ausführen möchte. Die einzigen zwei wichtigen Zeilen, die für die Frage relevant sind, sind "scanf" ("% d", &k); 'und" scanf "("% d ", & A [i]) == 1 '. Eine liest nur eine Integer-Variable und die andere liest mehrere Indeger von der Kommandozeile –

+0

So scanf entfernt die Wagenrücklauf '\ r' und/oder neue Zeile Zeichen '\ n'? Ist das der eine Weg funktioniert aber der andere nicht? Können Sie bitte erklären, wie **% * s ** funktioniert? –

Antwort

1

Ihr Problem ist, dass Sie nicht ‚Schritt über‘ Ihre end Eingang.

Wir können sehen, durch ein Experiment mit dem folgenden Programm zu tun:

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

void main(void) { 
    FILE *f; 
    long f_pos; 
    int ret; 
    int i; 
    int data[5]; 
    int data_last; 
    int search; 

    f = fopen("./input.txt", "r"); 
    if (f == NULL) { 
     perror("fopen()"); 
     return; 
    } 

    /* read in the values for the array */ 
    data_last = -1; 
    for (i = 0; i < 5; i++) { 
     ret = fscanf(f, "%d", &(data[i])); 
     printf("fscanf(data[%d]): ret: %d\n", i, ret); 
     f_pos = ftell(f); 
     printf("ftell(): %ld\n", f_pos); 
     if (ret != 1) { 
      break; 
     } 
     data_last = i; 
    } 

    /* check that we read in at least one value */ 
    if (data_last == -1) { 
     printf("no input data!\n"); 
     return; 
    } 

    /* insert 'fix' here */ 

    /* pre-load the 'search' with known garbage */ 
    search = 987; 

    /* now read in the search value */ 
    ret = fscanf(f, "%d", &search); 
    printf("fscanf(search): ret: %d\n", ret); 
    f_pos = ftell(f); 
    printf("ftell(): %ld\n", f_pos); 

    /* print out our info */ 
    for (i = 0; i <= data_last; i++) { 
     printf("data[%d]: %d\n", i, data[i]); 
    } 
    printf("search for: %d\n", search); 

    return; 
} 

Mit den folgenden Daten in input.txt:

123 
456 
end 
456 

Der Ausgang ist wie folgt:

fscanf(data[0]): ret: 1 
ftell(): 3 
fscanf(data[1]): ret: 1 
ftell(): 7 
fscanf(data[2]): ret: 0 
ftell(): 8 
fscanf(search): ret: 0 
ftell(): 8 
data[0]: 123 
data[1]: 456 
search for: 987 

ftell() sagt uns, wo der Cursor der Datei ist, und in diesem Fall können wir sehen Sie, dass es bei Byte 8 ist ... e der Eingangsleitung end.

Es geht nicht darüber hinaus, und so wird der nächste Versuch, eine Zahl (%d) zu lesen, auch fehlschlagen!

Es ist auch eine gute Idee, die Rückgabewerte zu überprüfen! Wir können sehen, dass der fscanf(&search) Aufruf eine Zahl nicht lesen konnte!


Die Lösung ist diese Schnipsel einfügen kurz nachdem wir prüfen, ob wir Array-Werte empfangen:

/* this is the 'fix' */ 
ret = fscanf(f, "end"); 
printf("fscanf(end): ret: %d\n", ret); 
f_pos = ftell(f); 
printf("ftell(): %ld\n", f_pos); 
+0

Vielen Dank für die sehr detaillierte und informative Antwort! –

Verwandte Themen