diff --git a/assets/calc-1.png b/assets/calc-1.png new file mode 100644 index 0000000..0dc3ab5 Binary files /dev/null and b/assets/calc-1.png differ diff --git a/assets/calc-2.png b/assets/calc-2.png new file mode 100644 index 0000000..5b55cf5 Binary files /dev/null and b/assets/calc-2.png differ diff --git a/assets/calc.png b/assets/calc.png new file mode 100644 index 0000000..decc797 Binary files /dev/null and b/assets/calc.png differ diff --git a/assets/p312.png b/assets/p312.png new file mode 100644 index 0000000..7e29d13 Binary files /dev/null and b/assets/p312.png differ diff --git a/assets/p313.png b/assets/p313.png new file mode 100644 index 0000000..9b6bf17 Binary files /dev/null and b/assets/p313.png differ diff --git a/document.yaml b/document.yaml index f9b03ea..0073fd2 100644 --- a/document.yaml +++ b/document.yaml @@ -31,5 +31,10 @@ paper_config: # - { name: "pkg-wo-opt", options: "" } sections: - - { path: 'section/introduction.tex', newpg: true } + - { path: 'section/introduction.tex', newpg: false } + - { path: 'section/syntax.tex', newpg: true } + - { path: 'section/p312.tex', newpg: true } + - { path: 'section/p313.tex', newpg: true } + - { path: 'section/calc.tex', newpg: true } + - { path: 'section/appendix.tex', newpg: true } diff --git a/main.tex b/main.tex new file mode 100644 index 0000000..51f30d6 --- /dev/null +++ b/main.tex @@ -0,0 +1,43 @@ +\documentclass{class/nitreport} + +\reporttitle{第10回課題} +\reportauthor{柴田 健琉} +\studentid{2024D14} +\seatingnum{15} +\reportdate{令和7年}{06月}{19日} +\turnindate{令和7年}{06月}{19日} +\schoolname{岐阜工業高等専門学校} +\department{電子制御工学科} +\subject{情報処理I} +\professor{岡崎憲一} + +\pagenumbering{roman} + +\begin{document} + \coverpage + + \tableofcontents + \newpage + \pagenumbering{arabic} + + \input{section/introduction.tex} + + \input{section/syntax.tex} + \newpage + + \input{section/p312.tex} + \newpage + + \input{section/p313.tex} + \newpage + + \input{section/calc.tex} + \newpage + + \input{section/appendix.tex} + \newpage + + \printbibliography[heading=bibintoc,title={参考文献}] + + \compiledTime +\end{document} diff --git a/output/main.pdf b/output/main.pdf new file mode 100644 index 0000000..4698fa7 Binary files /dev/null and b/output/main.pdf differ diff --git a/programs/calc/info.json b/programs/calc/info.json index f2d3ddd..565f656 100644 --- a/programs/calc/info.json +++ b/programs/calc/info.json @@ -1,10 +1,10 @@ { - "language": "", - "name": "", - "description": "", + "language": "C", + "name": "簡易電卓", + "description": "2つの実数を入力し、四則演算を指定し、小数点6桁で結果を表示する。0 divも考慮すること。", "output": { - "type": "screenshot | text", - "content": "" + "type": "screenshot", + "content": "./assets/calc.png" }, "note": "" } diff --git a/programs/calc/main b/programs/calc/main new file mode 100755 index 0000000..9b36d0c Binary files /dev/null and b/programs/calc/main differ diff --git a/programs/calc/main.c b/programs/calc/main.c index e69de29..897dadb 100644 --- a/programs/calc/main.c +++ b/programs/calc/main.c @@ -0,0 +1,48 @@ +#include + +#define ADD 1 +#define SUB 2 +#define MUL 3 +#define DIV 4 + +int main(void) { + double a, b; + int op; + + printf("Input first number: "); + scanf("%lf", &a); + printf("Input second number: "); + scanf("%lf", &b); + + printf("Select Operation:\n" + "[1]: Addition\n" + "[2]: Subtraction\n" + "[3]: Multiplication\n" + "[4]: Division\n" + "> "); + scanf("%d", &op); + + switch (op) { + case ADD: + printf("ANS: %lf\n", a + b); + break; + case SUB: + printf("ANS: %lf\n", a - b); + break; + case MUL: + printf("ANS: %lf\n", a * b); + break; + case DIV: + if (b == 0.0) { + puts("Zero Division"); + return 1; + } + printf("ANS: %lf\n", a / b); + break; + default: + puts("Undefined Operation"); + return 1; + } + + return 0; +} diff --git a/programs/ifvswitch/gen-if.py b/programs/ifvswitch/gen-if.py new file mode 100644 index 0000000..e7d594e --- /dev/null +++ b/programs/ifvswitch/gen-if.py @@ -0,0 +1,8 @@ +with open("./ifs.c", mode='w') as file: + num = 100000 + file.write("int comp(int x) {\n if (x == 0) {\n return 0;\n } ") + for i in range(1,num-1): + s = f"else if (x == {i}) {{\n return {i};\n }} " + file.write(s) + file.write(f"else {{\n return {num-1};\n }}\n}}") + file.write(f"\n\nint main(void) {{\n for (int i = 0; i < {num}; i++) {{ \n comp(i);\n }}\n return 0;\n}}\n") diff --git a/programs/ifvswitch/gen-switch.py b/programs/ifvswitch/gen-switch.py new file mode 100644 index 0000000..03960f8 --- /dev/null +++ b/programs/ifvswitch/gen-switch.py @@ -0,0 +1,8 @@ +with open("./switch-case.c", mode='w') as file: + num = 100000 + file.write("int comp(int x) {\n switch (x) {\n") + for i in range(num): + s = f" case {i}: return {i};\n" + file.write(s) + file.write(" }\n}") + file.write(f"\n\nint main(void) {{\n for (int i = 0; i < {num}; i++) {{\n comp(i);\n }}\n return 0;\n}}\n") diff --git a/programs/ifvswitch/progs.tar.xz b/programs/ifvswitch/progs.tar.xz new file mode 100644 index 0000000..aa303cf Binary files /dev/null and b/programs/ifvswitch/progs.tar.xz differ diff --git a/programs/p312/info.json b/programs/p312/info.json index f2d3ddd..9ececcd 100644 --- a/programs/p312/info.json +++ b/programs/p312/info.json @@ -1,10 +1,10 @@ { - "language": "", - "name": "", - "description": "", + "language": "C", + "name": "演習 3-12", + "description": "教科書のList 3-4をSwitch文で書き換えたプログラム。", "output": { - "type": "screenshot | text", - "content": "" + "type": "screenshot", + "content": "./assets/p312.png" }, "note": "" } diff --git a/programs/p312/main b/programs/p312/main new file mode 100755 index 0000000..7e0b5b6 Binary files /dev/null and b/programs/p312/main differ diff --git a/programs/p312/main.c b/programs/p312/main.c index e69de29..adfe234 100644 --- a/programs/p312/main.c +++ b/programs/p312/main.c @@ -0,0 +1,21 @@ +#include + +int main(void) { + int n; + + printf("Input Integer: "); + scanf("%d", &n); + + switch (n % 2) { + case 0: + puts("The number is even."); + break; + case 1: + puts("The number is odd."); + break; + default: + puts("Unknown Error"); + } + + return 0; +} diff --git a/programs/p313/info.json b/programs/p313/info.json index f2d3ddd..ef8cc06 100644 --- a/programs/p313/info.json +++ b/programs/p313/info.json @@ -1,10 +1,10 @@ { - "language": "", - "name": "", - "description": "", + "language": "C", + "name": "演習 3-13", + "description": "教科書のList 3-18 をSwitch文で書き換えたプログラム。", "output": { - "type": "screenshot | text", - "content": "" + "type": "screenshot", + "content": "./assets/p313.png" }, "note": "" } diff --git a/programs/p313/main b/programs/p313/main new file mode 100755 index 0000000..16a4374 Binary files /dev/null and b/programs/p313/main differ diff --git a/programs/p313/main.c b/programs/p313/main.c index e69de29..4eac1c1 100644 --- a/programs/p313/main.c +++ b/programs/p313/main.c @@ -0,0 +1,35 @@ +#include + +int main(void) { + int month; + + printf("Input month: "); + scanf("%d", &month); + + switch (month) { + case 12: + case 1: + case 2: + puts("It is winter."); + break; + case 3: + case 4: + case 5: + puts("It is spring."); + break; + case 6: + case 7: + case 8: + puts("It is summer."); + break; + case 9: + case 10: + case 11: + puts("It is autumn."); + break; + default: + puts("Unknown month."); + } + + return 0; +} diff --git a/references.bib b/references.bib index bc328a4..ed8df79 100644 --- a/references.bib +++ b/references.bib @@ -1,9 +1,8 @@ -@online{example, - title = {Example Entry}, - author = {Inc., Example}, - organization = {Example, Inc.}, - url = {https://www.example.com}, - year = {1970}, +@online{switch_cppref, + title = {switch statement}, + author = {cppreference}, + url = {https://en.cppreference.com/w/c/language/switch.html}, + year = {2018}, month = {01}, - urldate = {1970-01-01} + urldate = {2025-06-19} } diff --git a/section/appendix.tex b/section/appendix.tex index 81e259a..a7e2257 100644 --- a/section/appendix.tex +++ b/section/appendix.tex @@ -4,3 +4,67 @@ \subsection{Deep Dive - if と switch の根本的な違い} +初学者は\texttt{if}文と\texttt{switch}文の使い分けで困まる時があるようだ。 +前述したとおり、どちらも条件分岐を行うことができる。 + +しかし、2つには文法以外に明確な違いがある。それは、\texttt{switch}文のほうが「圧倒的」に\\処理速度が速いというところである。 +まず、その処理速度の違いを見てみる。 + +以下のPythonスクリプトで10万個の条件文を含むCソースコードを生成する: + +\defaultlistingstyle +\lstinputlisting[language=Python,title={\texttt{if}文10万個}]{../programs/ifvswitch/gen-if.py} +\lstinputlisting[language=Python,title={\texttt{switch}文10万個}]{../programs/ifvswitch/gen-switch.py} + +これらを実行し、Cソースコードを生成する: + +\begin{lstlisting} +$ python gen-if.py +$ python gen-switch.py +\end{lstlisting} + +\newpage + +以下が生成されたソースコードの一部始終: + +\lstinputlisting[language=C,title={\texttt{if}文10万個のソースコード},consecutivenumbers=false,linerange={1-8,199996-200010}]{../programs/ifvswitch/ifs.c} + +\lstinputlisting[language=C,title={\texttt{switch}文10万個のソースコード},consecutivenumbers=false,linerange={1-8,99998-100011}]{../programs/ifvswitch/switch-case.c} + +\begin{lstlisting} +// 検証に影響する最適化を無効にしてコンパイルする +$ gcc -O0 ifs.c -o ifs +$ gcc -O0 switch-case.c -o switch-case +\end{lstlisting} + +生成物をタイマに通して実行する: + +\begin{lstlisting} +$ time ./ifs + +real 0m59.045s +user 0m58.444s +sys 0m0.001s + +$ time ./switch-case + +real 0m0.006s +user 0m0.004s +sys 0m0.002s +\end{lstlisting} + +実行結果から\texttt{switch}文の方が\texttt{if}文の約9840倍も高速であると分かる。 + +では、なぜ\texttt{switch}文の方が速いのか。それは、比較演算の数にある。 + +\texttt{if}文はその数と同じ数の比較演算が使われている。 +一方、\texttt{switch}文は比較に関する演算は一度しか行われない。 + +それぞれのバイナリを逆アセンブルする: + +\begin{lstlisting} +$ objdump -Mintel -d ifs +$ objdump -Mintel -d switch-case +\end{lstlisting} + + diff --git a/section/calc.tex b/section/calc.tex new file mode 100644 index 0000000..4d49ad5 --- /dev/null +++ b/section/calc.tex @@ -0,0 +1,17 @@ +\section{簡易電卓} + +2つの実数を入力し、四則演算を指定し、小数点6桁で結果を表示する。0 divも考慮すること。 + +\subsection{コードリスティング} + +\lstinputlisting[language=C,title={簡易電卓}]{../programs/calc/main.c} + +\subsection{実行結果} + +\begin{center} + \includegraphics[width=\textwidth]{./assets/calc-1.png} +\end{center} + +\begin{center} + \includegraphics[width=\textwidth]{./assets/calc-2.png} +\end{center} diff --git a/section/introduction.tex b/section/introduction.tex index 4532cd4..b03c6d7 100644 --- a/section/introduction.tex +++ b/section/introduction.tex @@ -8,5 +8,5 @@ \item OS: Arch Linux \item CPU アーキテクチャ: \texttt{x86\_64} \item C コンパイラ: \texttt{gcc バージョン 14.2.1 20250322 (GCC)} - \item C コンパイラオプション: \texttt{} + \item C コンパイラオプション: \texttt{-Wall} \end{itemize} diff --git a/section/p312.tex b/section/p312.tex new file mode 100644 index 0000000..659441c --- /dev/null +++ b/section/p312.tex @@ -0,0 +1,13 @@ +\section{演習 3-12} + +教科書のList 3-4をSwitch文で書き換えたプログラム。 + +\subsection{コードリスティング} + +\lstinputlisting[language=C,title={演習 3-12}]{../programs/p312/main.c} + +\subsection{実行結果} + +\begin{center} + \includegraphics[width=\textwidth]{./assets/p312.png} +\end{center} diff --git a/section/p313.tex b/section/p313.tex new file mode 100644 index 0000000..e986681 --- /dev/null +++ b/section/p313.tex @@ -0,0 +1,13 @@ +\section{演習 3-13} + +教科書のList 3-18 をSwitch文で書き換えたプログラム。 + +\subsection{コードリスティング} + +\lstinputlisting[language=C,title={演習 3-13}]{../programs/p313/main.c} + +\subsection{実行結果} + +\begin{center} + \includegraphics[width=\textwidth]{./assets/p313.png} +\end{center} diff --git a/section/syntax.tex b/section/syntax.tex index e69de29..170f428 100644 --- a/section/syntax.tex +++ b/section/syntax.tex @@ -0,0 +1,42 @@ +\section{今回の構文} + +\subsection{\texttt{switch}文} + +\texttt{switch}文は\texttt{if}文と同じように条件分岐を行う文である。 +if文と違い、論理式・論理値による分岐ではなく、評価後の整数値によって分岐する。 +それぞれの条件は\texttt{case}ラベルで記載され、コロン(\texttt{:})の後に処理を記述する。 +処理の終わりは\texttt{break}文を書く。 +ケースは縦落ちすることができ、\texttt{break}文を書かずにしておくことで複数の値に同じ処理を割り当てることができる。 +\texttt{if}文における最後の\texttt{else}は\texttt{switch}文では\texttt{default}ラベルとなっている。\cite{switch_cppref} + +\defaultlistingstyle +\begin{lstlisting}[language=C,title={\texttt{switch}文}] +switch (式) { + case <値1>: + <処理>... // 値1の場合の処理 + break; + case <値2>: + <処理>... // 値1の場合の処理 + break; + default: + <処理>... // それ以外の場合の処理 +} +\end{lstlisting} + + +\begin{lstlisting}[language=C,title={縦落ち(Fall-through)する\texttt{switch}文}] +switch (式) { + case <値1>: + <処理>... // 値1の場合の処理 + break; + case <値2>: + case <値3>: + <処理>... // 値2と値3の場合の処理 + break; + case <値4>: + <処理>... // 値4の場合の処理 + break; + default: + <処理>... // それ以外の場合の処理 +} +\end{lstlisting}