ページ 11

文字列をつなぐ

Posted: 2008年12月02日(火) 15:26
by macka
はじめまして今私はポインタの勉強をしていて文字列をつなぐ下記のようなプログラムを作ったのですがabc123と表示させたいのに実行するとabcbcとしか表示されません。間違いの指摘をしていただきたいです。お願いします。
#include<stdio.h>
char *ketugou(char *,char *);
int main(void)
{
	char str[10]="abc";
	char ptr[10]="123";
	printf("%s,%s\n",str ,ketugou(str,ptr));
	getchar ();
	return 0;
}
char *ketugou(char *s,char *p)
{
	int i=0;
	while('\0'!=*(s++)){
	while('\0'!=*(p+i)){
		*(p+i)=*(s+i);
		i++;
	}
	}
	*(p+i)='\0';
	return p;

Re:文字列をつなぐ

Posted: 2008年12月02日(火) 15:52
by 御津凪
現在の ketugou 関数は、 p に s を中途半端に代入しています。
具体的に処理を追うと、
・最初の while 文で '\0'!=*(s++) を比較(sは比較後次のポインタ位置へ)。真なのでループ内へ
・次の while 文で '\0'!=*(p+i) を比較。真なのでループ内へ
・*(p+i)=*(s+i);
 i は 0 なので、 p[0] = s[0] と同じ。
  ただし、s は呼ばれた時と違うポインタ位置(一つずれている)なので、s[0] は 'b' 。
・i++;し、次のループへ。
・*(p+i)=*(s+i);
 i は 1 なので、 p[1] = s[1] と同じ。(s[1] は 'c' )
・i++;し、次のループへ。
・*(p+i)=*(s+i);
 i は 2 なので、 p[2] = s[2] と同じ。(s[2] は '\0' )
・i++;し、次の判定で 偽となるため内側の while 文を抜ける。
・外側の while 文で s++ されているが、 i に変化が無いので、内側の while 文にいくことなく
 そのまま while 文を抜け、関数が終了する。
結果、返されるポインタの文字列は "bc" となる。

Re:文字列をつなぐ

Posted: 2008年12月02日(火) 15:57
by box
> 	printf("%s,%s\n",str ,ketugou(str,ptr));

ここで何を出力したいのか、正確に教えてください。
abc123と出力させたいのに、と書かれていますが、上記のprintf()の実行では、
2つの文字列をカンマで区切って出力します。
abc123と出力させることは、もともとできません。

Re:文字列をつなぐ

Posted: 2008年12月02日(火) 16:01
by Dixq (管理人)
こんな感じでどうでしょう。
連結される側のポインタst1を終端まで進め、そこから連結する側の文字列をコピーする。
コピーした文字が終端記号ならそこで終わる。
コピー先の文字列の先頭アドレスを返す

#include<stdio.h>

char *MyStrcat(char *st1, const char *st2){
    char  *p = st1;
    /* st1を終端まで進める */
    while ( *st1 != '\0' ){
        st1++;           
    }
    /* 連結作業 */
    while ( 1 ){
        /* st2をst1の終わりからつなげる */
        *st1 = *st2;
        /* つなげた文字が終端記号なら抜ける */
        if( *st1 == '\0' ){
            break;
        }
        /* ポインタを進める */
        *st1++;
        *st2++;
    }
    return p;
}

int main(void){
    char str[10]="abc";
    char ptr[10]="123";
    printf("%s,%s\n",str ,ptr);
    printf("-> %s\n",MyStrcat(str,ptr));
    getchar ();
    return 0;
}

実行結果

abc,123
-> abc123


上記の関数は以下のようにかいても同じ意味です。

char *MyStrcat(char *st1, const char *st2){
    char  *p = st1;
    while (*st1) st1++;           
    while (*st1++ = *st2++) ;     
    return p;
}
 
 

Re:文字列をつなぐ

Posted: 2008年12月02日(火) 16:15
by macka
皆さんありがとうございます わかりやすく教えていただいたおかげで理解できました

Re:文字列をつなぐ

Posted: 2008年12月02日(火) 16:30
by non
本当にもう大丈夫ですか?
管理人さんのプログラムは難しいと思うけど・・・教科書通りじゃないって気がするけど。
なにが、教科書かって・・つっこまないで。


それでは、問題です。下のプログラムは、なぜ、駄目なんでしょうか。
課題1
char *MyStrcat(char *st1, const char *st2){
    char  *p = st1;
    while (*st1++) ;           
    while (*st1++ = *st2++) ;     
    return p;
}
課題2
char *MyStrcat(char *st1, const char *st2){
    char  *p = st1;
    while (*st1) st1++;           
    while (*st2) *str++=*str++;     
    return p;
}

Re:文字列をつなぐ

Posted: 2008年12月02日(火) 16:42
by macka
どちらもループを途中で抜けてしまうからではないですか?

Re:文字列をつなぐ

Posted: 2008年12月02日(火) 16:56
by non
課題2にミスがありました。失礼しました。
課題2 

char *MyStrcat(char *st1, const char *st2){
    char  *p = st1;
    while (*st1) st1++;           
    while (*st2) *st1++=*st2++;     
    return p;
}
>途中で抜けてしまうから
回答が、簡単すぎるので、mackaさんがわかっておられるか、ちょっとはかりかねますが、
おわかりなら、OKです。

Re:文字列をつなぐ

Posted: 2008年12月02日(火) 17:03
by macka
親切にありがとうございました。