はじめに
初めましての人もそうでない人もこんにちは!
皆さんはプログラムの勉強を勉強をしていますでしょうか?
私は動画サイトで勉強したりとか学校の課題で行う場面が多いですね!
私の最近の悩みとしては資料通りにプログラムを入力したつもりがスペルミスをしていたり大文字と小文字を間違えてしまったりとかがありますね〜
これらはエラーが出るので良心的ですがエラーが出ていないのに動いてしまうパターンがいちばん厄介でどこが違うのか本当にわかりにくいんですよね〜
絶対にどこかのコードが間違っているのでよくよく探してみると抜けているコードがあったりなど本当に厄介でした!
もちろんパソコンのショートカットキーを使ってコピペすれば手っ取り早いですがそれでは自分の成長には繋がりません!
どこを間違えてどうして間違えたのか理解しないといけないのでそれは避けたいです!
なのでどこの行が違うのか探すことが容易になればやりやすいと思ったので今回は2つのプログラムを比較できるアプリを作成していきたいと思います!
今回の目標
1.どの文章が違うのか行で判断させる!
2.違う文章があった場合はその行全体に赤でマーカーを引く!
この2点を意識して作成していきます!
扱う言語・技術
フロントエンド
React + TypeScript
バックエンド
Go
ディレクトリ構成
今回作成するディレクトリ構成です!
hikaku/
│
├── frontend/
│ ├── src/
│ │ ├── App.tsx
│ │ ├── App.css
│ │ ├── components/
│ │ │ └── TextComparison.tsx
│ │ └── ...
│ └── ...
└── backend/
├── main.go
├── go.sum
└── go.mod
準備しよう!
それではhikakuというフォルダを作成してhikakuディレクトリに移動したら以下のターミナルコマンドを入力してください!
フロントエンドの準備
npx create-react-app frontend --template typescript
cd frontend
npm install axios
バックエンドの準備
もうひとつターミナルを作成してhikakuディレクトリに戻ったら以下のコマンドを入力してください!
mkdir backend
cd backend
go mod init backend
go get github.com/gin-contrib/cors
go get github.com/gin-gonic/gin
これでフロントエンドとバックエンドの開発準備が完了しました!次から作成していきましょう!
作っていこう!
フロントエンド
以下のコードをコピペしてください!
import React from 'react';
import TextComparison from './components/TextComparison';
const App: React.FC = () => {
return (
<div className="App">
<h1>比較アプリ</h1>
<TextComparison />
</div>
);
};
export default App;
import React, { useState } from 'react';
import axios from 'axios';
const TextComparison: React.FC = () => {
const [text1, setText1] = useState('');
const [text2, setText2] = useState('');
const [comparison, setComparison] = useState('');
const [text1Html, setText1Html] = useState('');
const [text2Html, setText2Html] = useState('');
const handleCompare = async () => {
try {
const response = await axios.post('http://localhost:8080/compare', { text1, text2 });
setComparison(response.data.comparison);
setText1Html(response.data.text1Html);
setText2Html(response.data.text2Html);
} catch (error) {
console.error('Error comparing texts:', error);
setComparison('Error occurred while comparing texts');
setText1Html('');
setText2Html('');
}
};
return (
<div>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<textarea
value={text1}
onChange={(e) => setText1(e.target.value)}
placeholder="文章を入れてください"
style={{ width: '45%', height: '150px' }}
/>
<textarea
value={text2}
onChange={(e) => setText2(e.target.value)}
placeholder="文章を入れてください"
style={{ width: '45%', height: '150px' }}
/>
</div>
<button onClick={handleCompare} style={{ margin: '10px 0' }}>比較する</button>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<div style={{ width: '45%' }}>
<h4>文章1:</h4>
<div
dangerouslySetInnerHTML={{ __html: text1Html }}
style={{ whiteSpace: 'pre-wrap', fontFamily: 'monospace' }}
/>
</div>
<div style={{ width: '45%' }}>
<h4>文章2:</h4>
<div
dangerouslySetInnerHTML={{ __html: text2Html }}
style={{ whiteSpace: 'pre-wrap', fontFamily: 'monospace' }}
/>
</div>
</div>
</div>
);
};
export default TextComparison;
このようになるようにコピペしてくd・・・
(心の声:今回の導入でコピペしたら成長しないって書いたよな〜。なのにコピペしてくださいっていうのはおかしい気が・・・)
頑張って手を動かして作成してください!!
バックエンド
お疲れ様です!おそらくこれをみている頃には手がガタガタになって辛いとは思いますがこの調子で次のコードも"手打ちで!"頑張ってください
package main
import (
"html"
"net/http"
"strings"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
)
type CompareRequest struct {
Text1 string `json:"text1"`
Text2 string `json:"text2"`
}
type CompareResponse struct {
Comparison string `json:"comparison"`
Text1HTML string `json:"text1Html"`
Text2HTML string `json:"text2Html"`
Differences int `json:"differences"`
}
func main() {
r := gin.Default()
config := cors.DefaultConfig()
config.AllowOrigins = []string{"http://localhost:3000"}
r.Use(cors.New(config))
r.POST("/compare", compareTexts)
r.Run(":8080")
}
func compareTexts(c *gin.Context) {
var req CompareRequest
if err := c.BindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
lines1 := strings.Split(req.Text1, "\n")
lines2 := strings.Split(req.Text2, "\n")
comparison := "The texts are "
if len(lines1) != len(lines2) {
comparison += "different in number of lines. "
} else {
comparison += "of the same number of lines. "
}
differences := 0
text1HTML := ""
text2HTML := ""
maxLines := len(lines1)
if len(lines2) > maxLines {
maxLines = len(lines2)
}
for i := 0; i < maxLines; i++ {
if i < len(lines1) && i < len(lines2) {
words1 := strings.Fields(lines1[i])
words2 := strings.Fields(lines2[i])
lineHTML1 := ""
lineHTML2 := ""
maxWords := len(words1)
if len(words2) > maxWords {
maxWords = len(words2)
}
for j := 0; j < maxWords; j++ {
if j < len(words1) && j < len(words2) {
if words1[j] != words2[j] {
differences++
lineHTML1 += "<span style='background-color: #ffcccb'>" + html.EscapeString(words1[j]) + "</span> "
lineHTML2 += "<span style='background-color: #ffcccb'>" + html.EscapeString(words2[j]) + "</span> "
} else {
lineHTML1 += html.EscapeString(words1[j]) + " "
lineHTML2 += html.EscapeString(words2[j]) + " "
}
} else if j < len(words1) {
differences++
lineHTML1 += "<span style='background-color: #ffcccb'>" + html.EscapeString(words1[j]) + "</span> "
} else if j < len(words2) {
differences++
lineHTML2 += "<span style='background-color: #ffcccb'>" + html.EscapeString(words2[j]) + "</span> "
}
}
text1HTML += strings.TrimSpace(lineHTML1) + "<br>"
text2HTML += strings.TrimSpace(lineHTML2) + "<br>"
} else if i < len(lines1) {
differences++
text1HTML += "<span style='background-color: #ffcccb'>" + html.EscapeString(lines1[i]) + "</span><br>"
} else if i < len(lines2) {
differences++
text2HTML += "<span style='background-color: #ffcccb'>" + html.EscapeString(lines2[i]) + "</span><br>"
}
}
comparison += "There are " + string(differences) + " differences between the texts."
response := CompareResponse{
Comparison: comparison,
Text1HTML: strings.TrimSpace(text1HTML),
Text2HTML: strings.TrimSpace(text2HTML),
Differences: differences,
}
c.JSON(http.StatusOK, response)
}
お疲れ様でした!後は実行するだけとなります!
実行!
2つのターミナルを用意してそれぞれfrontendとbackendのディレクトリに移動して
npm start
と
go run main.go
を入力して実行してみてください!
入力して試しにApp.tsxの内容を少し変えて試してみると直感的に異なるところがわかるようになりました!
終わりに
みなさんいかがだったでしょうか?
自分は英語がそこまで得意ではないのでちょくちょくスペルミスをしでかしてしまいますw
こうゆうのがあれば本当に頼もしいです!
みなさんのプログラミング技術が向上することを願っています!
これで今回の記事は終了です!
またどこかの記事でお会いしましょう!
Github URL