C言語IDEのCLionでファイルの読み込みをしようとしても読み込めない件
問題
CLionでファイルの読み込みをしようとしても読み込めない件について
CLionのファイルパスはどうなっているか?
その前にCLionとは
JetBrains社の C と C++用のIDEである。公式サイト
学生だと「Free individual licenses for students and faculty members」から無料で使えるのでおすすめ。
問題のプロジェクト
プロジェクトのファイル構成は下記のような感じ。
main.c
の中身は下記のもの。
#include <stdio.h> #include <stdlib.h> void test() { FILE *fp; char *filename = "./hello.txt"; char ch; // File Read fp = fopen(filename, "r"); if (fp == NULL) { fprintf(stderr, "Cannot file open %s\n", filename); exit(1); } while ((ch = fgetc(fp)) != EOF) { putchar(ch); } fclose(fp); } int main() { test(); return 0; }
hello.txt
の中身は下記のもの
Hello World
main.c
はhello.txt
を読み込んで、一文字ずつ標準出力するプログラムである。想定する実行結果は「Hello World」の出力である。
しかし、結果は下記のようにファイルの読み込みが失敗している。
/Users/******/CLionProjects/HELLO/cmake-build-debug/HELLO Cannot file open ./hello.txt Process finished with exit code 1
解決策
hello.txt
をcmake-build-debug
ディレクトリの下に入れればいい。そうすると下記のような構成になる。
$ ls cmake-build-debug/ CMakeCache.txt HELLO.cbp hello.txt CMakeFiles Makefile HELLO cmake_install.cmake
下記実行結果
/Users/*****/CLionProjects/HELLO/cmake-build-debug/HELLO Hello World Process finished with exit code 0
きちんとファイルの中身が出力されている。
原因
そもそも./hello.txt
の./
カレントディレクトリがどこをさしているのか。main.c
と同じ階層(/Users/*****/CLionProjects/HELLO/
)をさしていると思っていたがどうやら違うらしい。確認のため下記関数を定義し、実行してみる。
void test2(){ printf("> pwd \n"); system("pwd"); printf("> ls \n"); system("ls"); }
system();
は渡した文字列をターミナルに渡してくれる関数(参考)で、pwd
はカレントディレクトリのフルパスを出力するUNIXコマンドls
はディレクトリ内のファイルの一覧を表示するUNIXコマンド
である。Windowsだとdir
で代用がきくと思う。
実行結果は
/Users/sikeda/CLionProjects/HELLO/cmake-build-debug/HELLO > pwd /Users/sikeda/CLionProjects/HELLO/cmake-build-debug > ls CMakeCache.txt HELLO.cbp hello.txt CMakeFiles Makefile HELLO cmake_install.cmake Process finished with exit code 0
cmake-build-debug
がカレントディレクトリであることが確認できる。よくよく考えると、実行ファイルであるHELLO
がcmake-build-debug
にあるので当然である…。
試しにターミナルを開いて、直接実行ファイルを実行してみると、同じ結果が得られる。
$ pwd /Users/****/CLionProjects/HELLO/cmake-build-debug $ ./HELLO > pwd /Users/****/CLionProjects/HELLO/cmake-build-debug > ls CMakeCache.txt HELLO.cbp hello.txt CMakeFiles Makefile HELLO cmake_install.cmake
余談
ビルド先のディレクトリを変更できるらしい。
Q: CLionのビルド出力パスは変更できますか? A: 以下のようにCMake変数を指定すれば簡単に変更できます: set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "my_dir") 参考
CMakeLists.txt
にset(CMAKE_RUNTIME_OUTPUT_DIRECTORY "my_dir")
を追記する。CMake project needs to be reloarded
と出るので、Reload changes
をクリックする。- その後、実行すると
my_dir
が作られ、そこに実行ファイルが生成される。 下記は実行結果
/Users/****/CLionProjects/HELLO/cmake-build-debug/my_dir/HELLO > pwd /Users/****/CLionProjects/HELLO/cmake-build-debug/my_dir > ls HELLO Process finished with exit code 0
HELLO.cbp
の中身を見てみると、中身が変更されているのがわかる。.cbp
はおそらくCode::Blocks Project Fileのこと。このファイルはプログラムのビルド方法を決めるxmlファイルである。参考 What is the difference between a cbp file and a cpp file?
変更前: <Target title="HELLO"> <Option output="/Users/****/CLionProjects/HELLO/cmake-build-debug/HELLO" prefix_auto="0" extension_auto="0"/> <Option working_dir="/Users/****/CLionProjects/HELLO/cmake-build-debug"/> と <Target title="HELLO/fast"> <Option output="/Users/****/CLionProjects/HELLO/cmake-build-debug/HELLO" prefix_auto="0" extension_auto="0"/> <Option working_dir="/Users/****/CLionProjects/HELLO/cmake-build-debug"/> 変更後: <Target title="HELLO"> <Option output="/Users/****/CLionProjects/HELLO/cmake-build-debug/my_dir/HELLO" prefix_auto="0" extension_auto="0"/> <Option working_dir="my_dir"/> と <Target title="HELLO/fast"> <Option output="/Users/****/CLionProjects/HELLO/cmake-build-debug/my_dir/HELLO" prefix_auto="0" extension_auto="0"/> <Option working_dir="my_dir"/>