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

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

ただいまの
回答率

90.48%

  • C++

    3594questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

C++ ファイルからの読み込み

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 445

waewae96

score 5

こんばんは。
普段Cでコードを書いている学生です。
C++のvectorを使ってファイルから一行ずつ数字を読み込んで格納するファイルを作成中なのですが、
ファイルは読み込むのになぜかvectorに格納されません。
問題のコードは以下の通りです。二つの関数の宣言は別のヘッダファイルでしてあります。

#include <stdio.h>
#include <iostream>
#include <vector>
using namespace std;


FILE *fp1;
/*(1-3)*/
void file_input(vector<double> v){
  int leng = file_counter(0);
  v.reserve(leng);
  rewind(fp1);
  int i = 0;
  double j;
    while (1) {
    fscanf(fp1, "%lf",&v[i]);
    i++;
    printf("v=%f\n",v[i]);

    if(i >= leng)
      break;
}
    fclose(fp1);
}


/*(1-5)*/
int file_counter(int flag){
  char filename [256];
  int counter = 0;
  printf("ファイル名を入力してください:");
  scanf("%s",filename);

    if ((fp1 = fopen(filename, "r")) == NULL) {
        printf("file open error!!\n");
        exit(EXIT_FAILURE);
  }
  else{
    double fake;
    while(fscanf(fp1, "%lf", &fake) != EOF){
      counter++;
    }
  }
  if(flag){
    printf("ファイルから読み取ったデータ数は%dでした\n",counter);
    fclose(fp1);
  }

  return counter;
}

尚、ファイルからでなくキーボードから入力でvectorに格納する分にはうまく行きました。
以下のコードです。

vector<double> input_key(vector<double> v, int n){
    int i;
    for(i=0;i<n;i++){
        printf("data[%d]=",i);
        scanf("%lf",&v[i]);
    }
    return v;

この二つの違いがよくわかりません。
改善案などあれば教えてください。
稚拙な日本語とコードで申し訳ありませんが、よろしくお願いします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+2

void file_input(vector<double> v){

値渡しであるために、vectorのインスタンスがコピーされてしまっています。
つまり、呼び出し元のvと、関数内のvが別物です。

参照渡しするようにすれば良いでしょう。

尚、ファイルからでなくキーボードから入力でvectorに格納する分にはうまく行きました。
この二つの違いがよくわかりません。

後者のコードも値渡しですが、戻り値としてvectorのインスタンスを返しています。
結果的に二回コピーが生じ(※)、意図通りの出力が得られているだけです。


※ 実際には最適化される(はず)なので、これは方便としての嘘です。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/04/16 08:54

    ありがとうございます。
    調べてもvectorの参照渡しの方法がわかりません。
    簡単にどのようにすれば良いか教えていただけますでしょうか。

    キャンセル

  • 2018/04/16 08:56

    void file_input(vector<double>& v) {...}
    # &を型のケツに追加

    キャンセル

  • 2018/04/16 09:12

    ありがとうございます。ただ、
    関数file_input内でもvectorであるvの値が変更されません。

    FILE *fp1;
    /*(1-3)*/
    vector<double> file_input(vector<double> &v){
    int leng = file_counter(0);
    v.resize(leng);
    rewind(fp1);
    int i = 0;
    while (1) {
    fscanf(fp1, "%lf",&v[i]);
    i++;
    printf("v=%f\n",v[i]);

    if(i >= leng)
    break;
    }
    fclose(fp1);
    return v;
    }

    file_counterについては質問に乗せたものと同じです。
    上記のようにv[]の値を全て表示させてみたのですが、全てv[i]=0.0000となってしまいます。
    v[]に読み込ませずに確認したところ、ファイルの読み込みは、うまくいっているようです。
    v[]への書き込みがうまくいかないようです。
    どこが間違っているでしょうか。

    キャンセル

  • 2018/04/16 09:16 編集

    fscanf(fp1, "%lf",&v[i]); // 読んで
    i++;
    printf("v=%f\n",v[i]); // 次の要素をプリント(だめじゃん)

    ↑この出力を根拠にうまくいかないって言ってる?

    キャンセル

  • 2018/04/16 09:22

    そうです!
    全て0.00になってしまいます

    キャンセル

  • 2018/04/16 09:25

    だからー、それじゃダメなのあたりまえでしょ?
    fscanf(fp1, "%lf",&v[i]); // 読んで
    printf("v=%f\n",v[i]); // その要素をプリント
    i++; // 次へ
    じゃなきゃ。

    キャンセル

  • 2018/04/16 09:52

    本当だ!
    ありがとうございます笑
    変なミスしてましたね笑

    キャンセル

  • 2018/04/16 15:04

    解決したんなら適切に closeしてねー

    キャンセル

  • 2018/04/16 15:16

    @episteme さん
    なにかとありがとうございます。。。

    キャンセル

  • 2018/04/16 15:18

    いやだから、"best-answer"なり"解決済み"にしろって。

    キャンセル

0

呼び出し側のコードが提示されていないのでなんとも言えないですが、
下のバージョンのinput_keyを呼び出している時はvector<double> vにちゃんとn個分の要素があるvector<double>を渡して呼び出しているからうまく行ってるのでは?

上のコードでは

v.reserve(leng);

とやっていますが、std::vectorのreserveは領域の予約を行う関数で実際にleng分の要素を確保するわけではないです。

代わりに、

v.resize(leng);

とすることでうまく動くのではないかと思います。

C/C++はパフォーマンス上の理由から実行時に添字の範囲チェックなどはしないので、上のコードでも偶然動いてしまいうるんですが、Debugビルドだと実行時範囲チェックをしてくれる処理系も多いので、実はログなどに"Index is out of range"みたいな例外を出してプログラムが止まっているのではないでしょうか?本当に何も言わずにただただデータが入っていなかったのでしょうか?

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

  • ただいまの回答率 90.48%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 解決済

    4個×3行の数字のファイル入出力がうまくいきません

    #include <stdio.h> #include <stdlib.h> #include <math.h> void Read(); void Output(); FILE

  • 解決済

    構造体のプログラム

    いつもお世話になっています。C言語初心者でただいま勉強中です。構造体について質問させていただきます。ファイルから構造体配列に読み込んで以下のように出力するプログラムを作りたいんです

  • 受付中

    c言語の課題に悩んでいます

    前提・実現したいこと 出力したファイル(a.txt)を読み込み、各行の合計値をファイル(b.txt)へ出力するプログラムを作成したいのですが上手くいきません。どなたか下記のプログ

  • 解決済

    C言語 行列のファイル読み込み(と、ガウス消去法計算)

    大学の課題で、コンパイルは通ったのですが、うまく読み込んでいないようです。 ガウス消去法を用いて Ax = B を x について解くというもので、行列Aと行列Bはそれぞれ.c

  • 受付中

    プログラムを見やすく改良したい

    正常に動くプルグラムを見やすく改良したい。 具体的に教えていただければありがたいです。セグメンテーションフォルトでベスト7まで表示して停止します。173行あたりだと思うのですが、よ

  • 解決済

    実行時間の表示がおかしい

    ラックナンバーリサーチの時間が過去の履歴は正常に表示されますが、 短い順に並べるところの年と月が2017年が3917年、10月が9月と表示され、そのほかの 時間は正常です。コードの

  • 解決済

    数字(文字)が何も書かれていない、を表現するのにNULLであってるのか

    前提・実現したいこと C言語を使って,「input.txtに1個以上の実数が1行に1つずつ改行を挟んで書かれているとき, 記載されている実数をすべて読み込み,数値の合計,数値の個数

  • 解決済

    バイナリファイルの読み込み

    以下のような形式の.dat形式のファイルを読み込み,読み出し,printfで出力したいです. 2 36 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,

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

  • C++

    3594questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。