はじめての親子ハイキングに挑戦!! >>

はじめまして。C言語の超入門者です。現在、基礎的な事を独学中なのですが、以下(10)(11)の部分の解釈で行き詰まってしまいました。

(1)#include <stdio.h>
(2)
(3)main()
(4){
(5)int x,y;
(6)int a[2][4]={
(7){1,2,3,4},
(8){5,6,7,8}
(9)};
(10)for(x=0;x<2;x++){
(11)for(y=0;y<4;y++)
(12)printf("a[%d][%d]=%d ",x,y,a[x][y]);
(13)printf("\n");
(14)}
(15)}

(6)は、int a[2][4]・・・y方向に2列、x方向に4列
↑■■■■■■■
↑■5■6■7■8■
Y ■■■■■■■
方■1■2■3■4■
向■■■■■■■
   X方向→→
なので
(10)行目での条件を x<4
(11)行目での条件を y<2
とすると結果が正しく出ず、

(10)行目での条件を x<2
(11)行目での条件を y<4
と値を逆転させると正しく表示されるのは何故でしょうか?

(6)int a[2][4]は、x方向は2列 , y方向は4列 と逆に考えたほうが正解なのでしょうか?

超初心者でも分かる簡潔かつ明快な回答を宜しくお願い致します。

このQ&Aに関連する最新のQ&A

A 回答 (6件)

どうもかゆいところに手が届いてなさそうなので補足します。



> (10)行目での条件を x<4
> (11)行目での条件を y<2
> とすると結果が正しく出ず、
>
> (10)行目での条件を x<2
> (11)行目での条件を y<4
> と値を逆転させると正しく表示されるのは何故でしょうか?

あなたの疑問に対する明快な答えは、
「あなたの頭の中の (x, y) とプログラムの (x, y) が食い違って(入れ替わって)いるためです。」
つまり、あなたがyだと思っているのはプログラム上のxに当たり、xだと思っているのが
yに当たるるので、値の範囲もxが 0,1 、yは 0,1,2,3 で正常に表示されるのです。

「xは横方向、yは縦方向」
にこだわるなら、ANo.5のように、プログラムのxとyを入れ替え、頭の中にある
(x, y) に合わせるのが最も良い解決法でしょう。
もちろん、a[y][x]というアクセスの仕方になります。

無理やり
 int a[4][2] = {
  { 1, 5 },
  { 2, 6 },
  { 3, 7 },
  { 4, 8 }
 };
 for ( y = 0 ; y < 2 ; y++ ){
  for ( x = 0 ; x < 4 ; x++ )
   printf( "a[%d][%d]=%d ", x, y, a[x][y] );
  printf( "\n" );
 }
とできなくはないですが、明らかに配列への格納の順番が不自然ですよね?
ですのでC言語の世界では、
a[y][x]
とするのが普通だと覚えて下さい。

なお、蛇足ながら頭にイメージするのは

↑■■■■■■■
↑■5■6■7■8■
Y ■■■■■■■
方■1■2■3■4■
向■■■■■■■
   X方向→→

ではなく、

   X方向→→
Y ■■■■■■■
方■1■2■3■4■
向■■■■■■■
↓■5■6■7■8■
↓■■■■■■■

とした方がいいでしょうね。
Y方向は改行によって1進むので。

この回答への補足

fatbowlerさんはじめ、有識者のご意見を再度お聞きしたくて、新たに質問させて頂きます。

様々なご回答を頂きながら、今更ながら気付いたのですが、for文(2重ループ)に対しての理解も不十分だったようです。
fatbowlerさんの投稿を拝見した後、参考書および有識者のWEBサイトを見て回ったのですが、今回の2重ループは以下のような捉え方をすればいいのかな?と半信半疑の状態ですので、ご指南の程、宜しくお願い致します。
---------------------------------------------------------------
【今回の質問箇所】
(10)for(x=0;x<2;x++){
(11)for(y=0;y<4;y++)
---------------------------------------------------------------
■現在の2重ループ理解状況■

【プロセス1】
★x = 0 の状態で
y=0(結果:a[0][0] = 1)
y=1(結果:a[1][0] = 2)
y=2(結果:a[2][0] = 3)
y=3(結果:a[3][0] = 4)
以上yへの代入を実行しプロセス2へ
---------------------------------------------------------------
【プロセス2】
★x = 1 の状態で
y=0⇒a[0][1] = 5
y=1⇒a[1][1] = 6
y=2⇒a[2][1] = 7
y=3⇒a[3][1] = 8
以上yへの代入を実行し終了
---------------------------------------------------------------
【イメージ】
■■■■■
■4■■8■y[3]
■■■■■
■3■■7■y[2]
■■■■■
■2■■6■y[1]
■■■■■
■1■■5■y[0]
■■■■■
x[0] x[1]
---------------------------------------------------------------
上記内容で正しければ、今回の疑問は皆様のご協力で無事解決となるのですが。どうぞ、宜しくお願い致します。

補足日時:2007/07/15 06:33
    • good
    • 0
この回答へのお礼

fatbowlerさん、ご回答有難うございます。
正に私が悩んでいた核心を突いて頂き有難うございます。
ご説明頂いた内容をよく噛み砕いて考え直したいと思います。
また、どうしても分からない時にはご回答宜しくお願い致します。

お礼日時:2007/07/15 01:25

★回答者 No.2 です。


 ちょっと質問の解釈を間違いました。
 
>↑■■■■■■■
>↑■5■6■7■8■
>Y ■■■■■■■
>方■1■2■3■4■
>向■■■■■■■
>   X方向→→
 を
>int a[2][4]={
> { 1, 2, 3, 4 },
> { 5, 6, 7, 8 },
>};
 というデータにして
 [1][2][3][4]
 [5][6][7][8]
 と表示したいのなら回答者 No.3、No.4 さんので正しいです。
>for ( x = 0 ; x < 2 ; x++ ){
> for ( y = 0 ; y < 4 ; y++ )
>  printf( "a[%d][%d]=%d ", x, y, a[x][y] );
> printf( "\n" );
>}
 ↑
 これは変数の x、y の意味が逆ですね。だから
 ↓
 for ( y = 0 ; y < 2 ; y++ ){
  for ( x = 0 ; x < 4 ; x++ )
   printf( "a[%d][%d]=%d ", y, x, a[y][x] );
  printf( "\n" );
 }
 と x、y の変数名を入れ替えれば良さそうです。つまり意味を。
>と値を逆転させると正しく表示されるのは何故でしょうか?
 ↑
 値を逆転させると正しく表示されますか?
 変数名を入れ替えれば上手くいきますけど。
 
 内側のループに x(横方向)を
 外側のループに y(縦方向)にします。
 ※上手く説明できなくて済みませんでした。
・以上。
    • good
    • 0
この回答へのお礼

super-dogさん、Oh-Orangeさん、SRitchieさん、ymmasayanさん、早速のご回答有難うございました。
皆様のご解説を見て、60分考えてみました。

しかし、(10)行目 x<□ および (11)行目 y<□ に入る値がどうしても
(6)int a[2][4]={ からx<4 および (11)行目 y<2 ではないかと思ってしまうのです。

また、
ymmasayanさんのご説明で
>内側のyのループが早く回り(4回)、外側のxのループが2回回ります。
とありましたが、xとyに対する処理は同時に行われている訳ではないのですか?

Oh-Orangeさんから

BASIC 出身者ですか? と質問されましたが、
私はプログラムのプの字をかじり始めたばかりの者です。

>値を逆転させると正しく表示されますか?
>変数名を入れ替えれば上手くいきますけど。
ともご指摘がありましたが、
-------------------------------------------
私的な『正しく表示される』の意味

(10)for(x=0;x<2;x++){
(11)for(y=0;y<4;y++) でコンパイル後

a[0][0]=1 a[0][1]=2 a[0][2]=3 a[0][3]=4
a[1][0]=5 a[1][1]=6 a[1][2]=7 a[1][3]=8
-------------------------------------------
私的な『結果が正しく出ず』の意味

(10)for(x=0;x<4;x++){
(11)for(y=0;y<2;y++) でコンパイル後

a[0][0]=1 a[0][1]=2
a[1][0]=5 a[1][1]=6
a[2][0]=6618672 a[2][1]=4226262
a[3][2]=6693692 a[3][1]=0
-------------------------------------------
となることから、冒頭質問のように書きました。

本当に超初心者なので、皆様のご説明を理解できず申し訳ありません。

お礼日時:2007/07/15 01:13

↑■■■■■■■


↑■5■6■7■8■
Y ■■■■■■■
方■1■2■3■4■
向■■■■■■■
   X方向→→
ではなくて

↑■■■■■■■
↑■5■6■7■8■
前■■■■■■■
変■1■2■3■4■
数■■■■■■■
   後変数→→

です。
(10)for(x=0;x<2;x++){
(11)for(y=0;y<4;y++)
(12)printf("a[%d][%d]=%d ",x,y,a[x][y]);

から、内側のyのループが早く回り(4回)、外側のxのループが2回回ります。
したがって
1234
5678
と出力されます。
(10)と(11)をひっくり返すことはできません。
    • good
    • 0
この回答へのお礼

ご回答有難うございました。

失礼ですが、ANo.6 fatbowlerさんの回答下部に新たな質問を致しておりますので、ご指摘の程宜しくお願い致します。

お礼日時:2007/07/15 06:44

No.1の方の回答で正解ですが、


こう書いた方が分かりやすいかな?

for ( y = 0 ; y < 2 ; y++ ){ /* 行のループ */
for ( x = 0 ; x < 4 ; x++ ){ /* カラムのループ */



    • good
    • 0
この回答へのお礼

ご回答有難うございました。

失礼ですが、ANo.6 fatbowlerさんの回答下部に新たな質問を致しておりますので、ご指摘の程宜しくお願い致します。

お礼日時:2007/07/15 06:49

★二次元配列について


・int a[2][4] という場合は
 a[0][0]
 a[0][1]
 a[0][2]
 a[0][3]
 
 a[1][0]
 a[1][1]
 a[1][2]
 a[1][3]
 
 という順でメモリ内に確保されます。
 つまり a[縦方向][横方向] と考えるべきです。
>(6)int a[2][4]は、x方向は2列 , y方向は4列 と逆に考えたほうが正解なのでしょうか?
 ↑
 int a[4][2] なら縦4行×横2列という感じなります。
 なので x、y の数を入れ替えると上手く表示されただけです。
・質問者さんは BASIC 出身者ですか?
 多次元の配列の解釈(指定?)が C 言語系と BASIC 系で異なります。
 BASIC 系では多次元配列が左→右に次元が大きくなりますが、C 言語系は右→左の順になります。
 つまり int a[2][4] を a[横方向][縦方向] とした場合は
 5、1
 6、2
 7、3
 8、4
 という縦型イメージになります。
・正しくは int a[2][4] を a[縦方向][横方向] と解釈した方が良さそうです。
 その場合は
 for ( y = 0 ; y < 2 ; y++ ){
  for ( x = 0 ; x < 4 ; x++ ){
   printf( "a[%d][%d] = %d ", y, x, a[y][x] );
  }
  printf( "\n" );
 }
 となります。
・今回の場合は for 文の(10)、(11)の行を入れ替えて
 (11)for ( y = 0 ; y < 4 ; y++ ){
 (10) for ( x = 0 ; x < 2 ; x++ )
 (12)  printf( "a[%d][%d]=%d ", x, y, a[x][y] );
 (13) printf( "\n" );
 (14)}
 とすればちゃんとイメージ通りに表示されます。
 x、y の数を入れ替えるのではなく。
・本当はメモリ・イメージと配列のイメージをあわせた方が分かりやすいです。
 つまり、メモリの配置より
 a[横方向][縦方向] よりも
 a[縦方向][横方向] として
 アクセスして下さい。
・以上。
    • good
    • 0
この回答へのお礼

ご回答有難うございました。

失礼ですが、ANo.6 fatbowlerさんの回答下部に新たな質問を致しておりますので、ご指摘の程宜しくお願い致します。

お礼日時:2007/07/15 06:50

2次元配列のx方向、y方向は単なる概念なので。

。。
>(10)行目での条件を x<4
>(11)行目での条件を y<2
この条件では、(12)でa[3][1]を参照することになるので、
型宣言とあっていません
    • good
    • 0
この回答へのお礼

ご回答有難うございました。

失礼ですが、ANo.6 fatbowlerさんの回答下部に新たな質問を致しておりますので、ご指摘の程宜しくお願い致します。

お礼日時:2007/07/15 06:50

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qif文の判定条件に配列

2次元配列(ここではa[M][N]とします)の値が全て0の時にだけある文章を実行したいのですが、
if(for(i=0; i<M; i++){
for(j=0; j<N; j++)
map[i][j] == 0;
}){ (実行したい文) }
という文をコンパイルしたところエラーが出てしまいました。
if文の判定条件中にfor文は使えないのでしょうか?
使えないのであれば、別の書き方を教えて戴けると嬉しいです。よろしくお願いします。

Aベストアンサー

コンパイルして無いのですが、

flg =0;
for(i=0;i<M;i++)
{
for(j=0;j<N;j++)
{
if(map[i][j] != 0)
{
flg = 1;
}
}
}
if(flg == 0)
{
実行したい文
}

Q2次元配列の文字"列"の初期化方法

こまかな話しかもしれないのですが、2次元配列の文字列代入で、

char *array2 = {"Jan", "Feb", "March"}; //NG
はNGで
char *array2[3] = {"jan,", ...}; //OK
なのはどうしてなのでしょうか?

1: "[3]"は明示しなくとも代入される値から分かるという理由で省略してはいけないのでしょうか?

また、
2: 一次元の場合
char *array = "aaaaa";
とできるのにどうして2次元ではNGなのか、がピンと来ません。

すみませんが、宜しくお願い致します。

Aベストアンサー

>こまかな話しかもしれないのですが、2次元配列の文字>列代入で、
>
>char *array2 = {"Jan", "Feb", "March"}; //NG
>はNGで
>char *array2[3] = {"jan,", ...}; //OK
>なのはどうしてなのでしょうか?

上記は、2次元配列ではなくて、『ポインタ配列』の初期化代入です。

2次元配列であれば、
char buf[][8] = {"BLACK","BLUE","RED"};
のように、します。


一般的に、
       "文字列"
という表現は、
      文字列+ヌル文字
が記憶された場所を表すchar *のポインタになりますが、例外があります。

配列要素を初期化するときに、char * と見なすか、単なる連続文字列と見なすか、です。

代入すべき値がポインタの場合に、char *となります。
  char *p = "AAAA";

char *bufp[] = { "AAAA" , "BBBB" , "CCCC" };
です。

連続文字列として考えるときは

char buf[] = "AAAAAAAAAA";



char buf[][8] = {"BLACK","BLUE","RED"};

のような場合です。
上記の場合、8文字に満たない場合はヌル文字が補われます。

[BLACK000] [BLUE0000] [RED00000]

のようになります。

>こまかな話しかもしれないのですが、2次元配列の文字>列代入で、
>
>char *array2 = {"Jan", "Feb", "March"}; //NG
>はNGで
>char *array2[3] = {"jan,", ...}; //OK
>なのはどうしてなのでしょうか?

上記は、2次元配列ではなくて、『ポインタ配列』の初期化代入です。

2次元配列であれば、
char buf[][8] = {"BLACK","BLUE","RED"};
のように、します。


一般的に、
       "文字列"
という表現は、
      文字列+ヌル文字
が記憶された場所を表すchar *のポインタにな...続きを読む

Qif と配列の組み合わせ

なにやら思いつかなかったのでこちらで相談します。

配列のaと変数bがこんな感じだったとします。

int a[4]={1,3,4,7};
b=6;

もしbが配列aのどの数字にも当てはまらないならこうしますよ
もしbが配列aのどれかの数字に当てはまるならこうしますよ

といったプログラムを作りたいのですが短く処理できる
プログラムを思いつきません。(理論演算子を使えば長くなる)

どうすれば短く処理できますか?

Aベストアンサー

C++なら、
#include <algorithm>

int main(int argc, char** argv)
{
  int a[4] = {1, 3, 4, 7};
  int b = 6;
  if (std::find(a, a + 4, b) == a + 4){
    printf("どれにも当てはまらない\n");
  } else {
    printf("どれかに当てはまる\n");
  }
  return 0;
}

Cなら、
int main(int argc, char** argv)
{
  int a[4] = {1, 3, 4, 7};
  int b = 6;
  int found = 0;
  int i;

  for (i = 0; i < 4; i++){
    if (a[i] == b){
      found = 1;
      break;
    }
  }
  if (found){
    printf("どれかに当てはまる\n");
  } else {
    printf("どれにも当てはまらない\n");
  }
  return 0;
}

C++なら、
#include <algorithm>

int main(int argc, char** argv)
{
  int a[4] = {1, 3, 4, 7};
  int b = 6;
  if (std::find(a, a + 4, b) == a + 4){
    printf("どれにも当てはまらない\n");
  } else {
    printf("どれかに当てはまる\n");
  }
  return 0;
}

Cなら、
int main(int argc, char** argv)
{
  int a[4] = {1, 3, 4, 7};
  int b = 6;
  int found = 0;
  int i;

  for (i = 0; i < 4; i++){
    if (a[i] == b){
      found = 1;
      ...続きを読む

Qscanfでの読み込み文字数制限

scanf( "%10s" , file_name );
とすればfile_nameに読み込む文字数を10バイトに制限できるそうですが、10のところに定数(defineで定義したもの)を指定することはできないのでしょうか?

普通に
#define NUM 10
scanf( "%NUMs" , file_name );
としてもできないようでした。

Aベストアンサー

#define NUM 10 のままで

sprintf(fmt, "%%%ds", NUM);
scanf(fmt , file_name);

という方法もあります。

Q数字以外が入力されたらエラー文を出したい。

scanfで数字を取り込みたいのですが、ここでaなどのアルファベットや記号を入力すると、無限ループが発生してしまいます。
エラーが出ないように、数字以外が入力されたら、エラーメッセージを出すようなプログラムを作りたいのですが、どうすれば出来るでしょうか。

Aベストアンサー

★アドバイス
>scanfで数字を取り込みたいのですが、ここでaなどのアルファベットや記号を入力すると、
>無限ループが発生してしまいます。
 ↑
 ソースとかを見せて欲しいです。
 見ないとなぜ無限ループするのか判断できません。
>エラーが出ないように、数字以外が入力されたら、エラーメッセージを出すようなプログラムを
>作りたいのですが、どうすれば出来るでしょうか。
 ↑
 多分、scanf で整数の入力を行っていると思うので文字列で入力するようにします。
 そしてそのその文字列を strtod() 関数で整数に変換します。
・このときグローバル変数の errno を調べて ERANGE なら整数値のオーバーフローが起きたとか、
 第2引数で私のポインタに変換できなくなった位置をセットしますので、このポインタが \0 文字
 以外なら数字以外(アルファベットや記号)が混ざっていることになります。
・下にそのサンプルを載せます。

サンプル:
char buff[ 256 ];
char *argp;
int value;

// 文字列で入力
scanf( "%s", buff );
value = strtol( buff, &argp, 10 ); ←10進数で変換

// ここでチェック
if ( (errno != ERANGE) && (*argp != '\0') ){
 printf( "変換不可能な文字が入力されています。\n" );
 exit( 1 );
}

その他:
・上記のサンプルを使うには errno.h をインクルードして下さい。
 このヘッダに ERANGE 定数が定義されています。
 あと stdlib.h もインクルードしないと strtol() 関数が利用できません。
・以上。下の『参考URL』もどうぞ。

参考URL:http://www9.plala.or.jp/sgwr-t/lib/strtol.html

★アドバイス
>scanfで数字を取り込みたいのですが、ここでaなどのアルファベットや記号を入力すると、
>無限ループが発生してしまいます。
 ↑
 ソースとかを見せて欲しいです。
 見ないとなぜ無限ループするのか判断できません。
>エラーが出ないように、数字以外が入力されたら、エラーメッセージを出すようなプログラムを
>作りたいのですが、どうすれば出来るでしょうか。
 ↑
 多分、scanf で整数の入力を行っていると思うので文字列で入力するようにします。
 そしてそのその文字列を str...続きを読む

QC、C++、C#の関係について

現在C#で簡単な開発しています。

今度就く業務ではC++が必要だから、勉強しておくようにと言われました。
C#を使っていながら、恥ずかしい質問なのですが・・・

 ・よく聞く「VC++」と「C++.Net」は、違うのでしょうか?
  正式名称が「Microsoft Visual C++ .Net」なので、同じような気がするのですが。
  私の使用PCには「Microsoft Visual Studio .Net 2003」が入っています。

 ・C言語とC++との違いは何なのでしょうか?
  両者の関係が分かりません。
  C++を勉強する場合、C言語というのは飛ばしてよいのでしょうか?
  C#を習得するときは、C言語を勉強しませんでした。
  C++で開発とか、C#で開発とか言いますが、「C言語で開発」とは言わないですよね?

C#とC++がどれほど違うのかが不安です。
質問がたくさんになってしまいましたが、よろしくお願いいたします。

Aベストアンサー

 ・よく聞く「VC++」と「C++.Net」は、違うのでしょうか?

文脈により違うものをさす可能性もあります。(同じ可能性もありますが、大抵は違うかも…)

「VC++」は、Microsoft社のC++コンパイラ製品名(の略称)であって、言語ではないです。
但し、特にMFCでの開発をさして(C++と区別して)「VC++」と表現する方もいます。

そして、「VC++」は、「非.NET platformのC++(標準C++)」と、
.NET platform用のManaged C++(MSの独自拡張。後に整理されてC++/CLIとして規格化)の*両方に*対応してます。

C++.NETというと、恐らくはManaged C++(MS独自拡張)か、
C++/CLI(これはECMAで独立した言語として標準化)をさすと思われます。
# Managed C++とC++/CLIも微妙に違う言語です。

一報、単にVC++と言う場合、標準C++(+MFC)の可能性が高いです。


> 私の使用PCには「Microsoft Visual Studio .Net 2003」が入っています。

これは、.NET framework上のManaged C++と標準C++の両方に対応した製品です。

 ・C言語とC++との違いは何なのでしょうか?

C言語は、ISO/IEC9899で標準化された言語です。
C++は、C言語をベースに開発された別の言語です(ISO/IEC14882)。
そして、.NET framework用のC++/CLI (ECMA-372)も別の言語です。

CとC++の関係を例えるなら、ラテン語と英語とかみたいなものでしょうか。
(ベースでもあり、参考にはなるが、似て非なるもの)

> C++を勉強する場合、C言語というのは飛ばしてよいのでしょうか?

知っているとお得です。知らないと将来「はまる」可能性もあります。
ですが、最初に勉強するべきかといわれると、議論が分かれるところだと思います。

> C++で開発とか、C#で開発とか言いますが、「C言語で開発」とは言わないですよね?

「C言語で開発」とも言います。
(PCアプリだと「C言語+Win32」ということが少ないだけで、組込業界等に行くと普通にあります。別言語ですし、C言語のシェアも高いので)

> C#とC++がどれほど違うのかが不安です。

根本のOOPとかは共通ですが、C++の方が格段に複雑で難易度が高いです。
C++⇒C#は比較的容易ですが、逆は結構面倒だと思います。

C#がオートマ車の運転なら、C++はF1カーのようなもの。
クラッチの切り方から注意しないとエンストしたり、事故ります。
その代わり極めれば性能が出ます。(反面、極めるのは困難です)

 ・よく聞く「VC++」と「C++.Net」は、違うのでしょうか?

文脈により違うものをさす可能性もあります。(同じ可能性もありますが、大抵は違うかも…)

「VC++」は、Microsoft社のC++コンパイラ製品名(の略称)であって、言語ではないです。
但し、特にMFCでの開発をさして(C++と区別して)「VC++」と表現する方もいます。

そして、「VC++」は、「非.NET platformのC++(標準C++)」と、
.NET platform用のManaged C++(MSの独自拡張。後に整理されてC++/CLIとして規格化)の*両方に*対応してます。

C++.NET...続きを読む

Qgetchar()の意味・・・

今僕は専門学校で勉強しています。
僕の学校では、getchar() は } の前につけています。それで、プログラムを実行したときに画面消えなくなります。もし、つけてなかったら、画面はすぐに消えます(けど、プログラムはちゃんと実行されます)そいうものだと思っていたのですが、友人のプログラムを見るとgetchar()が分のとちゅうにあったりと学校で習ったのと違う使い方をしています。
getchar()の本当の意味(使い方)はなんなのでしょう?

回答おねがいします。

Aベストアンサー

getchar()は標準入力から1文字読み取る。という関数です。
この関数は1文字入力があるまで待機するので、} の前(終了直前)に書いてあれば、プログラムの終了直前で停止し、何かキー入力したら終了します。getchar()の戻り値を捨ててただ単に "続行するには何かキーを押してください . . ." という使い方です。
学校で教えている使い方が本当の使い方ではないということになりますね。

QLNK2019: 未解決の外部シンボルのエラーが出る

Microsoft Visual Studio 2008
Version 9.0.21022.8 RTM
Microsoft .NET Framework
Version 3.5 SP1
----------------------------------------------------------------
新しいプリジェクト→Win32 コンソール アプリケーション(ソリューションのディレクトリを作成 チェック外す)→Windows アプリケーション(空のプロジェクト チェック外す)
----------------------------------------------------------------
 プログラム

 mymain.cpp
#include "myhelper.h"
#include "mymain.h"

//自キャラのデータ
Point2D g_jikipos = {40, 400};//自キャラの座標

//画像ハンドル
int g_jikiimage[11];

//色々なファイルの読み込み
int LoadFiles(){
//画像ファイル読み込み
if(LoadDivGraph("media\\player01.bmp",
11,11,1,64,64,g_jikiimage) == -1) return -1;

return 1;
}


 mymain.h
//他から呼び出させるMyMainの関数
void MyMain();
int LoadFiles();


 myhelper.h(サンプルなので打ちミスはない)
#include "DxLib.h"
#include <limits.h>
#include <math.h>

//構造体宣言
//座標またはベクトルを記録する構造体
struct Vector{
float x,y;
};
typedef Vector Point2D;
//線を記録する構造体
struct Line2D{
Point2D startpos, endpos;
float katamuki;//傾きをラジアン値で記録
Vector speed;//移動している場合は速度をセット
};
//球体を記録する構造体
struct Ball2D{
Point2D position;
float hankei;//半径
};
//四角形を記録する構造体
struct Rect2D{
Point2D lefttop;
Point2D rightbottom;
float width;
float height;
};


//ライブラリ関数
Point2D PosInView(Point2D in);
int XInView(float inx);
int YInView(float iny);
void ScrollToLeft(float jikiposx);
void ScrollToRight(float jikiposx);
void ScrollToUp(float jikiposy);
void ScrollToDown(float jikiposy);
void DrawLineInView(float x1, float y1, float x2, float y2, int Color, int Thickness);
void DrawCircleInView(float x, float y, float r, int Color, int FillFlag);
void DrawAnimation(float x, float y, double ExtRate, double Angle,int TurnFlag,
int *imgarray, int allframe, float fps);
//ベクトル関数
Vector CreateVector(Vector in, float veclen);
Vector AddVector(Vector v1, Vector v2);
Vector SubVector(Vector v1, Vector v2);
Vector AddVectorInFrameTime(Vector pos, Vector speed);
Vector AddVectorInFrameTime2(Vector pos, Vector speed, Vector accel);
Vector Normalize(Vector in);
Vector RotateVector(Vector in, float radian);
float VectorLengthSquare(Vector in);
float DotProduct(Vector v1, Vector v2);
float CrossProduct(Vector v1, Vector v2);
void SetLine2DKatamuki(Line2D *in);
void DrawLine2D(Line2D in, int Color, int Thickness);
void DrawBall2D(Ball2D in, int Color, int Fill);
//当たり判定関数
bool HitTestLineAndBall(Line2D linein, Ball2D ballin);
bool IsPointAtLineFace(Line2D linein, Point2D ptin);
bool HitTestLineAndLine(Line2D line1, Line2D line2);
bool HitTestBallAndBall(Ball2D a, Ball2D b);
bool HitTestPointAndBox(Rect2D rect, Point2D pt);
//タイマー関数
void SetSimpleTimer(int idx, int time);
int GetPassedTime(int idx);


//グローバル変数
extern float g_frametime;
extern Rect2D g_framerect;//画面領域(当たり判定)
extern Point2D g_current_field_pos;//現在の左上座標
extern Rect2D g_stagesize;//ステージサイズ

//定数宣言
const float ZEROVALUE = 1e-10f;
const float PIE = 3.1415926f;
const int SCROLL_LIMIT = 200;
----------------------------------------------------------------
 エラー内容
1>myhelper.obj : error LNK2019: 未解決の外部シンボル "void __cdecl MyMain(void)" (?MyMain@@YAXXZ) が関数 _WinMain@16 で参照されました
1>C:\Documents and Settings\Owner\My Documents\Visual Studio 2008\Projects\my\Debug\my.exe : fatal error LNK1120: 外部参照 1 が未解決です
1>my - エラー 2、警告 0
ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ
----------------------------------------------------------------
画像を貼り付けときます
(見えにくい場合→http://www.dotup.org/uploda/www.dotup.org154142.jpg.html)
初心者なのでわかりやすくお願いします

Microsoft Visual Studio 2008
Version 9.0.21022.8 RTM
Microsoft .NET Framework
Version 3.5 SP1
----------------------------------------------------------------
新しいプリジェクト→Win32 コンソール アプリケーション(ソリューションのディレクトリを作成 チェック外す)→Windows アプリケーション(空のプロジェクト チェック外す)
----------------------------------------------------------------
 プログラム

 mymain.cpp
#include "myhelper.h"
#include "mymain.h"

//自...続きを読む

Aベストアンサー

ファイル構成から推測するに
mymain.cpp というファイルに
void MyMain(void) {
// ここに処理を書く
}
という関数が必要なようです。

Q構造体のメンバが配列の場合の扱い

typedef struct _info_t{
int xxx;
int yyy;
int zzz;
} info_t;

typedef struct _gData{
int aaa;
 int bbb;
info_t infoData[100];
} gData_t;

gData_t gMainData;

質問1
C言語で上記のようなグローバルのデータを作成しようとしています。
gMainDataの中身を初期化するにはどうするのがベストでしょうか?
(特にinfoData[100]の初期化)

質問2
gMainData.infoData[XXX]には info_t型のtmpDataを代入しようとしていますが
gMainData.infoData[XXX] = tmpData;
データがはいっているかどうかはどう判定するべきでしょうか?


質問3
以下のようにポインタを使うのは間違いでしょうか?
typedef struct _gData{
int aaa;
 int bbb;
info_t *infoData[100];
} gData_t;


初期化
memset(gMainData.infoData,NULL, 100);

データの代入
*gMainData.infoData[XXX] = tmpData;

データの有無判定
if( gMainData.infoData[XXX] == NULL){

}

typedef struct _info_t{
int xxx;
int yyy;
int zzz;
} info_t;

typedef struct _gData{
int aaa;
 int bbb;
info_t infoData[100];
} gData_t;

gData_t gMainData;

質問1
C言語で上記のようなグローバルのデータを作成しようとしています。
gMainDataの中身を初期化するにはどうするのがベストでしょうか?
(特にinfoData[100]の初期化)

質問2
gMainData.infoData[XXX]には info_t型のtmpDataを代入しようとしていますが
gMainData.infoData[XXX] = tmpData;
データがはいっているかどう...続きを読む

Aベストアンサー

1.初期化
ループでもmemsetでもよいと思います。どれがベストかはケース・バイ・ケースでしょう。

ただしmemsetの第2引数はint型、第3引数はバイト数なので、次のようにするべきです。
memset(gMainData.infoData, 0, 100 * sizeof(info_t));

また、C言語の規格により static 変数を明示的に初期化しなければ全て 0 になるので
static gData_t iniData;
gData_t data;
と定義しておいて
data = iniData;
のように初期化する方法も(一応)あります。


2.データの代入

info_t *infoData[100] は構造体の配列ではなく、ポインタの配列です。
infoData をポインタにするなら、構造体を下のようにすれば

typedef struct _gData {
 int aaa;
 int bbb;
 info_t *infoData[100];
 info_t _infoData[100];
} gData_t;

次のように代入することができます。

data._infoData[XXX] = tmpData;
data.infoData[XXX] = &(data._infoData[XXX]);


3.データの有無判定

前述の2のようにすれば
if( gMainData.infoData[XXX] == NULL){
}
でデータを代入済みかどうか判定できます。
もちろんデータを代入していないポインタがNULLであることが前提ですが。


・余談ですが、構造体のタグ名とtypedefする型名は同じでも大丈夫です。例えば

typedef struct info_t{
...
} info_t;

のように。

1.初期化
ループでもmemsetでもよいと思います。どれがベストかはケース・バイ・ケースでしょう。

ただしmemsetの第2引数はint型、第3引数はバイト数なので、次のようにするべきです。
memset(gMainData.infoData, 0, 100 * sizeof(info_t));

また、C言語の規格により static 変数を明示的に初期化しなければ全て 0 になるので
static gData_t iniData;
gData_t data;
と定義しておいて
data = iniData;
のように初期化する方法も(一応)あります。


2.データの代入

info_t *infoData[100] は構造体の配...続きを読む


人気Q&Aランキング