scanf() 的双重使用取决于调用顺序

Double usage of scanf() depends on call order

我用 C 编写了一个程序,它将一个值和一个有序的整数数组作为输入,并执行三元搜索以在数组中查找值(如果存在)。

我已经在 Whosebug 中看到了使用 scanf 和相关主题的所有可能问题。

我注意到如果我以相反的顺序调用 2 个 scanf 函数会有所不同。

如果我使用下面的代码。首先从用户读取值和数组后,程序和 scanf 将按预期运行。

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

虽然如果我以相反的顺序使用 scanf 输入,第二个 scanf 永远不会停止获取用户输入并读取缓冲区中剩余的值。

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

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

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

我不明白调用顺序有什么不同。 我尝试了其他线程中提到的解决方案,但 none 有效。

作为参考,这里是整个代码(按预期工作):

#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;
}

你的问题是你不是 'stepping over' 你的 end 输入。

我们可以通过使用以下程序进行实验来了解这一点:

#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;
}

input.txt中有以下数据:

123
456
end
456

输出结果如下:

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() 告诉我们文件的光标在哪里,在本例中我们可以看到它在字节 8...输入行 ende

它没有通过它,因此下一次读取数字 (%d) 的尝试也会失败!

检查 return 值也是个好主意!我们可以看到fscanf(&search)调用读取一个数字失败!


解决方案是在我们检查收到数组值后立即插入此代码段:

/* 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);