ページ 11

文字列について

Posted: 2006年12月05日(火) 16:43
by 困ったさん
二つの文字列s1,s2 をキーボードから入力し,それぞれの文字列の長さ(NULL 文字は含まな
い)を画面表示し,さらに文字列s1 の後ろに文字列s2 を連結して画面表示する
(ただし,文字列s1 と文字列s2 を連結したものを一度文字列s1 に格納してから
表示を行うこと.)っていうプログラムの作成が課題で出たんですけど
strlen(),strcat()等の関数が使えなくて・・・。
文字列の長さにstrlenが使えないし、文字列を連結するのにもstrcatが使えないなんて・・・(汗)
どうしたらいいんですか?

Re:文字列について

Posted: 2006年12月05日(火) 16:50
by 管理人
使えないというのは、使ってはいけないとされているんですか?

Re:文字列について

Posted: 2006年12月05日(火) 16:50
by 困ったさん
一応今回の課題では使わずにプログラムしなきゃならないみたいです。

Re:文字列について

Posted: 2006年12月05日(火) 16:57
by GPGA
関数を作ってしまうのが普通ですね。
int _strlen(const char* str)
{
	int i;
	for (i = 0; *str != '\0'; i++) {
		str++;
	}
	return i;
}

char* _strcat(char* str1, const char* str2)
{
	char* tmp = str1;
	int i;
	for (i = 0; *str1 != '\0'; i++) {
		str1++;
	}
	for (i = 0; *str2 != '\0'; i++) {
		*str1 = *str2;
		str1++;
		str2++;
	}
	*str1 = '\0';

	return tmp;
}

Re:文字列について

Posted: 2006年12月05日(火) 16:58
by box
サンプルです。
#include <stdio.h>

#define BUFLEN (512)

int main(void)
{
	char s1[BUFLEN], s2[BUFLEN];
	int len1, len2, i;
	
	printf("文字列s1:"), scanf("%s", s1);
	printf("文字列s2:"), scanf("%s", s2);
	
	for (len1 = 0; s1[len1] != '\0'; len1++)
		;
	for (len2 = 0; s2[len2] != '\0'; len2++)
		;
	printf("s1の長さ=%d, s2の長さ=%d\n", len1, len2);
	
	for (i = len1; i < len1 + len2; i++)
		s1 = s2[i-len1];
	s1 = '\0';
	printf("連結後のs1='%s'\n", s1);
	return 0;
}

Re:文字列について

Posted: 2006年12月05日(火) 17:01
by 困ったさん
すいませんboxさん。BUFLENっていうのはなんですか?

Re:文字列について

Posted: 2006年12月05日(火) 17:05
by box
BUFLENは、結合後の文字列s1を格納するのに十分な大きさを表わす値です。
サンプルでは、文字列終端の'\0'を含めて512バイトまで対応している、ということです。

Re:文字列について

Posted: 2006年12月05日(火) 17:10
by 困ったさん
なるほど・・・初めて見ました(笑)
勉強になります。

Re:文字列について

Posted: 2006年12月05日(火) 17:15
by 管理人
では、私は違った方向で・・ってやってること一緒ですが
#include <stdio.h>

int main(){
	int i=0,j=0;
	char s1[512],s2[512];
	
	printf("1つ目の文字列入力 ->\n") , scanf("%s",s1);
	printf("2つ目の文字列入力 ->\n") ,	scanf("%s",s2);

	printf("1: %s\n"  ,s1);
	printf("2: %s\n\n",s2);

	while(s1!='\0')
		i++;

	while((s1[i+j]=s2[j]) != '\0')
		j++;

	printf("連結: %s\n",s1);

	return 0;
}


文字列の長さがわからなくても、\0が出てくるまでカウントアップしてやればわかります。
最初のループの部分ですね。

次のループはs1は先ほど\0だったところをスタート地点にして、s2は最初をスタート地点にして代入をおこないます。
代入されたものが\0ではなかったらjをカウントアップして次々に代入していきます。

Re:文字列について

Posted: 2006年12月05日(火) 17:29
by keichan
>strlen(),strcat()等の関数が使えなくて・・・。
ではこれならいいですか?
#include <stdio.h>

int main()
{
    char s1[512], s2[512];
    scanf("%s", s1);
    scanf("%s", s2);
    sprintf(s1, "%s%s", s1, s2);
    printf("%s\n", s1);
    return 0;
}

Re:文字列について

Posted: 2006年12月05日(火) 18:25
by 管理人
おぉ、なるほど。

先生がさせようとしていることを賢くうまく外して見せるのも
やらしくて面白いですねw

Re:文字列について

Posted: 2006年12月05日(火) 18:35
by box
入力した文字列の長さを表示する、
という仕様をお忘れでは?

Re:文字列について

Posted: 2006年12月05日(火) 18:49
by 管理人
あぁ、長さの調査がいるんですねm(_ _)m

Re:文字列について

Posted: 2006年12月05日(火) 19:10
by 困ったさん
管理人さんへ

> char s1[512],s2[512];

もし[/url]に512みたいな具体的な数値がなかったらどうなりますか?

> printf("1つ目の文字列入力 ->\n") , scanf("%s",s1);
> printf("2つ目の文字列入力 ->\n") , scanf("%s",s2);


printf("1つ目の文字列入力 ->\n");
scanf("%s",s1);
printf("2つ目の文字列入力 ->\n");
scanf("%s",s2);

と同等の意味なんですか?どちらの書き方でもOKですか?
2つともバカみたいな質問でごめんなさい。

Re:文字列について

Posted: 2006年12月05日(火) 20:27
by 管理人
>> char s1[512],s2[512];

>もし[/url]に512みたいな具体的な数値がなかったらどうなりますか?

[512]という数字は「配列の要素数」と呼ばれ、配列の要素をいくつ作るか示すものです。
宣言の時にはいくつ生成するか決めているので、具体的な数字を書いてやらないと、
コンパイラはいくつ配列要素を作ればいいかわからず、エラーを吐き出してしまいます。

しかし、省略できる時もあります。

char s1[/url]="省略可能なkakikata..";

このように宣言と同時に格納する文字を示してやれば、いくつ用意すればいいのか
わかりますのでエラーになりません。
こうすると、全角文字が5つ、半角文字が10文字あるから、配列要素は20個必要です。
文字列は最後に終端記号である\0を入れる必要がありますから、
合計21個配列要素が必要だとわかりますね。

つまり宣言と同時に初期化しないときには、配列要素数の省略は不可。
同時に初期化するなら省略は可能ということです。

後、コンマについてですが、
①,②,③
と書けば、①から順番に③まで処理をしろといういみなので、
普通にたてに書いても同じです。
2つの値を交換する時など、1行の処理が少ない時や、
短く書きたい時によく使用します。

>2つともバカみたいな質問でごめんなさい。

全然そんなことないので、少しでも疑問があれば、何でも聞いてくださいね。

Re:文字列について

Posted: 2006年12月05日(火) 20:46
by box
> 先生がさせようとしていることを賢くうまく外して見せるのも

文字列の連結は、keichanさんがお書きになった
sprintf関数を使う方法が最良です。

標準関数のstrcatを使う場合、下手なコーディングをすると
strcatの連鎖地獄に陥ってしまいます。

しかし、sprintf関数を使えば、
sprintf(dest, "%s%s%s", src1, src2, src3);
のように、おそらく誰が見てもスッキリしたコードとなります。
コードがスッキリしている分、テストや保守が楽です。

Re:質問

Posted: 2006年12月06日(水) 14:55
by 困ったさん
いろいろと細かい所も質問できたおかげで理解が深まりました。
みなさんご指導ありがとうございました。