Skip to content

Conversation

hroc135
Copy link
Owner

@hroc135 hroc135 commented Apr 29, 2025


- マルチバイト文字が含まれている場合にどうなるか不安になった
- 上記コードだとマルチバイト文字の先頭バイトが ' ', '-', '+' と一緒だとおかしなことになる
- 調べたところ、マルチバイト文字は ascii と共存できるよう、先頭バイトは ascii の範囲外になるよう設計されているので、
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これは、文字コードによって違うのですが、JISコードは先頭バイトが ASCII とぶつかります。
最近は、あまり気にしなくていいのではないでしょうか。

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

最近あまり気にしなくて良くなったのはなぜですか?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JIS コードが使われることはあまりなく、十分にユニコードが使われるようになったからですね。

問題: https://leetcode.com/problems/string-to-integer-atoi/description/

### Step 1
- なんか帳尻合わせの汚いコードが出来上がった印象
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ステートマシンはだいたい大変になります。

```Go
func myAtoi(s string) int {
isNegative := false
isNumber := false
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ステートマシンを作る場合、ステートを表す enum 相当のものを使う方法もあります。

以下 C++ の記述です。

class Solution {
private:
    enum State {
        Whitespace,
        Signedness,
        Conversion,
    };
public:
    int myAtoi(string s) {
        State state = Whitespace;
        int64_t absolute = 0;
        int sign = 1;
        int index = 0;
        while (index < s.size()) {
            char ch = s[index];
            switch (state) {
                case Whitespace:
                    if (ch == ' ') {
                        ++index;
                        continue;
                    } else {
                        state = Signedness;
                    }
                    break;

                case Signedness:
                    if (ch == '+') {
                        sign = 1;
                        ++index;
                        state = Conversion;
                    } else if (ch == '-') {
                        sign = -1;
                        ++index;
                        state = Conversion;
                    } else {
                        state = Conversion;
                    }
                    break;

                case Conversion:
                    if (!isdigit(ch)) {
                        // HACK: Exit loop by setting index to s.size();
                        index = s.size();
                        continue;
                    }
                    absolute *= 10;
                    absolute += ch - '0';
                    ++index;
                    if (absolute > std::numeric_limits<int>::max()) {
                        // HACK: Exit loop by setting index to s.size();
                        index = s.size();
                        continue;
                    }
                    break;
            }
        }

        absolute *= sign;
        absolute = std::clamp<int64_t>(absolute, std::numeric_limits<int>::min(), std::numeric_limits<int>::max());
        return absolute;
    }
};

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

なるほどです。現在の状態がわかりやすいですね。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants