C 程序输出延后?

lgqfhwy
  • 62

为什么我写的程序会出现输出延后?
输入情况
如图,我是按照左边网页上的输入样例输入的,根据我的程序,输入 8 后就应该出现 ‘here',可直到下一次输入时才出现,而且根据我的程序,输完 A 1 2 后就应该执行

printf("Element = %c, cl = %c, cr = %c\n", T[i].Element, cl, cr);

但是并没有执行。
也就是我的程序中的

 printf("here\n");
        for (i = 0; i < n; i++) {
            printf("i = %d, n = %d\n", i, n);
            scanf("%c %c %c\n", &T[i].Element, &cl, &cr);
            printf("Element = %c, cl = %c, cr = %c\n", T[i].Element, cl, cr);

整个的执行顺序都不一样,为什么会是这样呢?
我的每一次输入输出都会延后一个,这是怎么回事?
而且最后输完 8 个后,还需要多输几个字符才能开始运行程序,这是怎么回事,求大神指教:)

#include <stdio.h>
#include <string.h>
#define MaxTree 10
#define ElementType char
#define Tree int
#define Null -1

struct TreeNode
{
    ElementType Element;
    Tree        Left;
    Tree        Right;
} T1[MaxTree], T2[MaxTree];


Tree BuildTree(struct TreeNode T[]);
int Isomorphic(Tree R1, Tree R2);


int main()
{
    Tree R1, R2;
    R1 = BuildTree(T1);
    R2 = BuildTree(T2);
    printf("hr3\n");
    if (Isomorphic(R1, R2))
        printf("Yes\n");
    else
        printf("No\n");

    return 0;
}

Tree BuildTree(struct TreeNode T[])
{
    printf("hr1\n");
    int n, i;
    scanf("%d\n", &n);
    int check[n];
    char cl, cr;
    int Root = -1;
    if (n) {
        for (i = 0; i < n; i++) {
            check[i] = 0;
        }
        printf("here\n");
        for (i = 0; i < n; i++) {
            printf("i = %d, n = %d\n", i, n);
            scanf("%c %c %c\n", &T[i].Element, &cl, &cr);
            printf("Element = %c, cl = %c, cr = %c\n", T[i].Element, cl, cr);
            if (cl != '-') {
                T[i].Left = cl - '0';
                check[T[i].Left] = 1;
            }
            else
                T[i].Left = Null;
            if (cr != '-') {
                T[i].Right = cr - '0';
                check[T[i].Right] = 1;
            }
            else
                T[i].Right = Null;
        }
        for (i = 0; i < n; i++) {
            if (!check[i])
                break;
        }
        Root = i;
    }
    return Root;
}


int Isomorphic(Tree R1, Tree R2)
{
    printf("hr3\n");
    if ((R1 == Null) && (R2 == Null))
        return 1;
    if (((R1 == Null) && (R2 != Null)) || ((R1 != Null) && (R2 == Null)))
        return 0;
    if (T1[R1].Element != T2[R2].Element)
        return 0;
    if ((T1[R1].Left == Null) && (T2[R2].Left == Null)) {
        //printf("hr3\n");
        return Isomorphic(T1[R1].Right, T2[R2].Right);
    }
    if (((T1[R1].Left != Null) && (T2[R2].Left != Null)) && ((T1[T1[R1].Left].Element) == (T2[T2[R2].Left].Element))) {
        // no need to swap the left and the right
        //printf("hr4\n");
        return (Isomorphic(T1[R1].Left, T2[R2].Left) && Isomorphic(T1[R1].Right, T2[R2].Right));
    }
    else    { //need to swap the left and the right
        //printf("hr5\n");
        return (Isomorphic(T1[R1].Left, T2[R2].Right) && Isomorphic(T1[R1].Right, T2[R2].Left));
    }
}
回复
阅读 2.4k
2 个回答
✓ 已被采纳

这是因为题主在int scanf( const char* format, ... );函数中的格式参数format设置导致的。

Tree BuildTree(struct TreeNode T[])
{
    printf("hr1\n");
    int n, i;
    scanf("%d", &n);  // <-- (1)
    int check[n];
    char cl, cr;
    int Root = -1;
    if (n) {
        for (i = 0; i < n; i++) {
            check[i] = 0;
        }
        printf("here\n");
        for (i = 0; i < n; i++) {
            printf("i = %d, n = %d\n", i, n);
            scanf("%c %c %c\n", &T[i].Element, &cl, &cr);  // <-- (2)
            printf("Element = %c, cl = %c, cr = %c\n", T[i].Element, cl, cr);
            //...

题主可以做几个小测试:

  • (1)处的语句换成scanf("%d", &n);

  • (2)处的语句换成scanf(" %c %c %c\n", &T[i].Element, &cl, &cr);

  • (2)处的语句换成scanf("%c %c %c", &T[i].Element, &cl, &cr);

  • (2)处的语句换成scanf(" %c %c %c", &T[i].Element, &cl, &cr);

具体原因可以参考这里这里关于格式参数format设置的说明,下面引用比较重要的几点:

format: C string that contains a sequence of characters that control how characters extracted from the stream are treated:

  • Whitespace character: the function will read and ignore any whitespace characters encountered before the next non-whitespace character (whitespace characters include spaces, newline and tab characters -- see isspace). A single whitespace in the format string validates any quantity of whitespace characters extracted from the stream (including none).

  • Non-whitespace character, except format specifier (%): Any character that is not either a whitespace character (blank, newline or tab) or part of a format specifier (which begin with a % character) causes the function to read the next character from the stream, compare it to this non-whitespace character and if it matches, it is discarded and the function continues with the next character of format. If the character does not match, the function fails, returning and leaving subsequent characters of the stream unread.

  • Format specifiers: A sequence formed by an initial percentage sign (%) indicates a format specifier, which is used to specify the type and format of the data to be retrieved from the stream and stored into the locations pointed by the additional arguments.

All format specifiers other than [, c, and n consume and discard all leading whitespace characters (determined as if by calling isspace) before attempting to parse the input. These consumed characters do not count towards the specified maximum field width.

Because most conversion specifiers first consume all consecutive whitespace, code such as

std::scanf("%d", &a);
std::scanf("%d", &b);

will read two integers that are entered on different lines (second %d will consume the newline left over by the first) or on the same line, separated by spaces or tabs (second %d will consume the spaces or tabs).

The conversion specifiers that do not consume leading whitespace, such as %c, can be made to do so by using a whitespace character in the format string:

std::scanf("%d", &a);
std::scanf(" %c", &c); // ignore the endline after %d, then read a char

语句确实执行了,不过stdoutstdin有可能被系统缓冲区缓存,导致终端上显示的顺序不对应了。OJ本身一般是用重定向评测的,不受影响。你自己测试的时候也可以把输入放到file.in里,然后./tree < file.in

某些情况下,这样不方便调试,这时可以考虑用fflush()清空缓冲区。在我的系统中试了一下,如果不在printf("hr1\n");后面加fflush(stdout);,甚至程序一开始都不会显示hr1的,直接等待输入了…

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏