C言語で行列の積を計算できるような関数を作って疑問に思ったことがあります。
まず↓のような2x3行列と3x2行列が計算できる関数を作りました、、
#include <stdio.h>
void mul(const int ma[2][3],const int mb[3][2],int mc[2][2])
{

int i,j,k;
for(i = 0; i < 2; i++)
for(j = 0;j < 2;j++)
for(k=0;k<3;k++)
mc[i][j]+=ma[i][k]*mb[k][j];
}
int main(void)
{
int i,j;
int ma[2][3] ={{1,2,3},{4,5,6}};
int mb[3][2] ={{7,8},{9,0},{1,2}};
int mc[2][2] ={0};
mul(ma,mb,mc);
for(i = 0;i < 2; i++)
{
for(j = 0;j < 2;j++)
printf("%4d",mc[i][j]);
putchar('\n');
}
eturn(0);
}
----------------------------------
これをmxn,nxp行列で計算できるような関数にしたいと思い
下のようにしたのですがエラーになります。どうしたらいいでしょうか・・?
#include <stdio.h>

void mul(const int ma[int m][int n],const int mb[int n][int p],int mc[m][p])
{
int i,j,k;
for(i=0;i<m;i++)
for(j=0;j<p;j++)
for(k=0;k<n;k++)
mc[i][j]+=ma[i][k]*mb[k][j];
}
int main(void)
{int i,j;
int ma[2][3] ={{1,2,3},{4,5,6}};
int mb[3][2] ={{7,8},{9,0},{1,2}};
int mc[2][2] ={0};
mul(ma,mb,mc);
for(i = 0;i < 2; i++)
{for(j = 0;j < 2;j++)
printf("%4d",mc[i][j]);
putchar('\n');}
return(0);}

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

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

A 回答 (5件)

「今の C の規格に従っていれば動く」という意味において「環境による」といえます>#4.

    • good
    • 0

「C言語 多次元配列 引数」 で検索してみてください。



結論から言うと、C 言語で多次元引数を引数指定する場合は、

void mul(const int ma[][3],const int mb[][2],int mc[][2]);

のように、二次元目以降は定数を指定する必要があり変数では指定できません。

任意サイズを扱う場合は、
・行、列数と共に、int ポインタとして渡す。
・配列を十分なサイズで固定し、番兵を立てるなり、行、列数を持ちまわるなり、常に全て計算するなり。
・専用の構造体を作る。
・時間もしくは自信が無ければライブラリ
くらいですかね。

>>3 は環境による?
    • good
    • 0

しゃ~ないので


void mul(int m, int n, int p, const int ma[m][n], const int mb[n][p], int mc[m][p])
あたりで.
    • good
    • 0

> void mul(const int ma[int m][int n],const int mb[int n][int p],int mc[m][p])



メチャクチャです。こんなかたちで任意のサイズの配列が使えるなら誰も苦労はしません。
    • good
    • 0

何をしたとき(コンパイルですか?実行ですか?)に、


どんなエラー(エラーメッセージは?)が出るのですか?
具体的に示してください。
    • good
    • 0

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

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

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

QR言語用のエディターはありませんか?

c言語用のエディターなどはよく聞きますが、
R言語用のエディターはあるのでしょうか??
(当方はWindows2000を使っています)

Aベストアンサー

どうやらemacs(meadow)にありそうです。
meadowってのは設定ファイルをかませると
いろいろな言語のエディタになります。
meadowのインストール方法は検索
すればすぐ見つかります。で、
R用の設定法がすぐに見つかりませんでした。

特化した言語なので、ここでの回答は
期待できません。ユーザグループがある
ようなので、そちらで質問されたほうが
いいと思います。

参考URL:http://r-user.g.hatena.ne.jp/

Qint nII[10] = { 0 }について

久々にCを使ってプログラムを組んでいるのですが、基本的な構文を思い出せず
いくつか教えていただきたく質問させていただきました。

1)配列すべてを初期化するのに、宣言時に

int nII[10] = { 0 };

で大丈夫だった(全ての要素が0で初期化)と記憶しているのですが、間違いないでしょうか?

2)構造体の初期化は

struct tm tm;
memset(&tm, 0, sizeof(struct tm))

で大丈夫でしょうか?

3)構造体の宣言は

typedef struct{
int a;
}HOGE, *LPHOGE;

HOGE st; // <- struct HOGE stと同じ
LPHOGE pst; // <- struct HOGE* pstと同じ

で問題ないでしょうか?

以上、3つ質問になって申し訳ないのですが、よろしくお願いします。

Aベストアンサー

1)OK
2)たぶんOK
3)HOGEという名前の構造体はない(当該の構造体には名前がない)ので、
// 以下のコメント記述が誤っています。ただし、

HOGE st;
LPHOGE pst;
という定義そのものはOK

QR言語の標準クラスライブラリの詳細 確認の仕方、ホームページなど

R言語初心者です。

R言語に最初から付随している標準クラスライブラリの詳細
(どんなメソッド、変数を持っているのかなど)を調べたいのですが、その方法が分かりません。
RのGUIやコンソールからの確認方法や、解説してあるHPなど何でもかまわないので教えて下さい。

また、使用しているパッケージの詳細も同じように確信したいのですが
方法はありますでしょうか?

よろしくお願いします。

環境:
Win7Pro64bit
R-3.2.2forWin64bit
RStudio0.99.489(使ったり使わなかったり)

Aベストアンサー

とりあえずコンソールから
> library()
でインストールされているライブラリのリストが表示される。

インストールされているフォルダも出てくるが、初めから入っているライブラリなら"C:/Program Files/R/R-3.2.2/library"の中にあるでしょう。
Windows VISTA以降なら管理者モードで起動していない限りは後から入れたパッケージは”C:/Users/.../Documents/R/win-library/3.2”の中に入るので、これで標準パッケージか追加パッケージか区別できると思います。

各パッケージの機能の詳細は
> ?base
などのようにパッケージ名を指定してヘルプを出し、Indexのリストをみれば文書化されている関数などは分かると思います。

個人的にはヘルプは英語のみだし必ずしも分かりやすい書き方でもないので、キーワードでインターネット検索して記述例など探すことが多いですね。

Qint i, int i[1];

C++で、
 int i;
と、
 int i[1];
は、どっちで宣言をしても、iは同じ振るまいですか?

Aベストアンサー

配列、ポインタなどよりももっと基礎的な概念である「右辺値」、「左辺値」を理解しましょう。

int i ;
この形で宣言されたiは代入式の右辺(代入する値)にも左辺(代入される領域)にも使うことが出来ます。
int a ;
a = i ;
i = 10 ;

C言語でも他のほとんどの言語でも「変数は右辺の時と左辺の時とでは解釈が違う」という原則があります。

代入式の右辺に配置出来るのは『値』です。
変数であっても良いし定数であっても、式であってもかまいません。
左辺がポインタ変数の場合は右辺はアドレス値(またはアドレス式)です。
代入式の右に配置可能な値を右辺値といいます。

代入式の左に配置出来るのは『領域』です。
変数であっても良いし、配列要素でもかまいません。
また、領域を示す式(int i[1]のときの*iなど)でもかまいません。
配列名(int i[1]のときのi)や定数は領域を持たないため、左辺に配置することが出来ません。
代入式の左に配置可能な領域を左辺値といいます。

int i[1] ;
この形で宣言されたiは右辺値に利用できます。
int *a ;
a = i ;
しかし、iだけでは領域を持たないため左辺値になりえません。
i = 1 ; //コンパイルエラーが出る。

コンパイル時に「有効な左辺値でない」と言う意味のエラーが出るのは「領域を示さない値を左辺値として使っている時」です。

どちらかと言うと「基礎理論」の部類なのでプログラム言語の本などには書いてないのですが、実は最も大切なのが「基礎理論」です。
頑張って勉強してください。

配列、ポインタなどよりももっと基礎的な概念である「右辺値」、「左辺値」を理解しましょう。

int i ;
この形で宣言されたiは代入式の右辺(代入する値)にも左辺(代入される領域)にも使うことが出来ます。
int a ;
a = i ;
i = 10 ;

C言語でも他のほとんどの言語でも「変数は右辺の時と左辺の時とでは解釈が違う」という原則があります。

代入式の右辺に配置出来るのは『値』です。
変数であっても良いし定数であっても、式であってもかまいません。
左辺がポインタ変数の場合は右辺はアドレス...続きを読む

QR言語で乱数を発生させるには!?

R言語というものをインストールしました。
命令一覧をインターネットで開きながらやっているのですが、
乱数発生の命令がないようなので質問してみました。

グーグルで検索したら、rnormを使っているようなのですが、
これは乱数発生ではありませんよね・・・?

Aベストアンサー

R 統計 乱数 でグーしてみてください。

参考URL:http://cwoweb2.bai.ne.jp/~jgb11101/files/R_simulation.pdf

Qchar AA[]{"全角文字"};から"全"という一字を取り出したい

 今晩は、Cの初心者です、宜しくお願いします。
 全角文字の入ったchar AA[]{"全角文字"};から"全"という文字一字を取り出す時にAA[0]とかくとエラーになります。
 どのようにしたら取り出せるのでしょう。
 ポインタを使う方法と使わない方法を教えて下さい。
 宜しくお願いします。

Aベストアンサー

お疲れ様です。

まずお伺いしたのがOSおよび開発するためのコンパイラです。

ロケール等の話は分かりませんが、昔のC言語で日本語を扱う場合には全角文字1文字で2個つのchar領域を使用していました。
(マルチバイト文字セットと言います。)

詳細は参考URLを参照の事。

windowsでVCと仮定した場合、charを使われていると言うことは、多分、shift-jis(シフトJIS)で文字列を扱っていると思われます。

結論として全角文字1文字だけを取り出したいという場合は、結局char2個分のデータを取り出す必要があります。

>char AA[]={'全','角'};

char AA[]="全角";
とし
>printf("%s%s\n" , AA[0],AA[1] ) ;

printf("%c%c\n" , AA[0],AA[1] ) ;
とすれば、「全」だけを表示する事が可能と思われます。

日本語を文字列で表示する為の文字コードについては
Shift-JISだけでなく、UnicodeやUTF・EUC・JISなどがあります。

もう少し詳しく記載してあるホームページはないか探してみましたが、ちょっと無理でした。

参考URL:http://marupeke296.com/CPP_charUnicodeWideChar.html

お疲れ様です。

まずお伺いしたのがOSおよび開発するためのコンパイラです。

ロケール等の話は分かりませんが、昔のC言語で日本語を扱う場合には全角文字1文字で2個つのchar領域を使用していました。
(マルチバイト文字セットと言います。)

詳細は参考URLを参照の事。

windowsでVCと仮定した場合、charを使われていると言うことは、多分、shift-jis(シフトJIS)で文字列を扱っていると思われます。

結論として全角文字1文字だけを取り出したいという場合は、結局char2個分のデータを取り出...続きを読む

QR言語で統計分析を始めたい

カテゴリ違いかもしれませんが、
ここなら適切な回答を頂けると思い質問します。

本日ちょっとした出来事がありまして統計分析とR言語に強烈な興味をもちました。
しかし、残念ながら中学の数学もろくにできないような人間ですので
統計学を学ぶにはどの位のレベルの数学知識が必要かが知りたいです。

今目標としているのは財務省が発表している輸出入貿易統計を使って
今後どの国に何を輸出したらよいかという指標を自分で算出したいと思います。

データ参照元↓(財務省統計ページ)
http://www.e-stat.go.jp/SG1/estat/List.do?lid=000001100843


こういった予測をするのに必要な数学レベルを教えてください
そこから統計分析、R言語と進んで行けたらと思います。
よろしくお願いします。


余談ですが英語が読めたりコピペでVBAプログラムを多少作る事はできます。

Aベストアンサー

統計は、今ある数値を解析するものです。つまり、過去の出来事です。
やりたいことは未来の予測なので統計とは違いますね。
統計手法の中で、大量のマトリックスデーターを使って傾向分析をして、予測をすることができるものとして、近いものとしては、重回帰分析でしょうか。

Qint main(int argc, char* argv[]) についての質問

こんにちは.つね日ごろ思っている質問させてください.
Cの参考書には,
(1)
void main(void)
{
}

(2)
int main(int argc, char* argv[])
{
return 0;
}
の2つのパターンが記載されていますが,
どういう違いがあるのでしょうか?

(1)の場合main関数は,型を持たず,引数も持たない.
※Turbo Cなどのコンパイラーでは,
return文がないと警告出ます.
(2)の場合は,int 型をかえし,引数はint型 変数と char型ポインタ配列(?)
を指定している.
といったくらいしか分かりません.

(2)に関してもう少し述べれば,
コマンドラインからファイルを指定し,実行することが
できると勉強した記憶があるのですが,
理解があいまいです.

特に(2)の場合のmain関数の意味と,その使い方について
アドバイスお願い致します.

Aベストアンサー

> (1)
> void main(void)
  ...
> (2)
> int main(int argc, char* argv[])
  ...
> の2つのパターンが記載されていますが,どういう違いがあるのでしょうか?

(1) は、間違いです。少なくとも ANSI-C の規格に合致していません。

main() は、特別な関数で、ANSI-C の規格では以下の三通りのうちのどれか
でなくてはいけない、と定められています。

int main(void)
int main(int argc, char *argv[]);
int main(int argc, char *argv[], char *envp[]);

因みに三番目の形式では、三つ目の引数には環境変数が入ります。
以下のようなコードで確認ができます。

int main(int argc, char *argv[], char *envp[])
{
  int i = 0;
  while (envp[i]) {
    printf("envp[%d] = '%s'\n", i, envp[i]);
    ++i;
  }
  return 0;
}


> ※Turbo Cなどのコンパイラーでは,return文がないと警告出ます

Turbo C は、規格に厳格なのでしょう。返り値が void なのはおかしいので、
int だとみなすよ、という警告も出てるはず。で、int が帰り値だとみなし
ているので return が無いと、返り値が不定になるよ、と警告を出している
のでしょう。

> (1)
> void main(void)
  ...
> (2)
> int main(int argc, char* argv[])
  ...
> の2つのパターンが記載されていますが,どういう違いがあるのでしょうか?

(1) は、間違いです。少なくとも ANSI-C の規格に合致していません。

main() は、特別な関数で、ANSI-C の規格では以下の三通りのうちのどれか
でなくてはいけない、と定められています。

int main(void)
int main(int argc, char *argv[]);
int main(int argc, char *argv[], char *envp[]);

因みに三番目の形式では、三...続きを読む

QC言語「K&R」の演習2-9について

「プログラミング言語C」、K&Rの演習2-9についてです。

「2の補数系では、x & (x - 1) により、xの右端の1ビットが消える。なぜか説明せよ。この事実を使って、もっと速いbitcountプログラムを書け。」の前半部分(~を説明せよ)が分かりません。1の補数系ではこうならないのでしょうか?

よろしくお願いします。

Aベストアンサー

==================================
「Cアンサー・ブック 啓学出版」より
==================================
解答

bitcount(n)
unsigned n;
{
 int b;
 for(b=0; n!=0; n&=n-1)
   ++b;
 return(b)
}


x-1の値の例として2進で1010(10進で10)を考えてみましょう。(x-1)+1はxになります。
2進      10進
1010  x-1  10
+ 1     + 1
----     ----
1011   x   11
2進数においては、x-1に1を加えた場合、x-1のもっとも右の0ビットがxにおいて1となります。したがって、xのもっとも右の1のビットに対応するx-1のビットは0となります。これが2の補数を用いている数において、x&(x-1)がもっとも右の1のビットをクリアする理由です。
 4ビットの符号なしの数を考えてみましょう。この数のすべての1のビットを数えるために、もとのbitcountではもっとも右のビットを調べるために4回のシフトを行っていますが、代わりに、"x&(x-1)がxのもっとも右のビットをクリアする"という知識を使うことができます。例として、xを9としてみましょう。
1001 2進であらわした9 (x)
1000 2進であらわした8 (x-1)
----
1000 x&(x-1)
もっとも右の1のビットがクリアされています。結果の値は、2進で1000、10進で8となります。さらに同じことを繰り返します。
1000 2進であらわした8 (x)
0111 2進であらわした7 (x-1)
----
0000 x&(x-1)
ここでももっとも右の1ビットがクリアされます。結果の値は、2進で0000、10進で0です。もうxには1のビットがないので、プロセスは終了します。
 もっとも条件のの悪い場合、すなわちxのすべてのビットが1の場合、ANDを行う数はもとのbitcountのシフト数と同じです。結局、こちらのほうが速いバージョンであるといえます。

==================================
「Cアンサー・ブック 啓学出版」より
==================================
解答

bitcount(n)
unsigned n;
{
 int b;
 for(b=0; n!=0; n&=n-1)
   ++b;
 return(b)
}


x-1の値の例として2進で1010(10進で10)を考えてみましょう。(x-1)+1はxになります。
2進      10進
1010  x-1  10
+ 1     + 1
----     ----
1011   x   11
2進数においては、x-1に1を加えた場合、x-1のもっとも右の0ビットがxにおいて1となります...続きを読む

Qfp = fopen(argy[1], "r");の[1]の意味は

https://oshiete.goo.ne.jp/qa/8940272.html
 の11行目に
fp = fopen(argv[1], "r");の[1]の意味が分かりません。
試したいのですが、ソフトがうまく動きません
 よろしくお願いいたします。

Aベストアンサー

前の例題も読みました。

大分苦戦しているようですが、配列については理解が進みましたでしょうか?
お答えしますと、最初のパラメータ文字列が代入されています。

古いC言語の約束でして大変有名なものです。

コマンドラインコンソールから実行ファイル名を書いて、
パラメータをスペースで区切って指定したとします。

このパラメータ文字列が[1]以降に入ります。
例として、"test"と言う名前の実行ファイルがあったとします。

例)> test test1 test2 3 4

このようにコマンドラインから入力し実行すると、

argc = 5
argv[0] = "test"
argv[1] = "test1"
argv[2] = "test2"
argv[3] = "3"
argv[4] = "4"

と文字列が入ってきます。

以下はサンプル。

void main( int argc , char *argv[])
{
if( argc < 2 )
{
// パラメータ指定がなかった場合の表示
printf( "test に続けて4つまでパラメータを入力できます\n");
exit(0);
}
if( argc > 5 )
{
 // パラメータが5つ以上あった場合の表示
printf( "5つ以上のパラメータは受け付けません\n");
exit(-1);
}

// 正常ルート
printf( "パラメータの数は%d個ですね?ニヤッ\n", argc-1);
printf( "最初のパラメータは%sでしょ?\n", argv[1]);
printf( "残りはargv[2]以降ですが、面倒なので表示しません\n");
}

と言う具合に、引数を活用できます。argv[0]には、実行ファイル名が入ります。
argc は実行ファイルの名前も含めてカウントされます。

プログラムによっては必要な引数の数が変わりますし、
ユーザーのコマンドラインからの入力ミスなどでパラメータがなかったり、
必要なパラメータが不足していたりしますので、
argcとargvを使って最初にシンタックスエラーチェックをするのが常道です。

実行ファイル名の指定がなく、プログラムが実行されることはないと思われます
から、argcは1以上の値になります。

argc, argvの活用は、
実行コマンドを手打ちで打ち込むコンソール形式でよく用いられる基本的な
アプリケーションの開発手法です。

ご質問の箇所は、
第一パラメータにプログラム内で読み込むファイルのファイル名を指定してるの
でしょう。(よくあります)

しかし、Windowsなどのウィンドウを使用するアプリケーションは、
これとは違っておりますので注意が必要です。
(C言語とは別に、Windowsに特化した開発ノウハウの勉強が必要です)

Windows系で上記の様な基本的なプログラムを作成する場合は、
プロジェクトの作成時に(VisualStudioなどで)コンソールアプリケーション
を選んで作成します。実行時にコンソールが開きます。

Linuxの場合は、コンソールがデフォルトになっているでしょうから、
(特殊な設定がなければ)そのまま作成できます。

テキストエディタでソースを記述し、gcc などでコンパイルします。
実行形式ファイルが出来ていれば、想定どおりの動作をするでしょう。

ファイルの読み込みが出来るようになったら、
ファイルの内容を書き換えて保存したり、
ファイル名を変えたり、
ディレクトリ内のファイルを全て表示したり、
ファイル内に含まれる文字列を検索し、該当するファイルをリストしたりなど、

有用なサンプルプログラムを沢山作って練習します。

ファイルを読み込む先は、char型の配列でバイトサイズのメモリーとして確保
します。メモリーと変数の関係を充分に理解することをお勧めします。
殆どのプログラムは、このメモリーの確保やメモリーサイズの計算と格闘する
場合が多くなるからです。

バイナリー形式のファイル(すべてはバイナリー形式として良いのですが)に
ついて理解が深まった後は、
bmpの画像ファイル、wavなどの音声ファイルをあけて、
これの中身を書き換えて遊びます。

特にwavファイルは、音量の変更や周波数フィルタなども掛けれますので、
メモリ、配列、ファイルの関係を(焦らずに)ゆっくり理解するだけで、
今の知識レベルでも面白いことが沢山出来ます。

以上、ご参考に成れば。

前の例題も読みました。

大分苦戦しているようですが、配列については理解が進みましたでしょうか?
お答えしますと、最初のパラメータ文字列が代入されています。

古いC言語の約束でして大変有名なものです。

コマンドラインコンソールから実行ファイル名を書いて、
パラメータをスペースで区切って指定したとします。

このパラメータ文字列が[1]以降に入ります。
例として、"test"と言う名前の実行ファイルがあったとします。

例)> test test1 test2 3 4

このようにコマンドラインから...続きを読む


人気Q&Aランキング

おすすめ情報