c言語のポインタについて質問です。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
akatuki

c言語のポインタについて質問です。

#1

投稿記事 by akatuki » 9年前

この問題の解答を教えてください(できれば解説も)よろしくお願いします。

①文字列のポインタを引数とし、その文字列を最後の文字から初めまで逆順に表示する関数print_rev を作成せよ。

②2 個の文字列のポインタを引数として、それらを比較して、最初に異なる位置(0以上の整数)を返す関数str_diff_point を作成せよ。ただし、それらが、一致したときは-1 を返すこととする。

③2 個の文字列のポインタを引数とし、第2の文字列が第1のポインタの指す文字列に含まれているときは最初のポインタを返す関数strsearch を作成せよ。ただし、見つからないときはNULL を返すこととする。

アバター
ookami
記事: 214
登録日時: 9年前
住所: 東京都

Re: c言語のポインタについて質問です。

#2

投稿記事 by ookami » 9年前

①のみです!お役に立てば幸いです←
l;print_rev(char*s){s+=l=strlen(s);while(l--)putchar(*--s);}
最後に編集したユーザー ookami on 2011年5月27日(金) 12:44 [ 編集 1 回目 ]

アバター
バグ
記事: 130
登録日時: 9年前
住所: 愛媛県
連絡を取る:

Re: c言語のポインタについて質問です。

#3

投稿記事 by バグ » 9年前

じゃあ、私は③のみ・・・

コード:

char*strsearch(char*a,char*b){return strstr(a,b);}

jaken

Re: c言語のポインタについて質問です。

#4

投稿記事 by jaken » 9年前

一応ライブラリ等を使わない形で

コード:



// ①文字列のポインタを引数とし、その文字列を最後の文字から初めまで逆順に表示する関数print_rev を作成せよ。
void print_rev(char* str)
{
    // 最終地点の検索
    int i;
    for(i = 0 ; i < 99 ; i++){
        if(*(str+i) == '\0')break;
    }
    // 逆に表示
    for(int n = i ; n >= 0 ; n--){
        printf("%c", *(str+n));
    }
    printf("\n");
}

//②2 個の文字列のポインタを引数として、それらを比較して、最初に異なる位置(0以上の整数を返す
//関数str_diff_point を作成せよ。ただし、それらが、一致したときは-1 を返すこととする。
int str_diff_point(char* s1, char* s2)
{
    int ret = 0;
    for(;;){
        if(*(s1+ret) == '\0' && *(s2+ret) == '\0')break;
        if(*(s1+ret) == '\0' || *(s2+ret) == '\0')return ret;
        
        if(*(s1+ret) == *(s2+ret))ret++;
        else return ret;
    }
    return -1;
}
//③2 個の文字列のポインタを引数とし、第2の文字列が第1のポインタの指す文字列に含まれているときは最初のポインタを返す
//関数strsearch を作成せよ。ただし、見つからないときはNULL を返すこととする。
char* strsearch(char* s1, char* s2)
{
    // s1の中にs2があるか検索
    for(int i = 0 ; *(s1+i) != '\0' ; i++){
        if(*(s1+i) == *(s2+0)){
            int j;
            for(j = 0 ; *(s1+i+j) == *(s2+j) ; j++){
                if(*(s1+i+j) == '\0')return NULL;
            }
            if(*(s2+j) == '\0')return (s1+i);
        }
    }
    
    return NULL;
}


アバター
bitter_fox
記事: 607
登録日時: 9年前
住所: 大阪府

Re: c言語のポインタについて質問です。

#5

投稿記事 by bitter_fox » 9年前

①です、若干使いにくいです。

コード:

print_rev(char*s){for(s+=strlen(s);*--s;putchar(*s));}
ポインタを文字列の末尾まで進めてそこからヌル文字が出てくるまで一文字ずつ出力します。

コード:

// 確保及び呼び出し。
main()
{
	char *s = (char*)calloc(257, sizeof(char))+1;
	scanf("%255s", s);
	print_rev(s);
}

かずま

Re: c言語のポインタについて質問です。

#6

投稿記事 by かずま » 9年前

bitter_fox さんが書きました:

コード:

    print_rev(char*s){for(s+=strlen(s);*--s;putchar(*s));}
ポインタを文字列の末尾まで進めてそこからヌル文字が出てくるまで一文字ずつ出力します。
先頭文字のひとつ前を参照してはいけませんし、そこに '\0' があるとも限りません。

コード:

print_rev(char*s){*s?print_rev(s+1),putchar(*s):0;}
これだと、グローバル変数も strlen() も使いません。

かずま

Re: c言語のポインタについて質問です。

#7

投稿記事 by かずま » 9年前

かずま さんが書きました:先頭文字のひとつ前を参照してはいけませんし、そこに '\0' があるとも限りません。
よく見ていなくて、すみませんでした。calloc で余分に領域を確保しているんですね。

maru
記事: 150
登録日時: 9年前

Re: c言語のポインタについて質問です。

#8

投稿記事 by maru » 9年前

かずま さんが書きました:
かずま さんが書きました:先頭文字のひとつ前を参照してはいけませんし、そこに '\0' があるとも限りません。
よく見ていなくて、すみませんでした。calloc で余分に領域を確保しているんですね。
正しいご指摘だと思いますよ。関数の仕様にはそんな前提条件は書かれていませんからね。
いくら使用例でcalloc で余分に領域を確保していても、仕様は満足しません。
かずま さんが書きました:
bitter_fox さんが書きました:

コード:

print_rev(char*s){*s?print_rev(s+1),putchar(*s):0;}
これだと、グローバル変数も strlen() も使いません。
print_rev関数の型はintでしょうか?省略せずに書いた方がよいと思います。

アバター
ookami
記事: 214
登録日時: 9年前
住所: 東京都

Re: c言語のポインタについて質問です。

#9

投稿記事 by ookami » 9年前

l;print_rev(char*s){s+=l=strlen(s);while(l--)putchar(*--s);} // ookami 60byte
print_rev(char*s){for(s+=strlen(s);*--s;putchar(*s));} // bitter_foxさん 54byte (難あり)
print_rev(char*s){*s?print_rev(s+1),putchar(*s):0;} // かずまさん 51byte

今のところ、かずまさんのコードが一番短いですね!
再帰や三項演算子をフツーに使ってきてるあたり、手馴れた感が...w

maru
記事: 150
登録日時: 9年前

Re: c言語のポインタについて質問です。

#10

投稿記事 by maru » 9年前

ookami さんが書きました:l;print_rev(char*s){s+=l=strlen(s);while(l--)putchar(*--s);} // ookami 60byte
print_rev(char*s){for(s+=strlen(s);*--s;putchar(*s));} // bitter_foxさん 54byte (難あり)
print_rev(char*s){*s?print_rev(s+1),putchar(*s):0;} // かずまさん 51byte

今のところ、かずまさんのコードが一番短いですね!
再帰や三項演算子をフツーに使ってきてるあたり、手馴れた感が...w
短けりゃいいってもんではないでしょう。可読性のほうが重要です。
その点ではookamiさんのコードのほうが好ましいと考えます。(変数 l が関数ローカルでないのがいただけませんが。)
文字列処理で1文字につき1回再帰呼び出しを使うのはどうなんでしょうか。再帰構造は確かにスマートですが、コストがかかります。そのことをわかって使うのならばいいでしょうが、知らずに使うと痛い目にあいます。

ISLe
記事: 2646
登録日時: 9年前
連絡を取る:

Re: c言語のポインタについて質問です。

#11

投稿記事 by ISLe » 9年前

難読コードは丸投げ連投をこらしめるためじゃないんですかね。
#この投稿も無粋だと思いましたが。

maru
記事: 150
登録日時: 9年前

Re: c言語のポインタについて質問です。

#12

投稿記事 by maru » 9年前

ISLe さんが書きました:難読コードは丸投げ連投をこらしめるためじゃないんですかね。
私もそんなところだろうと思っているんですが、そのコードがいかにも優れているかのようなコメントには賛成いたしかねます。初心者がこれを見てこんなコードがいいんだと思われても困りますからね。

たいちう
記事: 418
登録日時: 9年前

Re: c言語のポインタについて質問です。

#13

投稿記事 by たいちう » 9年前

> その点ではookamiさんのコードのほうが好ましいと考えます。

maruさんはookamiさんのコードの可読性が良いとお考えなのですね。
初心者がこれを見てこんなコードがいいんだと思っても構わないと。

かずま

Re: c言語のポインタについて質問です。

#14

投稿記事 by かずま » 9年前

No.4 の jaken さんのプログラムについては誰も何も言わないのでしょうか?

(1) なぜか文字数に 99 の制限がある。
  逆順文字列の前後に勝手に '\0' と '\n' をつける。

(2) とりあえず仕様どおりには動きそうですが、無駄が多い。

(3) strsearch("abc", "bc") が NULL を返す。

真面目に書けばこんなところでしょうか。

コード:

 
void print_rev(const char *s)
{
    int i = 0;
    while (s[i] != '\0') i++;
    while (--i >= 0) putchar(s[i]);
}

int str_diff_point(const char *s1, const char *s2)
{
    int i;
    for (i = 0; s1[i] == s2[i]; i++)
        if (s1[i] == '\0') return -1;
    return i;
}

char *strsearch(const char *s1, const char*s2)
{
    do {
        const char *p1 = s1, *p2 = s2;
        do {
            if (*p2 == '\0') return (char *)s1;
        } while (*p1++ == *p2++);
    } while (*s1++);
    return NULL;
}

かずま

Re: c言語のポインタについて質問です。

#15

投稿記事 by かずま » 9年前

かずま さんが書きました:

コード:

    while (--i >= 0) putchar(s[i]);
これはバグです。次のように訂正します。

コード:

    while (i-- > 0) putchar(s[i]);

かずま

Re: c言語のポインタについて質問です。

#16

投稿記事 by かずま » 9年前

かずま さんが書きました:これはバグです。次のように訂正します。
すみません。これ、勘違いです。
unsigned int i; だったら、前者はバグですが、int i; なので、どちらでもかまいません。
int i; の代わりにポインタを使った場合は、そのポインタが元の文字列の先頭より
前を指してはいけませんから、while の中にデクリメントを書くことはできません。

コード:

void print_rev(const char *s)
{
    const char *p = s;
    while (*p != '\0') p++;
    while (p > s) putchar(*--p);
}

アバター
ookami
記事: 214
登録日時: 9年前
住所: 東京都

Re: c言語のポインタについて質問です。

#17

投稿記事 by ookami » 9年前

どうもすいません、ookamiです。
コードゴルフを演出して余計な刺激を生んでしまい、申し訳ないです。

「こらしめる」というほど立派なことは考えていませんでしたが、
フォーラムルールにも「丸投げはNG」とあるので、
「直球で模範解答を返しちゃいけないだろうなぁ」くらいには思っていました。
それで、思いつき的にコードゴルフを始めてしまいました。すいません。

「可読性の方が重要」かどうかは、場合によりけりかと思いますし、
もちろん、最初に私が投稿したコードも「読みやすい」とは思っていません。
バグさん・bitter_foxさん・jakenさん・かずまさんのコードについても、特に批評を書くつもりはないです。


質問者のakatukiさんからの返事がまだですが、
丸投げが公然と認められている掲示板もありますから、
もうそちらで解決しているかもしれませんし、
私は、このトピックは「この辺でおひらき」でもいいかなぁと思っています。

ただ、「真面目に書くなら」といった流れもありますので、
そこは続けてもいいかもしれませんね?

閉鎖

“C言語何でも質問掲示板” へ戻る