【CS50】PSET3&4 模拟选举/图片处理(模糊)

356 阅读2分钟

这个系列是在观看Harvard Cs50课程中,做课后ProblemSets的一些记录。

网络上已经存在很多该系列的blogs和videos,该文用以自我记录,并提供给其他和我一样的代码新手+中文使用者一些参考。

包含每个pset中我认为值得注意的points总结,并mark一些优秀解法。

Plurality (Pset3)

Background: Vote for certain candidates, and print out the winner.

strcmp

use strcmp, a function that is defined in string.h header, to compare two strings, and check if a certain string is exsited.

    for (int i = 0; i<candidate_count; i++)
    {
        if (strcmp(candidates[i].name, name ) == 0)
        {
            candidates[i].votes ++ ; 
            return true;
        }
        return false;

How to select the max voted candidate?

  • 用 * tracker iterate 迭代* 的思维代替比较 的思维。
  • 设置一个值,使之始终 track 目前输入的最大值,不断迭代。

Tips:其他注意的小点

  1. for loop 中,分隔条件用; 来进行。
  2. 记住 print 等动作后要用分号;来结束。
  3. return 的位置:return false 是在某个功能结尾。 [举例]
bool vote(string name)
{
    // TODO
    for (int i = 0; i<candidate_count; i++)
    {
        if (strcmp(candidates[i].name, name ) == 0)
        {
            candidates[i].votes ++ ; 
            return true;
        }
    }
    return false;
    // 这个地方写错了 return 的位置,导致了 bug 出现。
}
  1. int argc: 用来记录输入在命令行的字符串个数;
  2. string argv:用来记录输入在命令行的指令
  3. 上述两个命令需要载入#include <string.h>

Pset4 filter

Background 背景知识

Bitmaps

  1. 24-bit color 类似 BMP、JPEG、PNG 的文件,支持使用 24-bit color,即,每个像素(pixel)使用 24 个 bits。 BMP 文件一般支持 1-,4-,8-,16-,24-,以及 32-bit color。 [Example: 如何表示 Red]
R | G | B
0xff | 0x00 | 0x00
pure red | no green | no blue

[TOC] 2. BITMAP 中的BITMAPFILEHEADER

  • 存储文件尺寸,height and width;
  • 存储在这个 header 中,长度为 14bytes(14*8 个 bits);
  1. BITMAP 中的BITMAPINFOHEADER
  • 长度为 40bytes。
  1. 在 实际的bitmap 中,色彩是反过来存储的,即 RGB 的顺序实际上是 BGR,例如0000ff代表的其实是red

常见的图像处理

  1. Grayscale 变为灰度图像
  • 当图像变为灰度值时,RGB 三个值应该是相同的(才能混合出灰度的形态)
  • 使用 RGB 的平均值来确定灰度后像素的值。
  1. Sepia 处理为红褐色调(an old-timey feel)
  • 将原有的每个像素 RGB 值通过特定算法改变,最终呈现出红褐色调的感觉。
  • 有许多种处理的算法,以下举例一种算法:
sepiaRed = .393 * originalRed + .769 * originalGreen + .189 * originalBlue
sepiaGreen = .349 * originalRed + .686 * originalGreen + .168 * originalBlue
sepiaBlue = .272 * originalRed + .534 * originalGreen + .131 * originalBlue

1、2 处理起来都不复杂。 关键是一定要记住 declare 每个变量的类型。 以及在做 grey 的时候不知道为什么遇到了 segmentation fault,重新搞了一遍有没有了。


  1. Relection 镜像处理
  • 记住在 bitmap 中使用了一个 2-dimensional array 来表示像素的位置;
  • 通过算法改变每个像素的位置后,即可实现相应的镜像;
void reflect(int height, int width, RGBTRIPLE image[height][width])
{
    for (int i = 0; i < height; i++)
    {
        // iterate through the array until you get to the mid-point
        for (int j = 0; j < (width/2); j++)
        {
            RGBTRIPLE temp = image[i][j];
            //just like how [0][9]...[4][5], [i] will swap with [total-1-i]
            image[i][j] = image[i][width - (j + 1)];
            image[i][width - (j + 1)] = temp;
        }
    }
    return;
}
  1. Blur 模糊处理
  • 将特定的 pixel 色值与周围 pixel 色值的求取平均值,并将这些 pixels 赋予新的色值。
  • 周围的含义:类似扫雷游戏原理。 这个好难,是俺第一次接触分情况讨论的问题。
  1. 情况 1:该像素周围(连同自身)一共有 9 个 pixel,即处于中间地带;
  2. 情况 2:该像素周围(连同自身)一共有 6 个 pixel,即处于边上;
  3. 情况 3:该像素周围(连同自身)一共有 4 个 pixel,即处于角上; 目前我可以看懂的一种解法:完全分情况讨论,并且把左边右边上下左右角都分开情况(可以通过[i+1/-1]等方式较为轻松但写起来很繁复实现)。

解法链接:medium.com/@dentured/c…

stackoverflow 上还有人给出了用矩阵简洁判断的方式,但我矩阵都快忘干了,目前没有力气研究。先码着等我想起矩阵咋算再来看吧。

stackoverflow.com/questions/6…