我尝试创建一个C代码,可以创建一个ppm,就像图片1中的文本文件一样。当某人可以提供帮助时,就可以了。我是一个新的程序员,我试过做6秒的代码。我试图扫描文本文件中的数据并将其放入数组并尝试使用ppm,但我的代码无法使用:/。
答案 0 :(得分:0)
前进的道路是将任务拆分为较小的子任务,分别解决和测试每个子任务,并且只有在它们全部工作后才将它们组合成一个程序。
因为OP没有发布任何代码,我也不会发布任何直接有用的代码。如果由于即使在尝试之后没有获得任何前进进展而确实阻止OP,这实际上应该是实际使用的。如果OP只是在寻找某人做功课,那么这应该会让他们非常烦恼。两者都适合我。 :)
第一个子任务是读取数组中的输入。网上有几个例子,这里有相关问题。您希望将其放在一个单独的函数中,以便以后合并到整个项目中更容易。由于您是初学程序员,因此可以使用
这样的函数int read_numbers(double data[], int max);
使调用者声明最大数据点数,并且该函数返回读取的数据点数;如果发生错误,则为负数。用于测试该功能的main()
应该是微不足道的,比如说
#define MAX_NUMBERS 500
int main(void)
{
double x[MAX_NUMBERS];
int i, n;
n = read_numbers(x, MAX_NUMBERS, stdin);
if (n <= 0) {
fprintf(stderr, "Error reading numbers from standard input.\n");
return EXIT_FAILURE;
}
printf("Read %d numbers:\n", n);
for (i = 0; i < n; i++)
printf("%.6f\n", x[i]);
return EXIT_SUCCESS;
}
第二个子任务是生成PPM图像。 PPM实际上是一组密切相关的图像格式,也称为Netpbm format。示例图像是位图图像 - 仅黑色和白色;没有颜色,没有灰色阴影 - 因此PBM格式(或PPM的变体)适合于此。
我怀疑通过使用二维数组攻击此子任务是最容易的,该数组的大小适合您可以生成的最大图像(即unsigned char bitmap[HEIGHT_MAX][WIDTH_MAX];
),但请注意,您也可以使用它。 (您也可以动态生成图像,没有任何数组,但这更容易出错,并且不像使用数组存储图像那样普遍适用。)
您可能需要根据最大数据值确定位图的宽度,并根据数据点的数量确定位图的高度。
测试时,只需用一些简单的图案填充数组,或者只是从左上角到右下角的对角线。
然后,考虑编写一个将矩形区域设置为给定值(0或1)的函数。根据图像,您还需要一个绘制垂直虚线的功能,改变(异或)每个位的状态。例如,
#define WIDTH_MAX 1024
#define HEIGHT_MAX 768
unsigned char bitmap[HEIGHT_MAX][WIDTH_MAX];
int width = 0;
int height = 0;
void write_pbm(FILE *out); /* Or perhaps (const char *filename)? */
void fill_rect(int x, int y, int w, int h, unsigned char v);
void vline_xor(int x, int y, int h);
此时,您应该已经意识到应该首先编写和测试write_pbm()
函数,即保存PBM图像的函数。然后,您可以使用fill_rect()
函数不仅绘制填充的矩形,还可以将图像(您要使用的数组部分)初始化为背景颜色(0或1)。上面的所有三个函数都可以,而且应该在不同的子步骤中完成,这样您就可以依赖于您之前编写的代码是正确和经过测试的。这样,您只需要查看自上次成功测试以来您编写的代码中的错误!这听起来似乎是一种缓慢的进展方式,但事实证明它是获得代码工作的最快方式。你很快就开始喜欢测试给你的信心,以及你只需要一次关注和担心一件事。
第三个子任务是找出一种绘制矩形和垂直虚线的方法,用于各种输入。
(我在上面做了一点作弊,并在前一个子任务中包含了fill_rect()
和vline_xor()
函数,因为我可以告诉他们需要绘制示例图片。)
垂直虚线最容易绘制,使用绘制垂直线的功能,保持每个其他像素不变,但每隔一个像素排除一次。 (提示:for (y = y0; y < y0 + height; y += 2) bitmap[y][x] ^= 1;
)
留下填充的矩形。它们的高度显然是恒定的,它们之间有一些垂直空间,它们从左边缘开始;所以,唯一的办法是计算每个矩形的宽度。 (并且,整个位图应该有多宽,以及有多高,如前所述;最大的数据值和数据值的数量决定了这些。)
我建议您为每个子步骤编写一个单独的程序,而不是编写一个C源文件,并在每一步添加它。也就是说,在每次使用子部件后,将其保存为单独的文件,并保留以供参考 - 如果愿意,可以备份。如果你完全迷失方向,或决定解决某些问题的另一条路径,你只需要恢复到上一个参考版本,而不是从头开始。
众所周知,这种工作流程是可靠,高效和可扩展的:无论项目有多大,上述方法都可行。当然,有一些工具可以帮助我们以简单,结构化的方式执行此操作(对每个提交的注释 - 已完成的代码单元,如果您愿意的话); git
是一个流行的,免费但非常强大的。如果您对此感兴趣,只需对git for beginners
进行网络搜索。
如果您不愿意通读上述文字并阅读其描述的工作流程,那么您在学习如何使用git
等工具来帮助您完成工作流程时会遇到很多麻烦。您还会喜欢有多少打字工具,例如make
(以及包含制作配方的Makefiles
),以及制作和维护不仅可以工作的项目,而且看起来多么容易专业的。然而,不要试图同时掌握所有这些:一步一小步,确认你有稳固的基础,然后继续前进。这样,当你绊倒时,你不会伤到自己;只是学习。
玩得开心!