This commit is contained in:
2025-06-19 17:30:16 +09:00
parent 261688c4bc
commit 3a3c8f4675
27 changed files with 340 additions and 24 deletions

BIN
assets/calc-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 910 KiB

BIN
assets/calc-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 481 KiB

BIN
assets/calc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

BIN
assets/p312.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 KiB

BIN
assets/p313.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 851 KiB

View File

@@ -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 }

43
main.tex Normal file
View File

@@ -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}

BIN
output/main.pdf Normal file

Binary file not shown.

View File

@@ -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": ""
}

BIN
programs/calc/main Executable file

Binary file not shown.

View File

@@ -0,0 +1,48 @@
#include <stdio.h>
#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;
}

View File

@@ -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")

View File

@@ -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")

Binary file not shown.

View File

@@ -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": ""
}

BIN
programs/p312/main Executable file

Binary file not shown.

View File

@@ -0,0 +1,21 @@
#include <stdio.h>
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;
}

View File

@@ -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": ""
}

BIN
programs/p313/main Executable file

Binary file not shown.

View File

@@ -0,0 +1,35 @@
#include <stdio.h>
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;
}

View File

@@ -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}
}

View File

@@ -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}

17
section/calc.tex Normal file
View File

@@ -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}

View File

@@ -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}

13
section/p312.tex Normal file
View File

@@ -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}

13
section/p313.tex Normal file
View File

@@ -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}

View File

@@ -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}