---
# System prepended metadata

title: Compute Area of Rectangle
tags: [Coding Practice]

---

---
title: 'Compute Area of Rectangle'
tags: Coding Practice
---
# Compute Area of Rectangle
contributed by < `ChongMingWei` >

## Outline
[TOC]



## 題目
給定一含有4個座標點的字串，坐標皆位於 Cartesian grid 上(皆為整數坐標點)，給定的順序不為一定，請計算出該矩形的面積。
E.g.
- input
`{"(-1 2)","(4 -1)", "(4 2)", "(-1 -1)"}`
- output
`15`

## 實作流程
- 首先需要將給定的字串中，所有的座標資料分析出來，使用到 `strtok` 來切出數字的部分，接著使用 `strtol` 來將切出的數字字串轉變為 `long` 的資料型太後，映射到 `int` 資料型態儲存。
這邊我們只需要選擇前三組座標即可，原因如下:
    - 我們使用三組座標，會形成一個直角三角形，而我們可以藉由此三組座標得到三個不同的向量，其中必定會有兩個向量互相垂直，只要得到這兩個向量，就可以用外積來計算矩形面積。
![](https://i.imgur.com/g77siqx.png)

> 參考 [外積公式](https://read01.com/zh-tw/EQjg88.html#.X39XLMIzaM9)
- 計算面積: 使用外積的方式，但此處我們只有二維，但仍可已將其擴充到三維坐標:
$v1 = (x1,y1),\ v2=(x2,y2)>>v1 = (x1,y1,0),\ v2=(x2,y2,0)$
![](https://i.imgur.com/2X8Mbec.png)
此時我們只需要計算 $x1y1-x2y2$ ，最後將此外積結果加上絕對值 $|x1y1-x2y2|$ 就是我們要求的面積。


## 程式碼
```c=
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
typedef struct vector{
    int x;
    int y;
}vec;
//使用外積來計算矩形面積
int compute_cross(vec v1, vec v2){
    int area = (v1.x*v2.y-v2.x*v1.y);
    //取絕對值
    int mask = area>>31;
    return (area + mask) ^ mask;
}
int compute_area(char **a, int len){
    int *coords = malloc(sizeof(int)*(len-1)*2);
    const char *lp = "(";
    const char *rp = ")";
    const char *s = " ";
    /*This kind is also ok
     * char lp[] = "(";
    char rp[] = ")";
    char s[] = " ";*/
    for (int i =0;i<len-1;i++){
        char *first=NULL, *second=NULL;//分別用來放空格前、後的字串
        char *buf;
        buf = malloc(sizeof(char)*(strlen(a[i])+1));//strlen得到的會是去到`\0`的長度，所以+1
        strncpy(buf, a[i], strlen(a[i])+1);
        first = strtok(buf, s);
        second = strtok(NULL, s);
        //以'('來切割，這邊'('前沒有字串，會返回'('後的字串，也就是x坐標
        char *num1 = strtok(first, lp);
        //string轉long，再映射成int
        coords[2*i] = strtol(num1,NULL,10);
        //以')'來切割，返回')'前的字串，也就是y坐標
        char *num2 = strtok(second, rp);
        //string轉long，再映射成int
        coords[2*i+1] = strtol(num2,NULL,10);
        //釋放記憶體
        free(buf);

    }
    //前三組座標形成的三個向量
    vec v1, v2, v3;
    v1.x = coords[2]-coords[0];
    v1.y = coords[3]-coords[1];
    v2.x = coords[4]-coords[0];
    v2.y = coords[5]-coords[1];
    v3.x = coords[4]-coords[2];
    v3.y = coords[5]-coords[3];
    //分別計算內積，若為0表示夾角為90度，使用外積計算面積並返回
    if ((v1.x*v2.x+v1.y*v2.y)==0)
        return compute_cross(v1,v2);
    else if((v1.x*v3.x+v1.y*v3.y)==0)
        return compute_cross(v1,v3);
    else 
        return compute_cross(v2,v3);
    //釋放記憶體
    free(coords);


}

int main(int argc, char *argv){
    char *a[] = {"(-1 2)","(4 -1)", "(4 2)", "(-1 -1)"};
    int len = sizeof(a) / sizeof(*a);
    int area = compute_area(a,len);
    printf("result:%d\n",area);
    return 0;
}
```

### strtok的使用
當我們在使用 `strtok` 時，欲分割的字串必須要"可修改"，因為欲分割的字串本身會遭到 `strtok` 修改，如以下範例:
```c=
int main(int argc, char *argv){
    char s[] = " ";
    char test[] = "(4 -1)";
    char *buf = malloc(sizeof(test));
    strcpy(buf,test);
    printf("%s\n",buf);
    char *first = strtok(buf, s);
    printf("%s\n",buf);
    char *first2 = strtok(NULL, s);
    printf("%s\n",buf);
    printf("%s\n",first);
    printf("%s\n",first2);
    return 0;
}
```
輸出結果:
```cpp
(4 -1) //原本的 buf
(4     //經過strtok處理過後的buf
(4     
(4     //first
-1)    //first2
```
如果改成以下:
```c=
int main(int argc, char *argv){
    char s[] = " ";
    char *buf = "(4 -1)";//內容不可被修改
    printf("%s\n",buf);
    char *first = strtok(buf, s);
    printf("%s\n",buf);
    char *first2 = strtok(NULL, s);
    printf("%s\n",buf);
    printf("%s\n",first);
    printf("%s\n",first2);
    return 0;
}
```
輸出結果:
```cpp
執行期間發生錯誤（RE） #stdin #stdout 0s 4176KB
```