为什么我的C程序在printf之前就停止了?

时间:2014-08-11 19:19:08

标签: c printf

我尝试制作的程序几乎是一个点,因为它围绕屏幕中心移动,好像受重力影响。方法I用作"显示"只是打印一个" "没有任何意义的地方和" X"哪里有一点。在完成我的程序编写并注意到它没有按照我想要的方式工作之后,我开始调试它。完整的计划如下:

#include <stdio.h>
#include <math.h>

double dist (double xpos, double ypos, double xm, double ym);
double acc (double xpos, double ypos, double xm, double ym, double grav, int xory);

int main () {
    double xpos, ypos, xvel, yvel, xm, ym, grav, step;
    double xtpos, ytpos, xtvel, ytvel;
    int refresh, width, height;
    int xposr, yposr, xmr, ymr;

    xpos = 3;
    ypos = 4;
    xvel = 0;
    yvel = 0;
    grav = 4;
    step = 1;
    xm = 0;
    ym = 0;
    width = 128;
    height = 64;
    refresh = 1;

    int screen[width][height];
    printf ("done2\n");
    printf ("test\n");
    printf ("done3");
    while (refresh == 1) {
        printf ("entered loop");
        usleep (100000);
        for (int a = 0; a <= height; ++a) {
            for (int b = 0; b <= width; ++b) {
                screen[b][a] = 0;
            }
        }
        xposr = rint (xpos);
        yposr = rint (ypos);
        xmr = rint (xm);
        ymr = rint (ym);
        screen[xmr][ymr] = 1;
        screen[xposr][yposr] = 1;

        for (int y = 0; y <= height; ++y) {
            for (int x = 0; x <= width; ++x) {
                if (screen [x][y] == 0) {
                    printf (" ");
                }
                else {
                    printf ("X");
                }
            }
            printf ("\n");
        }

        xtpos = xpos + (xvel * step);
        ytpos = ypos + (yvel * step);
        xtvel = xvel + (acc (xpos, ypos, xm, ym, grav, 0) * step * step);
        ytvel = yvel + (acc (xpos, ypos, xm, ym, grav, 1) * step * step);

        xpos = xtpos;
        ypos = ytpos;
        xvel = ytvel;
        yvel = xtvel;
        refresh = 0;
    }
}

double dist (double xpos, double ypos, double xm, double ym) {
    double deltax, deltay, result;
    deltax = xpos - xm;
    deltay = ypos - ym;
    result = sqrt ((deltax * deltax) + (deltay * deltay));
    return result;
}

double acc (double xpos, double ypos, double xm, double ym, double grav, int xory) {
    double result;
    if (xory == 0) {
        result = ((xpos - xm) * grav * grav) / (dist (xpos, ypos, xm, ym) * dist (xpos, ypos, xm, ym) * dist (xpos, ypos, xm, ym));
    }
    else if (xory == 1) {
        result = ((ypos - ym) * grav * grav) / (dist (xpos, ypos, xm, ym) * dist (xpos, ypos, xm, ym) * dist (xpos, ypos, xm, ym));
    }
    return result;
}

该程序似乎挂起并且从未进入可以看到的while循环,因为没有&#34;进入循环&#34;文字印在屏幕上。这很奇怪,因为while循环应该无限循环,因为refresh == 1.然后我会在while之前放一些printf语句来查看程序停止的位置。此时,运行程序后我唯一得到的是

done2
test
|

出于某种原因,该程序甚至不必费心去做下一个printf语句。

3 个答案:

答案 0 :(得分:3)

printf写入名为FILE *的特殊stdoutprintf(/*...*/)fprintf(stdout, /*.../*)同义。出于性能原因,stdout是行缓冲,这意味着在您向其写入换行符或手动刷新之前,写入其中的任何内容都可能无法向外显示。输出字符是昂贵的,通过缓冲输出我们可以输出更少的次数,我们的程序运行得更快,更快。

如果您没有输出到文件,可以通过说

让它在每个打印件上刷新
printf("entered loop\n"); // note the extra '\n'

如果你只是写文本(不是格式字符串,不打印任何变量),你也可以使用puts(const char *)打印你给它的字符串,然后换行。

puts("entered loop");
输出到文件(而不是屏幕)时,

stdout完全缓冲。以下将始终使其刷新。如果您希望输出完全按照您的编写方式保留,则可以采用以下方法:

printf("entered loop");
fflush(stdout);

如果你想生活危险,你可以做到

setbuf(stdout, NULL);

一旦进入你的主人或其他地方,这将阻止stdout上的所有缓冲(危险地,我的意思是非常慢,你可能实际上不应该这样做)。

答案 1 :(得分:2)

您应该在printf中包含换行符:

printf("entered loop\n");

这将导致缓冲区刷新。没有它,角色将无法实际打印在控制台上。顺便说一句,这也是你没有看到“done3”打印的原因,它也缺少“\ n”。

或者,您可以手动冲洗它:

printf("entered loop");
fflush(stdout);

有必要的原因是stdout是一个缓冲设备(嗯,它适用于某些* nix系统)。这意味着它不会在屏幕上打印,除非填充缓冲区,手动刷新或在打印文本中包含新行字符。

答案 2 :(得分:0)

除了kamituel和Ryan Haining发现的问题之外,您的计划还存在以下问题:

  • 当索引达到给定维度的大小时,迭代遍历screen矩阵维度的循环应该停止。您必须使用a < height代替<=。必须至少在4个不同的实例中纠正这个错误。

  • 将矩阵screen定义为int screen[height][width];更为常见,因为它允许嵌套循环中更好的局部性,y在外部循环中进行迭代x在内在的。发布的代码不正确,但有点令人惊讶。

  • 如果acc()既不是result也不是xory,则
  • 函数0会返回未初始化的变量1。如果配置正确,编译器应该针对此问题和其他潜在问题生成警告。如果xory只是一个布尔值,那么单个测试就足够了。

  • 循环while (refresh == 1)似乎只迭代一次。为什么要把它变成循环?