strtok

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

strtok

#1

投稿記事 by Haru » 17年前

いつもお世話になってます。Haruです。Strtokでスペースを区切り文字とし、文字列を分解する作業をしているのですが、スペースのみで入力した場合と、文字列の最後にスペースを入力した場合に、スペースを読み込んでしまうんですが、読み込まないようにするにはどうすればよいのでしょうか?私が考えている原因としては、上の二つの場合だと、スペースがNULLにかえってない(?)からだと思うのですが・・・。良い対処法を教えてください。お願いします。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

int main(void)
{
	int i,c = 0;
	int argc;
	int sentou = 0;
	char *argv[256];
	char *tp;
	char str[256];

	while((str[c++] = getchar()) != '\n');  /* 改行まで読み込み */
	puts(str);

	tp = strtok(str," ");  	/*  文字列strをスペースごとの字句(トークン)に分ける。一度目は分解対象の文字列を指定 */
	i = 0;

	printf("[%d]  =  [%s] \n",i,tp);               /* i = 回数 tP = スペースで分解した文字列strの1番目 */

	i = 1;                                         /* 0は既に表示しているので1から */
	
	while(tp != NULL)                              /*  tp = NULLでなければループ  */
	{
		tp = strtok(NULL," ");                 /* 2度目以降はNULLを指定 */
 
		if((tp != NULL) && (tp != " "))        /* もしtp = NULLでなければ  */

		{
			printf("[%d]  =  [%s] \n",i,tp);
			i++;
        	}
	}
	printf(" %d \n",i);
	return 0;
}

バグ

Re:strtok

#2

投稿記事 by バグ » 17年前

このソースでも駄目ですか?
#include <stdio.h>
#include <string.h>

int main(void)
{
	char string[256];
	char* split = " ";
	char* token;

	strcpy(string, "I Like Programing");
	printf("%s\n", string);

	token = strtok(string, split);
	while (token != NULL)
	{
		printf("%s\n", token);
		token = strtok(NULL, split);
	}

	return 0;
}

Mist

Re:strtok

#3

投稿記事 by Mist » 17年前

> スペースがNULLにかえってない(?)からだと思うのですが・・・。
思うだけじゃなくてデバッグで確認して欲しいところですが。
(tpの値を出力すればすぐにわかること)

修正したほうがいいところ
1.str配列は'\0'で初期化すべき
  strtokは文字列終端を\0で判断するから
  今のプログラムだと\nより後ろは不定値
2.区切り文字の判断には\nを追加しておいたほうがいい
  文字列の最後が\nになるから(\nもひとつのトークンとしてみなすのであれば別ですが)
3.(tp != " ") はたぶん間違ってる
  tpが指す文字列の先頭が空白でないかをチェックしたいのなら
  (*tp != ' ')
提示プログラムを動作確認出来たらまた回答します。

Haru

Re:strtok

#4

投稿記事 by Haru » 17年前

>バグさん

そのソースコードでは、うまくできます!
キーボードで自由に文字列を入力させたときにスペースがはいっちゃうんですよ(^^;

>Mistさん

>> スペースがNULLにかえってない(?)からだと思うのですが・・・。
>思うだけじゃなくてデバッグで確認して欲しいところですが。
>(tpの値を出力すればすぐにわかること)

失礼しました。一応デバッグをして確認はしたのですが、自信がないものでつい、「~と思う」
と言ってしまいました。
Mistさんの修正した方が良いところを注意して修正したいと思います!

バグ

Re:strtok

#5

投稿記事 by バグ » 17年前

その文字は本当にスペースですか?改行文字ではありませんか?

Haru

Re:strtok

#6

投稿記事 by Haru » 17年前

>バグさん
すいません。改行でした。
printf("DEBUG:%s,tp); としてたので、てっきりスペースだと思い込んでました。
申し訳ないです。。

Mist

Re:strtok

#7

投稿記事 by Mist » 17年前

それならば、私の指摘の1と2で直るでしょう。
スタックな文字配列変数は初期化する癖つけておいたほうがいいと思います。

Mist

Re:strtok

#8

投稿記事 by Mist » 17年前

私が作った修正ソースです。
参考までにどうぞ。(環境Xp + VC++2008EE)
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

int main(void)
{
	int i,c = 0;
//	int argc;
//	int sentou = 0;
//	char *argv[256];
	char *tp;
	char str[256];

	memset(str, 0, sizeof(str));	// *-*

	while((str[c++] = getchar()) != '\n');  /* 改行まで読み込み */
	puts(str);

	tp = strtok(str," \n");  		// *-* /*  文字列strをスペースごとの字句(トークン)に分ける。一度目は分解対象の文字列を指定 */
	i = 0;

	if (tp != NULL) {
		printf("[%d]  =  [%s] \n",i,tp);               /* i = 回数 tP = スペースで分解した文字列strの1番目 */

		i = 1;                                         /* 0は既に表示しているので1から */
	
		while(tp != NULL)                              /*  tp = NULLでなければループ  */
		{
			tp = strtok(NULL," \n");    // *-*         /* 2度目以降はNULLを指定 */
 
			if(tp != NULL)				// *-*		/* もしtp = NULLでなければ  */
			{
				printf("[%d]  =  [%s] \n",i,tp);
				i++;
			}
		}
	}

	printf(" %d \n",i);

//	system("PAUSE");

	return 0;
}

Haru

Re:strtok

#9

投稿記事 by Haru » 17年前

>Mistさん
いつもありがとうございます!おかげでできるようになりました!!
文字配列変数を初期化するのも勉強になりました!

閉鎖

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