二次元配列にint型、char型の文字を格納する仕方の件について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
masechin
記事: 7
登録日時: 8年前

二次元配列にint型、char型の文字を格納する仕方の件について

#1

投稿記事 by masechin » 7年前

只今C言語を勉強している者です。fgetsで入力しておいて
その入力しておいた文字をstrtokで配列に入れる動作を作りたいと思っています。
私的にはうまくやっていると思うのですが、あまりうまく文字を格納
出来なくて困っています。最初のH,W,Nは思い通りの文字を格納することが出来たのですが
それ以降のfor文で二次元配列に文字を格納するところ、数字を格納するところが下記の
とおり入力に対し出力がうまく実行できませんでした。
どのようにすればうまく格納することができるでしょうか。
すみませんがご教授お願いします。

入力例) 出力)
3 6 7
C A B J Q B A E S B B Q
S E . . J C A E S B B Q
A E S B B Q A E S B B Q
2 2 3 2 2 2 2 2
1 3 1 6 1 1 1 1
1 4 2 5 1 1 1 1
1 2 3 1 1 1 1 1
1 6 3 5 1 1 1 1
1 3 3 4 1 1 1 1
3 1 3 6 3 3 3 3

コード:

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

#define Hikaku 4
#define max 100

int main(int argc,char *argv[])
{
	int H,W,N;
	char str[100];
	int i,j;
	int a[max][max];
	char *z[max][max];

	fgets(str,sizeof(str),stdin);

	H = atoi(strtok(str," "));
	W = atoi(strtok(NULL," "));
	N = atoi(strtok(NULL," "));

	for(i = 0;i<H;i++)
	{
		fgets(str,sizeof(str),stdin);
			for(j = 0;j<W;j++)
			{
				if(j == 0)
				{
				z[i][j] = strtok(str," ");
				j++;
				}
				z[i][j] = strtok(NULL," ");
			}
	}

	for(i = 0;i < H;i++)
	{
		for(j = 0;j<W;j++)
		{
			printf("%s ",z[i][j]);
		}
	}
	for(i = 0;i<N;i++)
	{
		fgets(str,sizeof(str),stdin);
		for(j = 0;j<Hikaku;j++)
		{
			if(j == 0)
			{
				a[i][j] = atoi(strtok(str," "));
				j++;
			}
			a[i][j] = atoi(strtok(str," "));
		}
	}

	for(i = 0;i<N;i++)
	{
		for(j = 0;j<Hikaku;j++)
		{
			printf("%d",a[i][j]);
		}
			printf("\n");
	}
}


box
記事: 2002
登録日時: 13年前

Re: 二次元配列にint型、char型の文字を格納する仕方の件について

#2

投稿記事 by box » 7年前

ご自分の投稿を確認してみてください。どこからどこまでが入力で、どこからどこまでが出力なのか、
全くわかりません。

こういう内容を言いたかったのですか?

コード:

入力               出力
3 6 7
C A B J Q B        A E S B B Q
S E . . J C        A E S B B Q
A E S B B Q        A E S B B Q
2 2 3 2            2 2 2 2
1 3 1 6            1 1 1 1
1 4 2 5            1 1 1 1
1 2 3 1            1 1 1 1
1 6 3 5            1 1 1 1
1 3 3 4            1 1 1 1
3 1 3 6            3 3 3 3
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

masechin
記事: 7
登録日時: 8年前

Re: 二次元配列にint型、char型の文字を格納する仕方の件について

#3

投稿記事 by masechin » 7年前

すみません。
入力と出力にスペースを入れないままで投稿してしまいました。
入力と出力ですがboxさんの通りで合っています

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 二次元配列にint型、char型の文字を格納する仕方の件について

#4

投稿記事 by みけCAT » 7年前

●前半
strtokは文字列をコピーせず、渡されたバッファを直接書き換え、その中へのポインタを返すので、その後バッファを書き換えると当然返されたポインタに指されている内容も変わります。
後で使うには、バッファを確保して文字列をコピーするようにするか、1文字でいいのならそもそもタイトル通りポインタではなく「char型の文字」の配列にして直接文字を格納するといいでしょう。

●後半
ループ内2番目のstrtokも第一引数がstrなので、strの最初のトークンしか取得されません。ここをNULLに変えるといいでしょう。

●共通
WやHikakuが1のとき、このままでは無効なデータの読み取り操作が行われてしまいます。
ループ内のj++;は消し、jの値によって第一引数がstrのstrtokと第一引数がNULLのstrtokを1回のループに付きどちらか1個のみを実行するようにするといいでしょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

masechin
記事: 7
登録日時: 8年前

Re: 二次元配列にint型、char型の文字を格納する仕方の件について

#5

投稿記事 by masechin » 7年前

みけCATさんありがとうございました。strtokはメモリのポインタを渡すという
ことは分かりました。コード上に表してみましたが、私のstrtok関数の認識が
甘いせいかエラーが出てしまいました。度々申し訳ませんがコード上に表すためには
どのように書けば¥よろしいでしょうか。

変更点)

コード:

	int H,W,N;
	char str[max];
	int i,j;
	int a[max][max];
	char* z[max][max];

	fgets(str[100],sizeof(str[100]),stdin);

	H = atoi(strtok(str," "));
	W = atoi(strtok(NULL," "));
	N = atoi(strtok(NULL," "));

	for(i = 0;i<H;i++)
	{
		fgets(str[i],sizeof(str[i]),stdin);
			for(j = 0;j<W;j++)
			{
				if(j == 0)
				{
				z[i][j] = strtok(str[i]," ");
				j++;
				}
				z[i][j] = strtok(NULL," ");
			}
	}


アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 二次元配列にint型、char型の文字を格納する仕方の件について

#6

投稿記事 by みけCAT » 7年前

masechin さんが書きました:strtokはメモリのポインタを渡すという
ことは分かりました。
じゃあどうして正しくポインタを渡していたのにわざわざポインタじゃないものを渡すように書き換えたのですか?
しかも、ついでにどうしてstrtokと関係ないところまでポインタを渡すべき所にポインタじゃないものを渡して、ついでに範囲外へのアクセスで未定義動作を発生させるようにしたのですか?
masechin さんが書きました:コード上に表すためには
どのように書けば¥よろしいでしょうか。
例えば文字を格納するなら文字を取得して格納するように書けばいいでしょう。

コード:

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

#define Hikaku 4
#define max 100

int main(int argc,char *argv[])
{
	int H,W,N;
	char str[100];
	int i,j;
	int a[max][max];
	char z[max][max]; /* ポインタではなく文字の配列にする */

	fgets(str,sizeof(str),stdin);

	H = atoi(strtok(str," "));
	W = atoi(strtok(NULL," "));
	N = atoi(strtok(NULL," "));

	for(i = 0;i<H;i++)
	{
		fgets(str,sizeof(str),stdin);
		/* インデントを整える */
		for(j = 0;j<W;j++)
		{
			if(j == 0)
			{
				/* インデントを整える */
				z[i][j] = *strtok(str," "); /* 返ってきたポインタをデリファレンスして代入 */
				/* ※本当はデリファレンスする前にNULLでないことを確かめるべきだが、省略 */
				/* ここではjを加算しない */
			} else { /* jが0でない時だけ次の処理を行うようにする */
				z[i][j] = *strtok(NULL," "); /* 返ってきたポインタをデリファレンスして代入 */
				/* ※本当はデリファレンスする前にNULLでないことを確かめるべきだが、省略 */
			}
		}
	}

	for(i = 0;i < H;i++)
	{
		for(j = 0;j<W;j++)
		{
			printf("%c ",z[i][j]); /* 文字を扱うようにしたので、%sではなく%cを使う */
		}
		printf("\n"); /* 1行ごとに改行するようにする */
	}
	/* 省略 */
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

かずま

Re: 二次元配列にint型、char型の文字を格納する仕方の件について

#7

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

strtok を使わないといけないのですか?
scanf ではダメなんでしょうか?

コード:

#include <stdio.h>
 
#define Hikaku 4
#define max 100
 
int main(void)
{
    int H, W, N, i, j, a[max][max];
    char z[max][max];
 
    scanf("%d%d%d", &H, &W, &N);

    for (i = 0; i < H; i++)
        for (j = 0; j < W; j++)
            scanf(" %c", &z[i][j]);

    for (i = 0; i < H; i++) {
        for (j = 0; j < W; j++)
            printf("%c ",z[i][j]);
        putchar('\n');
    }
    for (i = 0; i < N; i++)
        for (j = 0; j < Hikaku; j++)
            scanf("%d", &a[i][j]);
 
    for (i = 0; i < N; i++) {
        for (j = 0; j < Hikaku; j++)
            printf("%d ", a[i][j]);
        putchar('\n');
    }
    return 0;
}
scanf の " %c" が注意を要するところです。

閉鎖

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