ファイルの中の行数をカウントするにはどうすればよいか
プログラムの行数ならその行数分だけ
またコメントや空白行もカウントするにはどうしたらよいか
以下のプログラムに追加したい場合どうしたらよいか教えてください。

#include <stdio.h>

int main(int argc , char *argv[]){

char s[256];
int i;
FILE *fin;
int local;
int nCount = 0;

for(i = 1 ; i < argc ; i++){

printf("%s\n",argv[i]);
local = 0;

fin=fopen(argv[i],"r");

memset(s,0,sizeof s);
while(fgets(s,sizeof s,fin) != NULL){
//printf("%s",s);
local++;
nCount++;
}
memset(s,0,sizeof s);
while(fgets)
printf("local count = %d\n",local);

fclose(fin);

}
printf("grobal count = %d\n",nCount);
return 0;
}

A 回答 (1件)

だいたいあってるようですが…。



[単純な行数カウントについて]
・fopen()でエラーが起こった時の対応が無い
・fgets()は'\0'を付加するためmemset()は不要
・fgets()が“1行を読みこむ”ことを期待してはいけない
fgets()は「第3引数で示した文字数-1」を超える文字数の行については分割して読みこまれるため、行は'\n'の有無で判断するべき('\n'無しでEOFの時は当然1行)
・2つ目のmemset()とwhile(fgets)は意味不明(というかwhile(fgets)は終了しないのでは?)

[空行、コメント行について]
仕様が不備で答えられません
・空白行とは何をさすか('\n'のみの行で良いか)
・コメント行とは何を指すか(C/C++のコメントで良いか)
・非コメントとコメントが1行にある場合はどちらにカウントするか(a++ ;/* インクリメント */などの場合)
・文字列定数中に改行が含まれる場合は行と認識するか
"a

b
c"
この場合、空行と改行が含まれる

仕様としてはこの程度は明確になっていないとプログラムは作れません。
    • good
    • 0

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

このQ&Aを見た人はこんなQ&Aも見ています

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

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

Qテキストファイルの行数を取得する方法(C言語

C言語でテキストファイルのトータル行数を取得する関数又はその方法を教えてほしいのですが。

宜しくお願いします。

Aベストアンサー

>C言語でテキストファイルのトータル行数を取得する関数又はその方法を教えてほしいのですが。

 3つ前の質問 http://okwave.jp/qa5129642.html 質問文中のソース冒頭 line2++; 部分(下に修正したもの掲載)で、

・テキストファイルの行数を、ファイルの頭から1行ずつ「読み捨て」て、それをファイル終端まで繰り返すことで数えています。

 ここでは、「全体として、どの位メモリを確保したらいいか」という動機から、超みっともない?こと(読み捨て、1ファイルを2度オープン)をしています。
  (本人には、http://okwave.jp/qa5114580.html の No.3 で指摘済み)
 1行ずつ読み込みながら、1行分のメモリを追加確保していくのが普通だと思うのですが・・。

・エディタでファイルを開けば判ることを、わざわさプログラムにする理由はなく、(質問文には現れない)主目的との「兼ね合い」でご質問された、と思います。
・「何々したいから、プログラムの冒頭で、ファイルのトータル行数を取得しておきたい」の「何々」部分を明らかにすれば、「兼ね合い」を解消する技法について「回答」が得られるかもしれません。

もし、上の質問者様と同様な動機でしたら、少なくとも、「エディタでファイルを開き、行数を確認」し、プログラム実行時にコマンドラインで、argv[ 2 ] に行数が入るようにして下さい。
超みっともない「読み捨て、1ファイルを2度オープン」は不要となります。

プログラムでは、line2 = atoi( argv[ 2 ] ); とすることで、行数を得ることができます(ファイル名は、argv[ 1 ] で)
----------------------------------------------
直球回答

int line2 = 0;
char buf[ 1024 ]; // 最大レコード長より大きいこと
FILE *fp;

if( NULL == ( fp = fopen( argv[ 1 ], "r" ) ) ){

 printf( "%s が開けません\n", argv[ 1 ] );

 return( -1 );
}
while( NULL != fgets( buf, 1024, fp ) ){

 line2++;
}
fclose( fp );

>C言語でテキストファイルのトータル行数を取得する関数又はその方法を教えてほしいのですが。

 3つ前の質問 http://okwave.jp/qa5129642.html 質問文中のソース冒頭 line2++; 部分(下に修正したもの掲載)で、

・テキストファイルの行数を、ファイルの頭から1行ずつ「読み捨て」て、それをファイル終端まで繰り返すことで数えています。

 ここでは、「全体として、どの位メモリを確保したらいいか」という動機から、超みっともない?こと(読み捨て、1ファイルを2度オープン)をしています。...続きを読む

Q”行数のカウント”はどうすればいいのでしょうか? 

 共立出版の”プログラム言語C 第2版”p24に
以下のプログラムが書いてありますが、

#include <stdio.h>

/*入力の行数をカウント*/
main()
{
int c, nl;

nl = 0;
while ((c = getchar()) != EOF)
if (c == '\n')

++nl;
printf("%d\n", nl);
}

これをgccでコンパイルして
./***で実行しても 何もでてきません。
更にこの実行コマンドの次に 任意のファィルを指定しても 何も実行されません。
 前のページの ”ファィルの複写” ”文字のカウント” のプログラムも こんな風に 何も実行されません。
 c言語の初歩なのでしょうが、この本の ここで つまずいては 前に 進めません。”ふつうのlinuxプログラミング”を読んでいたのですが、初歩が分からないと、理解できないと 考えて この本を読んでいました。
 このコードあたりから 実行が展開されないので 困っています。gccはfedora4のものを使用しています。
 尚、windosのcについては 関心がありません。多分ライブラィの互換がとれなくて ほとんどんのコードがエラーになってしまいます。

 共立出版の”プログラム言語C 第2版”p24に
以下のプログラムが書いてありますが、

#include <stdio.h>

/*入力の行数をカウント*/
main()
{
int c, nl;

nl = 0;
while ((c = getchar()) != EOF)
if (c == '\n')

++nl;
printf("%d\n", nl);
}

これをgccでコンパイルして
./***で実行しても 何もでてきません。
更にこの実行コマンドの次に 任意のファィルを指定しても 何も実行されません。
 前のページの ”ファィルの複写” ”文字のカウ...続きを読む

Aベストアンサー

入力はコマンドラインでファイル名を指定する形で与えるのではなく、
リダイレクトでおこなうのではないですか?
普通に実行すると、多分キーボードからの入力待ちになりそうな気がするんですが(^Dをタイプでそれまで入力した行数が出力される)。

./a.out < 入力ファイル
cat 入力ファイル | ./a.out

のようにしてやれば良いのではないでしょうか?

QC言語 ファイルの指定された行を表示

こんにちは。
回答お願いします。
今私は作業の高効率化を目指すためプログラムを考えています。
まだぜんぜんできていませんが・・
ファイルの指定された行を表示する関数がないだろうか?
もしくは似たような方法はないだろうかと考えています。

できれば例題とともに教えていただければ幸いです。
具体的にどういう風にしたいのかというと
----test.txt-------
aaaa
bbbbb
cccccc
dddd
eeeeeeee
ffffff
-------------------
というファイルがあったとしたらgetsで4と入れてやったら
四行目のddddが表示されるようにしたいのです。
まだまだ初心者ですのでさっと考えることができません。
どうかご教授お願いします。

Aベストアンサー

★高効率を目指しているの?
・固定長データなら高効率で1行を取得できたりします。
 例えば
 ----test.txt-------
 aaaaa
 bbbbb
 ccccc
 ddddd
 eeeee
 fffff
 -------------------
 という固定長データ(5文字×6行)の場合は
 int no = 4; ←4行目を取得したい時
 fseek( fp, ((no - 1) * 7), SEEK_SET ); ←5文字+\r+\n=『7』
 fgets( buff, sizeof(buff), fp );
 ↑
 これなら行番号で指定した1行を fgets() 関数で取得可能です。
 ※なおバイナリモードでオープンして下さい。
・可変長データの場合は行の先頭のオフセット位置を最初の読み込みで管理します。
 例えば
 ----test.txt-------
 aaaa
 bbbbb
 cccccc
 dddd
 eeeeeeee
 ffffff
 -------------------
 という可変長データ(4,5,6,4,8,6文字)の場合は
 オフセット位置の配列を行数分用意します。→事前に分かれば楽ですね。行数。
 long offset[ 100 ]; ←100行だと仮定
 int max;
 
 for ( max = 0 ; !feof(fp) ; max++ ){
  if ( max >= 100 ){ ←安全対策
   break;
  }
  offset[ max ] = ftell( fp );
  fgets( buff, sizeof(buff), fp );
 }
 ↑
 ここまでがオフセット位置の読み込みです。次は読み出しです。
 int no = 4; ←4行目を取得したい時
 fseek( fp, offset[no - 1], SEEK_SET );
 fgets( buff, sizeof(buff), fp );
 ↑
 これで行番号で指定した1行を fgets() 関数で取得可能です。
 ※やっぱりバイナリモードでオープンして下さい。
・あと行数の指定時に 1~max の範囲になるように補正処理も入れたほうが良いかも。
 例えば
 if ( no < 1 ){
  no = 1;
 }
 else if ( no >= max ){
  no = max;
 }
 ↑
 こんな感じで。
・以上を参考にして下さい。
 下の『参考URL』もどうぞ。

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

★高効率を目指しているの?
・固定長データなら高効率で1行を取得できたりします。
 例えば
 ----test.txt-------
 aaaaa
 bbbbb
 ccccc
 ddddd
 eeeee
 fffff
 -------------------
 という固定長データ(5文字×6行)の場合は
 int no = 4; ←4行目を取得したい時
 fseek( fp, ((no - 1) * 7), SEEK_SET ); ←5文字+\r+\n=『7』
 fgets( buff, sizeof(buff), fp );
 ↑
 これなら行番号で指定した1行を fgets() 関数で取得可能です。
 ※なおバイナリモードでオープンして下さ...続きを読む

Qfgetsで拾われる改行文字を削除したい

お世話になります

 C言語初心者のものです。今課題でC言語を用いたプログラミングを
Fedora上でやっています。問題は、fgetsでテキストファイルから、取得
した文字列の中から改行文字を削除できないことです。文字変数のアド
レスはわかっているのですが、終端文字に置換しようとすると、セグメ
ントエラーになってしまいます。これは如何にして解決すべきでしょう
か。よろしくお願いします。

Aベストアンサー

ポインタとかアドレスとか、C言語の用語としてあるものを別の意味に使うとまぎらわしいです。

「ポインタ」「アドレス」と言われたら、 この例なら str, str+i が思い浮びます。
「文字変数のアドレス」だと
char c ;
に対しての
&c
が思い浮びます。

配列なら「添字」、意味的には「x文字目」ですね。

> for(i=0;;i++){
> if(*(str+i)=='/n') {
> *(str+i)='\0';
> break;
> }
> }
/nが\nの間違いなら、この方法で半分正解です。もう少し広い範囲(可能なら全体)で見ないことにはなんとも言えません。
fgetsが最大文字数に達したり、ファイルの最後になったりで、strに改行文字が含まれない場合には、このループは止まりません(Segmentension Falutになって止まる)

・そのような状態になってないか、予めチェックする
・ループを終了させる仕組みを用意しておく
: forの終了条件を記述する、for中で if(*(str+i)=='\0') { break;} 等としておく、等
といった対策が必要です。


あと細かいところを言えば
・strを配列で用意したなら *(s+i)じゃなくてs[i]でいいんじゃないかな
・あるいは char *pみたいにしておいて、 iのループでなく pでループを組む( for(p=str;*p!='\0';p++) )とか。

ポインタとかアドレスとか、C言語の用語としてあるものを別の意味に使うとまぎらわしいです。

「ポインタ」「アドレス」と言われたら、 この例なら str, str+i が思い浮びます。
「文字変数のアドレス」だと
char c ;
に対しての
&c
が思い浮びます。

配列なら「添字」、意味的には「x文字目」ですね。

> for(i=0;;i++){
> if(*(str+i)=='/n') {
> *(str+i)='\0';
> break;
> }
> }
/nが\nの間違いなら、この方法で半分正解です。もう少し広い範囲(可能なら全体)で見ないことにはなんとも言えません。
fgetsが...続きを読む

Qファイル出力の場所を指定

現在C++にてhtmlファイルを出力するプログラムを作っているのですが、出力場所を指定することはできるのでしょうか?(現在はそのプログラムソースが保存されている場所と同じファイル内に出力されますが、それをデスクトップに出力するなど。)
もし、方法がありましたら、教えてください。
ソースや参考HPのURLなどのせていただけたらありがたいです。
環境はVisualStudio.NET2003です。
よろしくお願いします。

Aベストアンサー

単にファイル名の前にパスを指定する。

絶対パス指定
fp=fopen("c:/temp/test.txt","w");

相対パス指定
fp=fopen("./hoge/test.txt","w");


デスクトップはOSやユーザによって場所が異なるので、少し面倒です。
XPの場合環境変数を利用してこんな感じで出来ると思います。

例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void main(void)
{
FILE *fp;
char fname[1024];
strcpy(fname,getenv("USERPROFILE"));
strcat(fname,"/デスクトップ/test.txt");
fp=fopen(fname,"w");
//処理
fclose(fp);
}

QC言語のステップ数をカウントするプログラムについて

C言語のステップ数をカウントするプログラムについて教えてください。空白行・コメント行・実行行・そして全ステップ数をカウントします。全ステップ数については以下のように考えましたが空白行、コメント行をどのようにしたらよいかわかりません。ご指導宜しくお願いいたします。

※コメント行は// や/* */を対象にします
※空行はタブと改行のみの行も含みます

#include<stdio.h>
#include<stdlib.h>

int main()
{
int linecnt; //行数
   int a;
   FILE *fp;

   fp = fopen("test.txt", "r");
if(fp == NULL){
printf("入力ファイルがオープン失敗\n");
exit(1);
}

linecnt = 1;

while(feof(fp) ==0){
a = fgetc(fp);
linecnt++;
}

printf("全ステップ数 = %d", linecnt);

return 0;
}

C言語のステップ数をカウントするプログラムについて教えてください。空白行・コメント行・実行行・そして全ステップ数をカウントします。全ステップ数については以下のように考えましたが空白行、コメント行をどのようにしたらよいかわかりません。ご指導宜しくお願いいたします。

※コメント行は// や/* */を対象にします
※空行はタブと改行のみの行も含みます

#include<stdio.h>
#include<stdlib.h>

int main()
{
int linecnt; //行数
   int a;
   FILE *fp;

   fp = fope...続きを読む

Aベストアンサー

下記のサイトにソースを投稿しましたので参照にしてください。
http://climbi.com/b/8059/0

今回の質問は、C言語のソース解析を行いますが、厳密に行おうとするとC言語のコンパイラ
が行っている構文解析と同等の処理が要求されます。
それなので、簡易版の形で書いてみました。(バグがあるかもしれませんの自己責任でご使用ください)
作成方針は以下の通り。
1.1行の長さは1024バイト以内が前提
2.コンパイルが正常に完了したソースであることが前提
3.コメントの扱いは以下の通り
  /*から*/までをコメントとみなす。(複数行にまたがることを考慮する)
  //以降をコメントとみなす。(1行のみで、複数行にまたがることはない)
4.空白行の扱いは以下の通り
  行の先頭から終端迄、空白、タブのみで構成される行(空白、タブがなくても良い)
  /* から */の間にある空白行は、コメント行として扱う
5.上記3,4以外の文字が出現した場合、実行文とみなす。
6.ダブルクオート(")ではさまれた文字列中に、/*、*/、//等があってもコメントとは扱わず
  普通の文字列として扱う。
  例
  "aascii// abcd " はコメントではない
  "/* abcd */" はコメントではない
7.ダブルクオート(")の終端は\で修飾されないダブルクオート(")とする。
  例
  "abc" 最後"がダブルクオート終端
  "ab\"" 最後の"がダブルクオート終端
  "ab\"a\"a" 最後の"がダブルクオート終端
  "a\\" 最後の"がダブルクオート終端
8.シングルクオート(')で挟まれたダブルクオートは普通の文字として扱う。
  例
  '"'  普通のデータ(上記6,7の扱いをしない)
  '\"'  同上

9.各行のカウントは以下の通り
  コメントのみで構成させれる行をコメント行としてカウントする
  空白行のみで構成させれる行を空白行としてカウントする
  上記以外を実行行としてカウントする

尚、実際にソースステップをカウントするツールがあるので、それと比較してみました。
下記サイトのRakuStepCounterをダウンロードして実行した結果、こちらで作成した結果と同じ結果に
なりました。(多少のソースの比較のみです)
http://www.rakuchinn.jp/rakustepcounter.html

このソースをstep_count.cとして自分自身のソースをカウントすると以下のようになります。
総ステップ数=223
実行行数=184
コメント行数=37
空白行数=2

尚、136行に
printf("%d:%s\n",All_count,type);
がありますが、各行がどの行に属するのかを印字しています。
これが煩わしい場合は、コメントアウトしてください。

下記のサイトにソースを投稿しましたので参照にしてください。
http://climbi.com/b/8059/0

今回の質問は、C言語のソース解析を行いますが、厳密に行おうとするとC言語のコンパイラ
が行っている構文解析と同等の処理が要求されます。
それなので、簡易版の形で書いてみました。(バグがあるかもしれませんの自己責任でご使用ください)
作成方針は以下の通り。
1.1行の長さは1024バイト以内が前提
2.コンパイルが正常に完了したソースであることが前提
3.コメントの扱いは以下の通り
  /*から*/までをコ...続きを読む

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ファイルから入力した文字数をカウントして出力する。

ファイルから入力した文字数をカウントしてファイルに出力するプログラムをVC++のC言語を使ってビルドしたのですが警告が出ます。
何処が拙いのでしょうか?
教えて下さい。
実行環境はOSがWindows Vistaで統合開発環境がVisual C++ 2008です。
C言語初心者なので分かりやすく教えて下さい。

/* count_char.c */
#include <stdio.h>
#include <stdlib.h>/* for exit(); */

int main(int argc, char *argv[])
{
FILE *fin, *fout;
int len;
int ch;
char ss[80];

if (argc != 3) {
printf("引数の数が違います、エラー。用法:count_char fromfile tofile\n");
exit(1);
}

if ((fin = fopen(argv[1], "r")) == NULL) {
printf("読み込みファイル%sがオープン出来ません。\n", argv[1]);
exit(1);
}
if ((fout = fopen(argv[2], "w")) == NULL) {
printf("書き込みファイル%sがオープン出来ません。\n", argv[2]);
exit(1);
}

len = 0;
while ((ch = fgetc(fin)) != EOF) {
len++;
}

sprintf(ss, "文字数=%d\n", len);
fputs(ss, fout);

fclose(fin);
fclose(fout);

return 0;
}

警告の内容は以下の通りです。

1>------ ビルド開始: プロジェクト: count_char, 構成: Debug Win32 ------
1>コンパイルしています...
1>count_char.c
1>c:\vc9\count_char\count_char\count_char.c(16) : warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1> c:\program files\microsoft visual studio 9.0\vc\include\stdio.h(237) : 'fopen' の宣言を確認してください。
1>c:\vc9\count_char\count_char\count_char.c(20) : warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1> c:\program files\microsoft visual studio 9.0\vc\include\stdio.h(237) : 'fopen' の宣言を確認してください。
1>c:\vc9\count_char\count_char\count_char.c(30) : warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1> c:\program files\microsoft visual studio 9.0\vc\include\stdio.h(366) : 'sprintf' の宣言を確認してください。
1>マニフェストをリソースにコンパイルしています...
1>Microsoft (R) Windows (R) Resource Compiler Version 6.0.5724.0
1>Copyright (C) Micros

ファイルから入力した文字数をカウントしてファイルに出力するプログラムをVC++のC言語を使ってビルドしたのですが警告が出ます。
何処が拙いのでしょうか?
教えて下さい。
実行環境はOSがWindows Vistaで統合開発環境がVisual C++ 2008です。
C言語初心者なので分かりやすく教えて下さい。

/* count_char.c */
#include <stdio.h>
#include <stdlib.h>/* for exit(); */

int main(int argc, char *argv[])
{
FILE *fin, *fout;
int len;
int ch;
char ss[80];

if (argc != 3) {
printf("引数の数が違います、...続きを読む

Aベストアンサー

fopen()で警告が出るのはstdio.hを見れば解ると思うのですが、通常
fopen(const char *, const char *);
となっており、宣言とコードが食い違うためと考えられます。

また現在ではfopen_s()を使用することがMicrosoftで推奨されています。
詳細は以下のサイトを御覧ください。

http://msdn.microsoft.com/ja-jp/library/z5hh6ee9(v=VS.80).aspx

Qc言語でのfscanfについて

例えば
------------------
ほげほげ1
ほげほげ2
1,2
2,4
3,8
4,16
------------------
というデータファイルがあったとき3行目からのデータだけを抽出するにはc言語のfscanfでどのように書けばいいでしょうか?
簡単にでかまわないので、どなたか教えてください。

Aベストアンサー

1行目、2行目に空白がないのであれば、

int x,y;
fscanf(fp,"%*s %*s %d,%d ",&x,&y);

で、xに1、yに2が入ります。

QC言語でCSVファイルの行数を読み取りたい

大学で研究のため,プログラミングをしている者です.

現在、外部CSVに実験記録名(SECTION)を記述し,それを読み込んでINIファイルからデータのパラメータ(KEY)を呼び出してに実験システムを動作させています.
プログラムは以下のような構成になっています.都合上、省略してます.
-------------------------------------------------------------------------

// 変数や構造体の宣言
typedef struct Parameter{
int a;
double b;
...
// パラメータが続きます
} Parameter;
Parameter data_value[DATA]; //実験に使用したパラメータの構造体
char data_name[MAX_PATH]; //実験記録名
#define DATA データ数

// 読み出し部
for( int i<0; i<DATA; i++ ){
fscanf( fp, "%s", &data_name ); // EOFを用いたエラーチェックを省略
data_value[i] = getParameter( data_name ); // セクション名を渡して、実験パラメータ構造体を返す関数
}

-------------------------------------------------------------------------

CSVファイルは以下のように実験記録日と時間が記述されたものになります。
-------------------------------------------------------------------------
2012/09/02_10:10:10
2012/09/09_14:10:10
.....
-------------------------------------------------------------------------

INIファイルは以下のように実験記録日と時間をセクション、そのときのパラメータをキーとしたものです.
-------------------------------------------------------------------------
[2012/09/02_10:10:10]
a = 100
b = 61.2
....
[2012/09/09_14:10:10]
.....
-------------------------------------------------------------------------

ただ、この手法だと実験記録をINIファイルとCSVファイルに増やしていくたび(プログラムで処理)に、DATAを変更する必要があり、面倒です。(ちにみにいい結果が得られたときのみ記録するソフトになってます。)
私としては、定数DATAを使わず、CSVファイルから行数を取得したいと思ってます。
そして、パラメータは
Parameter *param = new Parameter[;取得した行数];
のように動的に確保してINIファイルからデータを読み出したいと思ってます.
そこで、あらかじめCSVファイルの行数を取得して、for文の最大値や動的なparamの生成をしたのですが、良い方法はないでしょうか?
友人からは、scanfを2回使って、1回目で行数獲得、獲得した値に基づき動的生成、2回目で実験記録名の読み取りをすればいいといわれたのですが、プログラムとして不細工な気がします。
この手法以外で提案がありましたら、教えていただきたいです。

質問文が長くなってしまい、申し訳ございません.
ご回答よろしくお願い致します.

大学で研究のため,プログラミングをしている者です.

現在、外部CSVに実験記録名(SECTION)を記述し,それを読み込んでINIファイルからデータのパラメータ(KEY)を呼び出してに実験システムを動作させています.
プログラムは以下のような構成になっています.都合上、省略してます.
-------------------------------------------------------------------------

// 変数や構造体の宣言
typedef struct Parameter{
int a;
double b;
...
// パラメータが続きます
} Parameter;
Parameter data_value[DATA]; /...続きを読む

Aベストアンサー

newはC言語に無いですが、同じ事をしたいなら
Parameter *param = calloc(取得した行数, sizeof(Parameter));
ですね。
newというのをC++のつもりで言っているなら、やりたいことを考えるとnewで一括で確保するより、STLのvectorを使ったほうがいいですね。以下、C言語のほうメインで書きます。

> そこで、あらかじめCSVファイルの行数を取得して、for文の最大値や動的なparamの生成をしたのですが、良い方法はないでしょうか?

「"あらかじめ"CSVファイルの行数を取得する」ということをするには、CSVファイルの行数を何らかの方法で数えなくてはなりません。
改行というのはファイルの中に改行を示す文字を入れているだけなので、改行の回数を数えるためには、一度ファイルすべてを読まなくてはなりません。つまり、ご友人の仰る通り行数を調べるためのファイル読み込み、データを入れるためのファイル読み込みの2回のファイル読み込みが必要になります。

実装方針を変えると、1回でも可能になります。
「CSVファイルから実験記録を読みながら不足していたらデータを保存する容量を増やしていく」という方針です。
この場合、配列を使う実装とリストを使う実装の2種類の実装方針があると思います。配列の添字でデータを参照することが多い場合は配列、任意の箇所への挿入や削除が頻繁に行われる場合はリストを使うというのは常識ですが、今回の場合、前者だと予測するので配列での実装になります。もし、リストを使うほうが適切な場合はqueue.hを使うと楽に実装できます。といっても、添字でアクセスしているところはすべてリストを所定の回数たぐるという操作に書きなおしですが。
(参考: http://www.freebsd.org/cgi/cvsweb.cgi/~checkout~/src/sys/sys/queue.h
http://www.jp.freebsd.org/cgi/mroff.cgi?sect=3&subdir=man&lc=1&cmd=&dir=jpman-7.2.2/man&man=LIST_HEAD)

ファイルを読みながらデータを保存する容量を増やし、配列を使う場合、プログラムはこんなかんじになるでしょう。(コンパイルしてみてないのでコンパイルできるかすら保証しませんが)
Parameter *data_value = NULL; //実験に使用したパラメータの構造体
size_t num_data_value = 0, max_data_value = 0;
#define INCREASE_DATA_VALUE_SIZE 1024
char data_name[MAX_PATH]; //実験記録名

// 読み出し部
for (; !feof(fp); num_data_value++){
if (num_data_value >= max_data_value) { // data_valueの容量がなくなったら拡張
max_data_value += INCREASE_DATA_VALUE_SIZE;
data_value = realloc(data_value, max_data_value * sizeof(data_value[0]));
if (data_value == NULL) {
fprintf(stderr, "Error: cannot allocate memory.");
exit(EXIT_FAILURE);
}
}
fscanf( fp, "%s", &data_name );
data_value[num_data_value] = getParameter( data_name ); // セクション名を渡して、実験パラメータ構造体を返す関数
}

以降はnum_data_valueをDATAの代わりに使います。
data_valueを関数で渡すときにはnum_data_valueも一緒に渡すことになります。
普通はdata_value、num_data_value、max_data_valueの3つ組みで構造体を作るかもしれません。

しかしながら、C言語でプログラムを書くには色々とおまじないが多いですし、メモリー周りの問題も簡単に起こせてしまうので個人的にはデータの集計にはPerl Python Rubyなどを使うほうがおすすめでです。今時、PCの性能は昔よりもずっと上がっていますし、スクリプト言語にもJITが実装されているのでファイルI/Oバリバリなことでもさせない限り、そう遅くないですしね。とは言っても、過去の先輩が残していった大量のライブラリーがあったりするとおいそれとスクリプト言語に行く事もできないと思いますが。その場合も、C++を使うことにして、Standard Template Library (STL)を使うと多少は楽になるかもしれません。例えばvectorを使えば何も考えずにメモリーの動的確保から容量の管理、自動的に追加をやってもらえますし、vectorは配列として取り出せますから。

というわけで、C言語で書く場合は不足するたびにreallocでメモリーを確保したら良いと思います。でも、データの集計にはスクリプト言語を使ったほうが楽です。過去の資産がある場合、実はC++を使って、extern "C"でそれを呼び出すようにして、残りはSTLを使うと多少は楽かもしれません。

newはC言語に無いですが、同じ事をしたいなら
Parameter *param = calloc(取得した行数, sizeof(Parameter));
ですね。
newというのをC++のつもりで言っているなら、やりたいことを考えるとnewで一括で確保するより、STLのvectorを使ったほうがいいですね。以下、C言語のほうメインで書きます。

> そこで、あらかじめCSVファイルの行数を取得して、for文の最大値や動的なparamの生成をしたのですが、良い方法はないでしょうか?

「"あらかじめ"CSVファイルの行数を取得する」ということをするには、CSVファイル...続きを読む


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング