-
Notifications
You must be signed in to change notification settings - Fork 0
8. String to Integer (atoi) #64
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,159 @@ | ||
| ## ステップ1 | ||
| 問題文に記載の条件をそのままコードに起こした。 | ||
| indexを用意してsを探索する | ||
| ・スペースの間はindexを進める | ||
| ・+/-の場合もindexを進めるが、intが負の数であるのかどうかを記録する | ||
| ・0以外が現れるまで、indexを進める | ||
| ・有効な数字(先頭は1~9でそれ以降は、 0~9)が現れた場合は配列に突っ込む | ||
| ・配列から取り出し、数値型に変換しながら最終的な数値を作る | ||
|
|
||
| intの限界値の処理に時間がかかった。 | ||
| acceptまで35分 | ||
| 時間計算量O(n) | ||
| 空間計算量O(n) | ||
|
|
||
| ## ステップ2 | ||
| ・IsNumberという関数を自作したが、C++に既にありそう | ||
| ・converted == numeric_limits<int>::max() / 10 && digit > 7と言う条件を使ったが | ||
| この7が分かりづらい気がする | ||
| ・ numeric_strs[i] - '0'以外にキャストする方法は? | ||
| ・longやlong long sの場合は?どうなる | ||
|
|
||
| ・IsNumberという関数を自作したが、C++に既にありそう | ||
| std::isdigitが存在している | ||
| https://en.cppreference.com/w/cpp/string/byte/isdigit | ||
|
|
||
| ・converted == numeric_limits<int>::max() / 10 && digit > 7と言う条件を使ったが | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 7 は、numeric_limits::max() % 10 ということですかね。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @oda
はいそのつもりで書きましたが、7って何?と自分でもしっくりこなかったです。 |
||
| この7が分かりづらい気がする | ||
| 絶対値を見た場合負の数側の方の一の位が8なので動く(怪しい気がする) | ||
| -2147483647になる場合、intminにならないのでそもそもstep1は誤っている | ||
|
|
||
| ・ numeric_strs[i] - '0'以外にキャストする方法は? | ||
| static_cast<int>()は使えない | ||
| >Character types are integer types used for a character representation. | ||
| C++はのCharはintの一種でstatic_castを用いるとASCIIコードに変換されるため | ||
| 試しにやってみると確かに今回の問題とは意図しない形になった | ||
|
|
||
| (int)も使えない、static_castと同じようにASCIIコードに変換される | ||
| 今回の場合、numeric_strs[i] - '0'を使うしかないのか | ||
|
|
||
| ・longやlong long sの場合は?どうなる | ||
| 内部もそれに合わせる | ||
|
|
||
| ## ステップ3 | ||
| **3回書き直しやりましょう、といっているのは、不自然なところや負荷の高いところは覚えられないからです。** | ||
|
|
||
| ## 他の方の解法 | ||
| ・long longの場合は、内部のintで計算しているところをlongやlong longに置き換えている | ||
| ・C++におけるオーバーフローの検出方法についてコメントがある | ||
| そもそもgccとclangの違いについてよく分かっていない(どちらもコンパイラですぐらい) | ||
| https://github.com/philip82148/leetcode-arai60/pull/6/commits/4e7c21a9e3cb96327ec31ece06e5c3fc1b0bbc03 | ||
|
|
||
| ・MIN = - MAX - 1の形で覚えておけばいいのか | ||
| ・サインビットの部分をPositive,Negativeと変数名としておくのも分かりやすい | ||
| https://github.com/Yoshiki-Iwasa/Arai60/pull/64/commits/857ed449085ebae4c21cd475d45b541d6d43ccac | ||
|
|
||
| ・処理ごとに関数に分けるのも一つの手段か | ||
| ・Pythonのisdigit()を使わないのかなと思ったら理由が書かれていた | ||
| >[0-9]以外もTrueにするやつがいくつかあったと思うので使うのを止めておい | ||
| なるほどです | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 漢字などでも True になるのは Python の isdigit の話ですね。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @oda C++であっても影響を受ける場合があるのですね。
|
||
| C++では、ロケールの影響は受ける可能性がある | ||
| ・joinして最後に変換する方法もある | ||
| c++だと変換した瞬間にオーバーフローしそう | ||
| https://github.com/fhiyo/leetcode/pull/57/commits/981cf81c9c82ed22dcc53f6d17e8a2364b32bc92 | ||
| https://github.com/Mike0121/LeetCode/pull/23 | ||
|
|
||
| ## Discordなど | ||
|
|
||
| ## コンパイラについての調査 | ||
| ISOに規格が存在する。 | ||
| ISO International Standard for C++, ISO IS 14882:1998, Programming Language - C++ | ||
|
|
||
| # gccについて | ||
| そもそもGNUとは?gccとどう関係する? | ||
| GNUとはオペレーティングシステムであり、かつコンピュータソフトウェアの広範囲に渡るコレクションである。 | ||
| GNUソフトウェアとLinuxカーネルを組み合わせたものが一般的に知られるLinuxである。 | ||
| GNUのカーネルにLinuxカーネルを用いるのが一般的な理由は、 | ||
| GNUのカーネルがGNUの中で最も成熟していない部分のためである。 | ||
| GNUのコンポーネントの一つとしてgccが存在している | ||
|
|
||
| gcc(GNU Compiler Collectionの略) | ||
| 最新標準パッケージには C、C++、Objective-C、Objective-C++、Fortran、Ada、Go、Dのコンパイラ並びに | ||
| これらのライブラリが含まれている。なるほどだからコレクションなのか。 | ||
|
|
||
| gccは、 実は、コンパイラドライバ(compiler driver)と呼ばれるプログラムであり、 | ||
| Cなどのプログラミング言語で書かれたソースプログラムから実行形式を 作り出すための処理を行う。 | ||
| gccは、「必要に応じてコンパイラや アセンブラ、リンケージエディタなどのプログラムを呼び出す」という 処理を行っている | ||
| gccコマンド自体が直接コンパイルを行っているわけではない。 | ||
|
|
||
| # コンパイルの手順 | ||
| 前処理 (Preprocess) | ||
| マクロ展開やヘッダの読み込みを行い、.i ファイルに保存。 | ||
| -E オプションで前処理のみ実行(結果は標準出力)。 | ||
|
|
||
| コンパイル (Compile) | ||
| コンパイラが .i をアセンブリ .s に変換。 | ||
| -S オプションでアセンブリコードのみ生成。 | ||
|
|
||
| アセンブル (Assemble) | ||
| アセンブラが .s をオブジェクトファイル .o に変換。 | ||
| -c オプションでここまでの処理を行い、リンクを省略。 | ||
|
|
||
| 連結編集 (Linkage Edit) | ||
| crt0.o(ランタイムルーチン)やライブラリをリンク(まとめる)。 | ||
| 対象: | ||
| ・ソースプログラムを前処理/コンパイル/アセンブルした結果 生成されたオブジェクトプログラム | ||
| ・プログラムの実行にあたって初期化や後処理などを行う 特別なオブジェクトプログラムである、crt0.o。(C RunTime) | ||
| ・-lオプションで指定されたライブラリに アーカイブされたオブジェクトプログラム(後述) | ||
|
|
||
| -o で出力ファイル指定、未指定時は a.out。 | ||
| -v で処理の詳細を確認可能。 | ||
|
|
||
| 複数のファイルをまとめて1つのファイルにすることを、 アーカイブ(archive)という。 | ||
| 複数のオブジェクトプログラムを一つのファイルにアーカイブしたものを、 ライブラリ(library)という。 | ||
|
|
||
| C言語で使われるprintf()などの標準的な関数は、 libc.aというライブラリに まとめられている。 | ||
| gccは連結編集するときに自動的にlibc.aを用いるので、 libc.aに含まれている関数を使うときにはgccに明示的にライブラリ名を | ||
| 指定する必要がない。しかしそれ以外のライブラリ (例えば数学ライブラリである libm.a)を使う場合には、 | ||
| (例えば-lmのように)明示的にライブラリ名を指定する必要がある。 | ||
|
|
||
|
|
||
| # clangについて | ||
| プログラミング言語 C、C++、Objective-C、Objective-C++ 向けのコンパイラフロントエンドである。 | ||
| コンパイラフロントエンド: 高水準言語を中間言語に翻訳するもの | ||
| コンパイラバックエンド: 中間言語をハードウェアプラットフォームの機械語に翻訳するもの | ||
| 中間言語を挟むことで、互換性の問題を回避する(コンパイラフロントエンドは中間言語に訳すことだけに専念できる) | ||
| LLVMプロジェクトで使われている | ||
| LLVMプロジェクトとは再利用可能なコンパイラのプロジェクトの集まり? | ||
|
|
||
| # コンパイルの手順 | ||
| これはgccと同じ(ほぼ同じ) | ||
|
|
||
| # gccとclangの違いは | ||
| GCCはコンパイル処理にはマルチスレッドを用いていないので、ソース一つごとのコンパイルではマルチプロセッサのハードウェアの恩恵を受けられない。一方Clangはメモリ使用量の削減と速度の向上を目指してコンパイルの処理が最初からマルチスレッド対応で設計されている。 | ||
| 2007年10月の時点で、ClangはCarbonのライブラリを、メモリとディスクを1/5程度しか使用せずに、GCCの2倍以上の速度でコンパイルできる | ||
| ※Carbon はPHPで日付と時間を扱うためのライブラリ | ||
|
|
||
| 共通もコマンドもあるがgccのみやclangのみのコマンドなども存在する | ||
| https://solid.kmckk.com/SOLID/doc/latest/solid_toolchain/overview.html | ||
|
|
||
| The LLVM compilers (clang, clang++) give error messages that are actually (somewhat) understandable, that’s a big plus for me (dabbling in C++). GCC is getting there, though. | ||
| The suport for new/experimental language features varies, they don’t support the same. | ||
| LLVM is much more open, you can hook your own tools in to do all sorts of fancy stuff. Not for the faint hearthed. | ||
| GCC supports more source languages and targets. | ||
| For some the GPL of GCC is a turn off. | ||
| proもconのどちらもあるので、clangが完全な上位互換ではなさそう | ||
|
|
||
| Refs: | ||
| https://docs.oracle.com/cd/E19957-01/806-4837/intro.html#702172 | ||
| https://ja.wikipedia.org/wiki/GNU | ||
| https://ja.wikipedia.org/wiki/GNU%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%A9%E3%82%B3%E3%83%AC%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3 | ||
| https://nenya.cis.ibaraki.ac.jp/TIPS/compiler.html | ||
| https://ja.wikipedia.org/wiki/Clang | ||
| コンピュータシステムの理論と実装 | ||
| https://www.quora.com/What-are-the-advantages-and-disadvantages-of-using-Clang-over-GCC-Why-would-someone-choose-to-use-Clang-instead-of-GCC | ||
| https://www.reddit.com/r/C_Programming/comments/som4ys/gcc_or_clang/ | ||
| https://www.llvm.org/ | ||
|
|
||
| C++を使っている方々がコンパイラに対してどれだけ理解して、何を抑えているのか知りたいです。 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 自分のよく使う言語かどうかに結構よるとは思います。(よく使うと、使うときに心配になるので、常に少しずつ調査をしています。) ざっくりとした仕組み、プリプロセッサが走って、狭義コンパイルのあとにリンクするなどは、たまに使う知識でしょう。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
これが身につけないといけない姿勢ですね。
この部分はしっかりと理解しておこうと思います。 |
||
| 教えていただけると幸いです。 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| class Solution { | ||
| public: | ||
| int myAtoi(string s) { | ||
| int index = 0; | ||
| while (index < s.size() && s[index] == ' ') { | ||
| index++; | ||
| } | ||
|
|
||
| bool is_negative = false; | ||
| if (index < s.size() && s[index] == '-') { | ||
| is_negative = true; | ||
| index++; | ||
| } else if (index < s.size() && s[index] == '+') { | ||
| index++; | ||
| } | ||
|
|
||
| while (index < s.size() && s[index] == '0') { | ||
| index++; | ||
| } | ||
|
|
||
| vector<char> numeric_strs; | ||
| while (index < s.size() && IsNumber(s[index])) { | ||
| numeric_strs.push_back(s[index]); | ||
| index++; | ||
| } | ||
|
|
||
| int converted = 0; | ||
| for (int i = 0; i < numeric_strs.size(); i++) { | ||
| int digit = numeric_strs[i] - '0'; | ||
|
|
||
| if (converted > numeric_limits<int>::max() / 10 || | ||
| (converted == numeric_limits<int>::max() / 10 && digit > 7)) { | ||
| if (is_negative) { | ||
| return numeric_limits<int>::min(); | ||
| } else { | ||
| return numeric_limits<int>::max(); | ||
| } | ||
| } | ||
|
|
||
| converted = converted * 10 + digit; | ||
| } | ||
|
|
||
|
|
||
| if (is_negative) { | ||
| return -converted; | ||
| } | ||
| return converted; | ||
| } | ||
|
|
||
| private: | ||
| bool IsNumber(char letter) { | ||
| set<char> letter_numbers = {'0', '1', '2', '3', '4', | ||
| '5','6', '7', '8', '9'}; | ||
| if (letter_numbers.contains(letter)) { | ||
| return true; | ||
| } else { | ||
| return false; | ||
| } | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| class Solution { | ||
| public: | ||
| int myAtoi(string s) { | ||
| // indexを勧めながら一文字ずつ前処理を行う | ||
| int index = 0; | ||
| while (index < s.size() && s[index] == ' ') { | ||
| index++; | ||
| } | ||
|
|
||
| bool is_negative = false; | ||
| if (index < s.size() && s[index] == '-') { | ||
| is_negative = true; | ||
| index++; | ||
| } else if (index < s.size() && s[index] == '+') { | ||
| is_negative = false; | ||
| index++; | ||
| } | ||
|
|
||
| while (index < s.size() && s[index] == '0') { | ||
| index++; | ||
| } | ||
|
|
||
| // 有効な数値を配列に入れる | ||
| vector<char> numeric_strs; | ||
| while (index < s.size() && isdigit(s[index])) { | ||
| numeric_strs.push_back(s[index]); | ||
| index++; | ||
| } | ||
|
|
||
| // intへの変換処理 桁ごとにオーバーフローしないかチェックする | ||
| int converted = 0; | ||
| for (int i = 0; i < numeric_strs.size(); i++) { | ||
| int digit = numeric_strs[i] - '0'; | ||
|
|
||
| if (converted > numeric_limits<int>::max() / 10 || | ||
| (converted == numeric_limits<int>::max() / 10 && digit > numeric_limits<int>::max() % 10)) { | ||
| if (is_negative) { | ||
| return numeric_limits<int>::min(); | ||
| } else { | ||
| return numeric_limits<int>::max(); | ||
| } | ||
| } | ||
| converted = converted * 10 + digit; | ||
| } | ||
|
|
||
| if (is_negative) { | ||
| return -converted; | ||
| } else { | ||
| return converted; | ||
| } | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| class Solution { | ||
| public: | ||
| int myAtoi(string s) { | ||
| int index = 0; | ||
| while (index < s.size() && s[index] == ' ') { | ||
| index++; | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 僕なら int index = s.find_first_not_of(' ');
if (index == string::npos) return 0;です。 |
||
|
|
||
| bool is_negative = false; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. int sign = 1;もありですね if(index >= s.size()) return 0;してしまえば、この条件式は以下では不必要です。 |
||
| if (index < s.size() && s[index] == '-') { | ||
| is_negative = true; | ||
| index++; | ||
| } else if (index < s.size() && s[index] == '+') { | ||
| is_negative = false; | ||
| index++; | ||
| } | ||
|
|
||
| while (index < s.size() && s[index] == '0') { | ||
| index++; | ||
| } | ||
|
|
||
| vector<char> numeric_strs; | ||
| while (index < s.size() && isdigit(s[index])) { | ||
| numeric_strs.push_back(s[index]); | ||
| index++; | ||
| } | ||
|
|
||
|
Comment on lines
+18
to
+27
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. このロジックいらないと思いますよ for(int i = first_index; i < s.size(); ++i) {
int digit = s[i] - '0';
// ...
}です。 |
||
| int converted = 0; | ||
| for (int i = 0; i < numeric_strs.size(); i++) { | ||
| int digit = numeric_strs[i] - '0'; | ||
|
|
||
| if (converted > numeric_limits<int>::max() / 10 || | ||
| (converted == numeric_limits<int>::max() / 10 && digit > numeric_limits<int>::max() % 10)) { | ||
| if (is_negative) { | ||
| return numeric_limits<int>::min(); | ||
| } else { | ||
| return numeric_limits<int>::max(); | ||
| } | ||
| } | ||
| converted = converted * 10 + digit; | ||
|
Comment on lines
+32
to
+40
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. もしこの書き方にするなら僕はコメントが欲しいかもしれません |
||
| } | ||
|
|
||
| if (is_negative) { | ||
| return -converted; | ||
| } else { | ||
| return converted; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is_negativeをsignにしてしまえば以下ですね。 return converted * sign;なお、convertedよりより具体的にabs(絶対値)とかもいいんじゃないでしょうか。 |
||
| } | ||
| } | ||
| }; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
long は 64 ビットデータモデルによっては 32-bit となる点に注意しましょう。
https://ja.wikipedia.org/wiki/64%E3%83%93%E3%83%83%E3%83%88#64%E3%83%93%E3%83%83%E3%83%88%E3%83%87%E3%83%BC%E3%82%BF%E3%83%A2%E3%83%87%E3%83%AB
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nodchip
ありがとうございます。このコメントをいただいたのは3回目でした🙇♂️
意識できるようしっかり叩き込もうと思います。