【掲示板ご利用上の注意】

 ※題名は具体的に!
 ※学校の課題の丸投げ禁止!
 ※ソースの添付は「HTML変換ツール」で字下げ!
 ※返信の引用は最小限に!
 ※環境(OSとコンパイラ)や症状は具体的に詳しく!
 ※マルチポスト(多重投稿)は慎んで!

 詳しくはこちら



 本当はこんなに大きく書きたくはないのですが、なかなか守っていただけなくて…。
 守ってくださいね。お願いします。(by管理人)

C言語ソース⇒HTML形式ツール   掲示板2こちら


管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.21113

ポインタを使って空行を削除とシステムコールでの改行の考え方
投稿者---ひか(2005/05/20 22:39:19)


毎度失礼します。
入出力時だけシステムコールを使い、標準入力からテキストを入力し空行を消すというものをやっています。
ここで、システムコールだと空行削除をポインタを使ってやらないといけないようなのですがいいのが思いつきません。
以下自分で書いてみたものです。

#include <stdlib.h>
#include <unistd.h>

main()
{
  char buf[1024], *p, *q;
  ssize_t len, len1;
  while ((len = read(STDIN_FILENO, buf, sizeof(buf))) > 0) {


    for (q = buf; q < &buf[len]; q++){
      if (*q==buf[0]=='\n'){
        buf[0] = 0;
      }
      if (*q == '\n' && *(q+1) == '\n'){
        *q = 0;
      }
    }

    p = buf;

    while ((len1 = write(STDOUT_FILENO, p, len)) >= 0 && len > len1) {
      len -= len1;
      p += len1;
    }

    if (len1 == -1) {
      exit(1);
    }
  }
  if (len == -1) {
    exit(1);
  }
  return 0;
}

また、システムコールで読み込んだものにはNULL文字が自動的に付かないようですが、改行文字\nに関しては何か特別なことはあるのでしょうか?

環境は一般的なLinuxでのC言語。
システムコールはUNIXを前提にしたものです。
ご指導よろしくお願いします。


この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:ポインタを使って空行を削除とシステムコールでの改行の考え方 21114 まきじ 2005/05/20 23:03:56
<子記事> Re:ポインタを使って空行を削除とシステムコールでの改行の考え方 21115 おでん 2005/05/20 23:21:05


No.21114

Re:ポインタを使って空行を削除とシステムコールでの改行の考え方
投稿者---まきじ(2005/05/20 23:03:56)


>if (*q==buf[0]=='\n')

if ((*q==buf[0])=='\n') と同じ事で、
これは、常に 偽 になりますよ。


この投稿にコメントする

削除パスワード

No.21115

Re:ポインタを使って空行を削除とシステムコールでの改行の考え方
投稿者---おでん(2005/05/20 23:21:05)


>また、システムコールで読み込んだものにはNULL文字が自動的に付かないようですが、
>改行文字\nに関しては何か特別なことはあるのでしょうか?

read()を使っているのは、何か意味がありますか?
・・・read()では、NULLは付きません・・・
無ければfgets()を調べれば幸せになれるかも?

あと、空行はスペースのみの行(通常空行とは言いませんが・・・)も含まれますか?
含まれる場合→
 読み込んだ行が空白文字のみで出来ているかの判定が必要です。
含まれない場合→
 読み込んだ行の先頭が改行文字なら空行です。


この投稿にコメントする

削除パスワード

No.21116

Re:ポインタを使って空行を削除とシステムコールでの改行の考え方
投稿者---ひか(2005/05/21 00:15:55)


>read()を使っているのは、何か意味がありますか?
>・・・read()では、NULLは付きません・・・
>無ければfgets()を調べれば幸せになれるかも?

課題として出されたもののため、readを使っています。

>あと、空行はスペースのみの行(通常空行とは言いませんが・・・)も含まれますか?

含みません。
そのため改行文字が二回続いた場合に片方の改行文字を消すということをしようとしました。
私のソースでは
if (*q==buf[0]=='\n')の部分でテキストの最初に改行が来た場合、
if (*q == '\n' && *(q+1) == '\n')の部分でそれ以降の場所に改行が来た場合、と処理しました。
しかし改行文字を消すという作業がよくわからなくて*q=0としています。


この投稿にコメントする

削除パスワード

No.21117

Re:ポインタを使って空行を削除とシステムコールでの改行の考え方
投稿者---かずま(2005/05/21 04:39:02)


> 課題として出されたもののため、readを使っています。

次のプログラムは動くはずですが、尋常ではない書き方をしているので、
課題の解答としては不適切だと思われます。
int main(void)
{
    char ibuf[1024], obuf[1024], *ip, *op = obuf;
    int f = 0, c, in = 0, out = sizeof obuf;

    while (in || (in = read(0, ip = ibuf, sizeof ibuf))) {
        c = *ip++,  in--;
        if (f || c != '\n') {
            out || (out = write(1, op = obuf, sizeof obuf));
            *op++ = c,  out--;
        }
        f = (c != '\n');
    }
    write(1, obuf, op - obuf);
    return 0;
}



この投稿にコメントする

削除パスワード

No.21125

Re:ポインタを使って空行を削除とシステムコールでの改行の考え方
投稿者---ひか(2005/05/21 19:41:01)


回答ありがとうございます。

>次のプログラムは動くはずですが、尋常ではない書き方をしているので、
>課題の解答としては不適切だと思われます。
それはエラー処理がされていないからということですか?

>if (f || c != '\n')
この部分のfが何の処理をしているかがわかりません。



この投稿にコメントする

削除パスワード

No.21131

Re:ポインタを使って空行を削除とシステムコールでの改行の考え方
投稿者---かずま(2005/05/22 03:23:36)


>> 次のプログラムは動くはずですが、尋常ではない書き方をしているので、
>> 課題の解答としては不適切だと思われます。
> それはエラー処理がされていないからということですか?

関数呼び出しの引数に代入式(ip = ibuf や op = obuf) を書いたり、
本来 if文で書くべきところを || 演算子で代用したりしているところを
普通の書き方だと思いますか?


>> if (f || c != '\n')
> この部分のfが何の処理をしているかがわかりません。

f は、一つ前の文字が改行('\n')でなかったことを示すフラグです。
f が 1 のとき、行の先頭でないから、どんな文字 c でも出力する。
f が 0 のとき、行の先頭ですから、'\n' 以外の文字なら出力する。
すなわち、行の先頭での '\n' の出力がなくなるので空行がなくなります。


この投稿にコメントする

削除パスワード

No.21132

Re:ポインタを使って空行を削除とシステムコールでの改行の考え方
投稿者---bin(2005/05/22 04:10:37)


>関数呼び出しの引数に代入式(ip = ibuf や op = obuf) を書いたり、
>本来 if文で書くべきところを || 演算子で代用したりしているところを
>普通の書き方だと思いますか?

でもよくやりません?そういうこと。
確かに見た目のわかりやすさは多少劣るかもしれませんが
実際そういう書き方をした方が処理が早くなったりするんですよ。
だからこういう書き方の方がある意味点数高い(?)かもしれません。
i=i+1 より i+=1 より i++ の方が処理早いのと同じ理屈です。
この辺はアセンブラをかじるとなんとなく解ってきますよ。


この投稿にコメントする

削除パスワード

No.21133

Re:ポインタを使って空行を削除とシステムコールでの改行の考え方
投稿者---YuO(2005/05/22 04:32:45)


>確かに見た目のわかりやすさは多少劣るかもしれませんが
>実際そういう書き方をした方が処理が早くなったりするんですよ。
(snip)
>i=i+1 より i+=1 より i++ の方が処理早いのと同じ理屈です。

どういう理屈なんでしょうか。
まともなコンパイラであれば,書き方の違い程度,ちゃんと吸収してくれます。

たとえば,Visual Studio 97のコンパイラでは,
# もう8年も前のコンパイラです。
i = i + 1;
と,
i += 1;
と,
i++;
はすべて同一のコードに翻訳されています。



この投稿にコメントする

削除パスワード

No.21134

Re:ポインタを使って空行を削除とシステムコールでの改行の考え方
投稿者---επιστημη(2005/05/22 08:48:42)


>確かに見た目のわかりやすさは多少劣るかもしれませんが
>実際そういう書き方をした方が処理が早くなったりするんですよ。
>...
>この辺はアセンブラをかじるとなんとなく解ってきますよ。

アセンブラをかじらないとわからないくらいの差でしかありません。




この投稿にコメントする

削除パスワード

No.21147

Re:ポインタを使って空行を削除とシステムコールでの改行の考え方
投稿者---nop(2005/05/23 10:13:57)


>実際そういう書き方をした方が処理が早くなったりするんですよ。

これは、全ての環境で実測値を取り、きちんと検証した上でのお話ですか?
もし、特定の環境下のみの実測や、
実測値すら取らずに仰っているのでしたら、
机上の空論でしかなく、お話にもなりませんよ?


>だからこういう書き方の方がある意味点数高い(?)かもしれません。

一体、何の点数ですか?
仮に、宿題や実務としての評価と言うことでしたら、
保守性や理解のし易さに欠け、高い評価が得られるとは思えません。


この投稿にコメントする

削除パスワード

No.21148

Re:ポインタを使って空行を削除とシステムコールでの改行の考え方
投稿者---επιστημη(2005/05/23 11:04:38)


>>実際そういう書き方をした方が処理が早くなったりするんですよ。
>
>これは、全ての環境で実測値を取り、きちんと検証した上でのお話ですか?

処理が早く「なったりする」という表現から、必ず早くなるという主張ではないでしょうし、全ての環境で検証しろというのは無茶なこと。

>>だからこういう書き方の方がある意味点数高い(?)かもしれません。
>...
>仮に、宿題や実務としての評価と言うことでしたら、
>保守性や理解のし易さに欠け、高い評価が得られるとは思えません。

昔のコンパイラはオプティマイズがヌルく、かなりソースに忠実な機械語を吐いていたので、その当時なら確かに(ちょびっと)早かったでしょうね。

きょうびのコンパイラは賢いから、機械語を意識したコードを書いて(ほんのちょっと)速度を稼ぐよな真似よりは、読みやすさを取るでしょう。



この投稿にコメントする

削除パスワード

No.21138

Re:ポインタを使って空行を削除とシステムコールでの改行の考え方
投稿者---ひか(2005/05/22 12:59:24)


>関数呼び出しの引数に代入式(ip = ibuf や op = obuf) を書いたり、
>本来 if文で書くべきところを || 演算子で代用したりしているところを
>普通の書き方だと思いますか?
よくこのような書き方をすることがあるので気づきませんでした。

>f は、一つ前の文字が改行('\n')でなかったことを示すフラグです。
>f が 1 のとき、行の先頭でないから、どんな文字 c でも出力する。
>f が 0 のとき、行の先頭ですから、'\n' 以外の文字なら出力する。
>すなわち、行の先頭での '\n' の出力がなくなるので空行がなくなります。
わかりやすい解説ありがとうございます。
勉強になりました。


この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧