質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.36%

  • C

    3957questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C言語のポインタ渡しなど

解決済

回答 3

投稿

  • 評価
  • クリップ 1
  • VIEW 560

sakas1231

score 27

fpaの参照しているfnameaファイルから500行2列の数字列を受け取り、posに保存してからそれをexpansionメソッドに代入して数値を変換してfnamebファイルに出力するというプログラムです。

#include <stdio.h>

//double (*expansion(double p[500][2]))[2];
void expansion(double x0[500][2]);
int main(){
    int ret, i = 0;
    FILE *fpa , *fpb;
    char *fnamea = "data.csv";
    char *fnameb = "data2.csv";
    double pos[500][2];
    double x, y;

    fpa = fopen(fnamea , "r");
    if(fpa == NULL){
        printf("ファイルが開けません");
        return -1;
    }
    fpb = fopen(fnameb , "w");
    if(fpb == NULL){
        printf("ファイルが開けません");
        return -1;
    }    

    while((ret = fscanf(fpa, "%lf,%lf", &x , &y)) != EOF){
        pos[i][0] = x;
        pos[i][1] = y;
        i++;
    }
    expansion(pos);

    for(i = 0; i < 500; i++){
        fprintf(fpb, "%lf,%lf\n", pos[i][0], pos[i][1]);
    }
    fclose(fpa);
    fclose(fpb);
}

void expansion(double x0[500][2]) {
    double H = 3.5;
    double org = 50;
    double dt = 0.1;
    int nk = 20 , i = 0 , j = 0 , k = 0;
    double vx[500][2] , x[500][2];
    for(i = 0; i < 500; i++){
        for(j = 0; j < 2; j++){
            vx[i][j] = H * x0[i][j];
            x[i][j] = x0[i][j] + org;
            for(k = 0; k < nk; k++){
                x[i][j] += vx[i][j] * dt;
            }
        }
    }
    x0 = x;
}

このようにするとエラーは吐かないのですが、出力結果がfnameaと同じ数字になってしまいます。
どうしてでしょうか、回答宜しくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+1

x0 = x; では配列の中身はコピーされません。

以下のようにするか、x0 = x; の部分をループを使ってコピーするような処理にするなどではどうでしょうか。

 x0[i][j] = x0[i][j] + org;
            for(k = 0; k < nk; k++){
                x0[i][j] += vx[i][j] * dt;
            }

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/26 12:30

    X0の指すアドレスをXの指すアドレスに書き換えることでX0とXが同じところを指す、という解釈をしていたのですがそこが違うということでしょうか

    キャンセル

  • 2017/01/26 12:40

    expansion の引数としての x0 は仮の変数なので、代入しても元の関数の x0 が変わることはありません。

    また、x 自体が expansion 内のローカル変数なので、適切にアドレスが変わるようにしていたとしても、既に存在しないアドレスを示すため、クラッシュします。

    キャンセル

  • 2017/01/26 12:41

    ご存知だと思いますが、ポインタを書き換えたければ、ポインタのポインタを渡す必要があります。

    ポインタの指し示す中身を変える場合 → ポインタを渡す
    ポインタ自体を変える場合 → ポインタのポインタを渡す

    キャンセル

  • 2017/01/26 13:29

    >>expansion の引数としての x0 は仮の変数なので、代入しても元の関数の x0 が変わることはありません

    なるほど、仮変数の場合はそのようなことが出来ないのですね、肝に銘じておきます

    キャンセル

  • 2017/01/26 13:39

    しかしその場合、一番はじめに回答として仰ったようにx0の値を直接変えたとしてもposには影響を及ぼさないのではないでしょうか?

    キャンセル

  • 2017/01/26 15:25

    x0は配列へのアドレスを示す変数です。
    そのアドレス自体は元の pos 配列を指し示しているので、中身を書き換えれば更新できます。

    配列 pos が示すアドレスが 100 だとして、x0 も 100 だという事です。
    pos が示すもの {100}
    x0 が示すもの {100}
    つまり、同じ 100 という場所を示していて、そこには配列の実体領域があるということです。


    キャンセル

  • 2017/01/26 18:13

    なるほど、ということはx0=xとしてもx0の指してるアドレスがxになるだけでposは変化しない
    ということでしょうか?
    なんだかわかってきた気がします

    キャンセル

  • 2017/01/27 17:08

    >なるほど、ということはx0=xとしてもx0の指してるアドレスがxになるだけでposは変化しない
    ということでしょうか?

    その通りです。

    キャンセル

  • 2017/01/29 23:57

    ありがとうございました!

    キャンセル

0

こんにちは。

蛇足のような気もしますが、少し補足してみます。

void expansion(double x0[500][2])

まず、C言語では、配列を渡すと自動的に配列先頭へのポインタに成り下がってしまいます。上記のように要素数を明記していてもです。この場合、x0の型はdouble (*)[2]になってしまいます。(double型2つの配列へのポインタ)

そして、expansion()の最後でx0にxを代入することで、仮引き数x0(ポインタ)はx(配列)の先頭アドレスを指しています。
しかし、C言語は常に値渡しです。x0が呼び出し元のposへ返却されることはありません。

更に、posは配列であって配列へのポインタではありません。なので、その先頭アドレスを書き換えることはできません。
posは配列としてメモリが割り当てられています。そのメモリを別のアドレスへ移動する手順は遥かに複雑です。移動先アドレスのメモリへデータをコピーして元のメモリを解放するような手順となります。C言語はこのような操作をサポートしていません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/26 13:34

    なるほど、あくまでx0は仮引数なのでいくらx0を変更しようとも、実引数であるところのposにはなんら影響を及ぼさない、という認識でよろしいでしょうか?

    キャンセル

  • 2017/01/26 13:44

    その通りです。

    そして、qt6hyさんが言われるように普通はポインタのポインタで渡せばポインタを返せますが、posは配列であってポインタではないので、ポインタのポインタにしてもダメです。コピーするしかありません。

    キャンセル

  • 2017/01/26 18:19

    ポインタのポインタを渡せば、ポインタを直接書き換えられるけれど、今回は配列を渡すからその手は使えない。そこで仮引数のアドレスにある値を直接書き換える。
    ということでしょうか?

    キャンセル

  • 2017/01/27 17:09

    その理解でよいです。

    キャンセル

  • 2017/01/27 18:23

    qt6hyさん、フォローありがとうございます。
    sakas1231さん、その理解で合ってます。

    キャンセル

  • 2017/01/29 23:57

    ありがとうございました!

    キャンセル

0

ポイント配列で渡す様にしてみました。 expansionの計算が????

#include <stdio.h>

void expansion(double (*x0)[500][2]);
int main(){
    int ret, i = 0;
    FILE *fpa , *fpb;
    char *fnamea = "data.csv";
    char *fnameb = "data2.csv";
    double pos[500][2];
    double x, y;

    fpa = fopen(fnamea , "r");
    if(fpa == NULL){
        printf("ファイルが開けません");
        return -1;
    }
    fpb = fopen(fnameb , "w");
    if(fpb == NULL){
        printf("ファイルが開けません");
        return -1;
    }

    while((ret = fscanf(fpa, "%lf,%lf", &x , &y)) != EOF){
        pos[i][0] = x;
        pos[i][1] = y;
        i++;
    }
    double (*p)[500][2];
    p=(double (*)[500][2])pos; //ポイント配列へ代入
    expansion(p);

    for(i = 0; i < 500; i++){
        fprintf(fpb, "%lf,%lf\n", pos[i][0], pos[i][1]);
    }
    fclose(fpa);
    fclose(fpb);
}

void expansion(double (*x0)[500][2]) {
    double H = 3.5;
    double org = 50;
    double dt = 0.1;
    int nk = 20 , i = 0 , j = 0 , k = 0;
    double vx[500][2];
    for(i = 0; i < 500; i++){
        for(j = 0; j < 2; j++){
            vx[i][j] = H * (*x0)[i][j];
            (*x0)[i][j] = (*x0)[i][j] + org;
            for(k = 0; k < nk; k++){
                (*x0)[i][j] += vx[i][j] * dt;
            }
        }
    }
}
#include <stdio.h>

typedef struct {
    double x[500][2];
}dfpos;

void expansion(dfpos *p);
int main(){
    int ret, i = 0;
    FILE *fpa , *fpb;
    char *fnamea = "data.csv";
    char *fnameb = "data2.csv";
        dfpos pos;
    double x, y;

    fpa = fopen(fnamea , "r");
    if(fpa == NULL){
        printf("ファイルが開けません");
        return -1;
    }
    fpb = fopen(fnameb , "w");
    if(fpb == NULL){
        printf("ファイルが開けません");
        return -1;
    }

    while((ret = fscanf(fpa, "%lf,%lf", &x , &y)) != EOF){
        pos.x[i][0] = x;
        pos.x[i][1] = y;
        i++;
    }
    expansion(&pos);

    for(i = 0; i < 500; i++){
        fprintf(fpb, "%lf,%lf\n", pos.x[i][0], pos.x[i][1]);
    }
    fclose(fpa);
    fclose(fpb);
}

void expansion(dfpos *p) {
    double H = 3.5;
    double org = 50;
    double dt = 0.1;
    int nk = 20 , i = 0 , j = 0 , k = 0;
    double vx[500][2];
    for(i = 0; i < 500; i++){
        for(j = 0; j < 2; j++){
            vx[i][j] = H * p->x[i][j];
            p->x[i][j] += org;
            for(k = 0; k < nk; k++){
                p->x[i][j] += vx[i][j] * dt;
            }
        }
    }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/26 15:41

    expansion()関数が呼び出し元のポインタpを書き換えていないので、ポインタのポインタにする意味は特にないですよ。この処理なら元のx0の渡し方で十分と思います。

    キャンセル

  • 2017/01/26 16:17

    ご指摘ありがとうございます。x0 = x;で上位に戻したいのかな、と思ってました。

    キャンセル

同じタグがついた質問を見る

  • C

    3957questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。