「シンゴ」さんと同じ問題なんですが…

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

「シンゴ」さんと同じ問題なんですが…

#1

投稿記事 by idiot » 18年前

下のような問題の時にはどうすればよいでしょうか?

<問題>
実行結果が次のようになるプログラムをつくりなさい。

Please enter a statemant: This is a programming class

Total 5 words. Each word contains;
This: 4 letters.
is: 2 letters.
a: 1 letters.
programming: 11 letters.
class: 5 letters.

ただし、単語数の上限は30、一単語の最大文字数は20と仮定する。
文章入力にはgets関数を使用する。
ブラケット演算子なしでポインタだけで書く。

プログラム一部

#include <stdio.h>
#include <string.h>

#define MAX_WORD 30
#define MAX_CHAR 20

int main(void);
int get_word(char *, char (*)[MAX_CHA[/url]);
void print_word(int, char (*)[MAX_CHA[/url]);

int main(void)
{
char line[MAX_WORD*MAX_CHA[/url];
char str[MAX_WORD][MAX_CHA[/url];
int num;

printf("Please enter a statemant:");
gets(line);

num =get_word(line, str);
print_word(num,str);

return 0;
}

管理人

Re:「シンゴ」さんと同じ問題なんですが…

#2

投稿記事 by 管理人 » 18年前

シンゴさんの投稿をみていらっしゃるのでしたらkeichanさんの投稿もみていらっしゃいますか?

それでしたらkeichanさんのプログラムを少しいじれば出来ると思います。

普通に関数化したいだけですよね?

関数化するとこうなるんじゃないでしょうか。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_WORD (30)  ///< 最大単語数
#define MAX_LENGTH   (20)	  ///< 単語毎の最大文字数
#define BUFFER_SIZE  (1024)		///< 入力バッファサイズ

int get_word(char *, char (*)[MAX_LENGTH]); 
void print_word(int, char (*)[MAX_LENGTH]); 

int get_word(char buffer [MAX_LENGTH],char word[MAX_WORD][MAX_LENGTH]){
	char* token = NULL;	  ///< トークン操作用
	const char separator[/url] = " ,\t\n";	///< トークンを分割する文字達
	int token_num = 0;			///< トークン数

	if( gets(buffer) == NULL )
		exit (1);
	token = strtok(buffer, separator);
	while( token != NULL ) {
		strcpy(word[token_num++], token);
		token = strtok(NULL, separator);
	}
	return token_num;
}

void print_word(int token_num,char word[MAX_WORD][MAX_LENGTH]){
	int token_count;						///< トークンカウンタ(コンソール出力制御に使用)
	printf("\nTotal %d words. Each word contains;\n", token_num);
	for( token_count = 0; token_count < token_num; token_count++ ) {
		printf("%s: %d letters.\n", word[token_count], strlen(word[token_count]));
	}
}

int main(){
	char word[MAX_WORD][MAX_LENGTH] = {0};  ///< トークン分割後の単語保存領域
	char buffer[BUFFER_SIZE] = {0};   ///< 入力用バッファ
	int token_num = 0;			///< トークン数

	printf("Please enter a statement: ");
	token_num = get_word(buffer,word);
	print_word(token_num,word);

	return 0;
}

idiot

Re:「シンゴ」さんと同じ問題なんですが…

#3

投稿記事 by idiot » 18年前

やってもらっておいて大変失礼なんですが、自分まだ学校でトークンというものを学習していないので、できればトークンなしで教えてほしいのですが…

管理人

Re:「シンゴ」さんと同じ問題なんですが…

#4

投稿記事 by 管理人 » 18年前

strtokは、とても便利な関数です。
そんなに難しい関数じゃないのでこの機会に是非覚えてみてはいかがでしょうか?
#include <stdio.h>
#include <string.h>

int main(void){
	int i=0;//forで使うi
	char s[5][5],str[/url] = "8,6,7,9,2",*tp;

	tp = strtok( str ,"," );//読み取る文字列はstr。区切るのは「,」

	while (1){
		if ( tp != NULL ){ //最後まで読み取ってなかったら
			strcpy(s,tp);//区切られた区間の文字列をsに格納
			i++;
		}
		else//最後まで読み取られたらブレイク
			break;

		tp = strtok( NULL, "," );//「,」を区切りにして次までのトークンへのポインタを返す

	}

	for(i=0;i<5;i++)
		printf("%s\n",s);

	return 0;
}


こちらにサンプルを書いておりますので、実際にコンパイルしてみてください。

char s[5][5],str[/url] = "8,6,7,9,2",*tp;

ここでstrにこのように代入しています。

tp = strtok( str ,"," );//読み取る文字列はstr。区切るのは「,」

strtokはポインタが返るので、tpにポインタを格納します。
この文字列情報があるアドレスだと思ってください。

具体的には最初、str[0]のアドレスが入ります。

tp = strtok( NULL, "," );

次にこの処理をすると、tpから次に,があるまでの区間を文字列としてくれます。
それは次にある,が\0に変わるのです。
文字列はtpから\0までを示しますから、str[0]から次の,までが文字列となります。
つまりこの時点でtpと示すと8になります。
一回呼ぶと、tpは進みます。tpが示すアドレスは次には先ほど,があった一つ先のところに
つまりstr[2]のアドレスへ移動します。

次に

tp = strtok( NULL, "," );

を呼ぶと、その次の,までを文字列とします。を\0に変換してかえしてくれるので、
str[2]からstr[3]までを文字列としてくれます。
つまりこのとき、tpと示すと、6となるわけです。

sにはその区切られた文字が個別にはいるので、printf文でこのように表示されるわけですね。

idiot

Re:「シンゴ」さんと同じ問題なんですが…

#5

投稿記事 by idiot » 18年前

ありがとうございます。いろいろと助かりました。早速勉強してみます。

閉鎖

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