質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
ASCII

ASCIIは、米国規格協会(ANSI)が制定したコンピューターの情報交換のための文字コードの一つ。アルファベットや数字などを1文字当たり7ビットで表します。英数字を表示する文字コードの中で最も高い互換性を持ち、多くの通信機器に利用されています。

UTF-8

UTF-8は8ビット符号単位の文字符号化形式及び文字符号化スキームです。データ交換方式、ファイル形式としては、一般的にUTF-8が使われる傾向があります。

文字コード

文字コードとは、文字や記号をコンピュータ上で使用するために用いられるバイト表現を指します。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

2回答

2792閲覧

Swiftで改行文字をカウントすると2倍になる

kiteretsu

総合スコア57

ASCII

ASCIIは、米国規格協会(ANSI)が制定したコンピューターの情報交換のための文字コードの一つ。アルファベットや数字などを1文字当たり7ビットで表します。英数字を表示する文字コードの中で最も高い互換性を持ち、多くの通信機器に利用されています。

UTF-8

UTF-8は8ビット符号単位の文字符号化形式及び文字符号化スキームです。データ交換方式、ファイル形式としては、一般的にUTF-8が使われる傾向があります。

文字コード

文字コードとは、文字や記号をコンピュータ上で使用するために用いられるバイト表現を指します。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2018/01/08 09:51

LinuxでSwiftのコードが書いているのですが、
行数をカウントする(改行文字をカウントする)プログラムをglibcを使って書いたところ、実際の2倍の値が返ってきてしまいます。
原因がわかる方がおられましたら、ご教授いただけないでしょうか?

カウントしているファイルの文字コードはUTF-8です。
3,4ファイル試しましたが、全て綺麗に2倍でした。

###カウントしている関数

swift

1func do_cat(filePath: String) { 2 var fd: CInt 3 var buf = Array<UInt8>(repeating: 0, count: Int(BUFSIZ)) 4 var n: Int 5 var count: UInt8 = 0 6 //"10" is return code by ASCII 7 let target: UInt8 = 10 8 9 10 fd = open(filePath, O_RDONLY) 11 12 if fd < 0 { die(s: filePath) } 13 while true { 14 n = read(fd, &buf, Int(BUFSIZ)) 15 if n < 0 { die(s: filePath) } 16 for i in buf { 17 if i == target { count = count + 1 } 18 } 19 if n == 0 { 20 print(count) 21 break 22 } 23 } 24 if close(fd) < 0 { die(s: filePath) } 25} 26

なんとなくtargetに使用している"10"が原因なのかな、とは思いますが
原因がわからず、もやもやします。

"10"を指定している理由ですが、UTF-8はASCIIに含まれる文字はASCIIと同じ、と
いう記事がどこかにあったので、UInt8で10を指定しています。
また、UTF-8の改行文字を指定する方法が見つからなかったのも理由の一つです。

下記の環境を使用しています。

  • Arch Linux
  • Swift 4.0.3

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

for i in buf { ... }

だと、バッファーの全ての要素に対するチェックになってしまいます。bufは内容を0で初期化しているものの、2回目以降のreadの結果をチェックする際には「最後に読み込んだデータ以外もチェックしてしまう」ことになります。

今回2倍の行数になったのは「EOFに達してn==0になった際に、直前に読み込んだデータをもう一度チェックしているから」です。

for i in buf[0..<n] { ... }

のように読み込んだバイト数の範囲のみをチェックすべきと思います。また「EOFに達したならそもそもチェックする前にbreakする」方がよいと思います。その方が合理的ですので。


なお、こうしたことはデバッグする(つまりデバッグプリントで変数の値などを印字するなどの工夫をして調べる)ことで解決するのが普通です。ほとんどデバッグをしておられないと思いますが、誰でもプログラムを動かすためにはデバッグするものですので、それを訓練することこをを一番お勧めしたいです。

投稿2018/01/08 10:56

KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kiteretsu

2018/01/08 12:38

readの動作を勘違いしていました。読み込み中にEOFに達した段階で0が返るのではなく、その次の読み込みの時に0が返るんですね。 bufの内容をprintしてみたら、すぐにわかりました。 ちゃんとデバッグするようにします......
KSwordOfHaste

2018/01/08 14:10

あれこれデバッグしなくても仕様を正確に把握して机上で問題に気づけるのが一番ではありますが、残念ながらなかなかそうはいきませんよね・・・ 自分などはごく簡単なバグでも実際にRUNしないと気づけないことも多く、それはそれでなさけない気持ちになりますが...orz
guest

0

MacOSX + Xcode(swift) での確認なので、kiteretsuさんの環境で、そのまま動くかわかりませんがご参考まで。

swift

1func do_cat(filePath: String) { 2 3 do { 4 var dataList:[String] = [] 5 let filedata = try String(contentsOfFile:filePath, encoding:String.Encoding.utf8) 6 if !filedata.isEmpty { 7 dataList = filedata.components(separatedBy: NSCharacterSet.newlines) 8 print(dataList.count - 1) 9 } 10 } catch { 11 print (error) 12 } 13 }

私の環境では、ファイルから読み込んで文字列に格納した際、一番最後に¥nが追加されていたので、1行余分にカウントされてしまうため、表示時に-1してます。

NSCharacterSet.newlines は、改行コードを意味するようなので、こちらを使ってみては如何でしょうか。
Apple Developer Document - newlines

投稿2018/01/08 11:44

Shara

総合スコア125

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kiteretsu

2018/01/08 13:31

教えて頂きありがとうございます。 今回のコードにNSCharactorSetを入れ込むことは出来ませんでしたが、 いろいろと便利そうなので覚えておきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問