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

A 回答 (3件)

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



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

で、xに1、yに2が入ります。
    • good
    • 5
この回答へのお礼

ご回答ありがとうございました。
一番シンプルで分かりやすかったので、ベストアンサーにさせていただきます。

お礼日時:2011/04/17 11:55

おっと!


1行目と2行目を読み飛ばす、っていうコードを追加する必要があるぞ!
    • good
    • 3
この回答へのお礼

ご回答ありがとうございました。

お礼日時:2011/04/17 11:55

こんな感じですね。



char s[256];
fscanf(stream, "%*[^\n]%*c%*[^\n]%*c%255s", s);

バッファのサイズは適当に調整してください。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございました。
参考にさせていただきます。

お礼日時:2011/04/17 11:48

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

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

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

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

Qファイルから読みこむ方法

Unix C++でファイルから、特定の行を読みこむことは可能でしょうか。
例えば、5行目から最後の行まで。10行目から20行目。等。

Aベストアンサー

 CやC++には、テキストファイルから指定した行を読み込むという関数は用意されていません。
 ですので、ファイル先頭から行単位で読んでいき、読んでいる行数を変数でカウントしながら、目的の行だけ配列に入れるなどの処理を行うことになります。

 行単位の読み込みは、istream系オブジェクトに用意されたgetlineメソッドで行えばよいでしょう。

#include <iostream.h>
#include <fstream.h>

int main(void)
{
  ifstream fin;
  int s = 10;   // 先頭からなら 1 を指定する
  int e = 20;   // 末尾までなら -1 を指定する
  const int bufsize = 256;
  char buf[bufsize];

  fin.open("xxx", ios::in | ios::nocreate);
  if (fin.fail()) {
    cerr << "ファイルを開けません\n";
    return 1;
  }
  for (int i = 1; i < s; i++)   // 読み飛ばし
    fin.getline(buf, bufsize);
  for (int i = s; i<=e || (e==-1 && !fin.eof()); i++) {
    fin.getline(buf, bufsize);
    cout << buf << endl;
  }
  fin.close();

  return 0;
}

 ところで、これまでの回答には何の補足もお礼もありませんが、解決はしたのですか?未解決なら分からないところを書かないと、新しい回答は書きにくいものですよ。

 CやC++には、テキストファイルから指定した行を読み込むという関数は用意されていません。
 ですので、ファイル先頭から行単位で読んでいき、読んでいる行数を変数でカウントしながら、目的の行だけ配列に入れるなどの処理を行うことになります。

 行単位の読み込みは、istream系オブジェクトに用意されたgetlineメソッドで行えばよいでしょう。

#include <iostream.h>
#include <fstream.h>

int main(void)
{
  ifstream fin;
  int s = 10;   // 先頭からなら 1 を指定する
...続きを読む

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() 関数で取得可能です。
 ※なおバイナリモードでオープンして下さ...続きを読む

Qfscanf関数について

--------------------------------------------------
#include<stdio.h>
#include<stdlib.h>
int main()
{
FILE*fp;
int ch,dt;
char ss[80];

if((fp=fopen("bbb.txt","w"))==NULL){
printf("出力ファイルをオープンできません.\n");
exit(1);
}

fprintf(fp,"%c",'A');
fprintf(fp,"%s\n","abcdeABCDE");
fprintf(fp,"%d\n",1234);
fclose(fp);

if((fp=fopen("bbb.txt","r"))==NULL){
printf("入力ファイルをオープンできません.\n");
exit(1);
}

ch=fgetc(fp);
printf("ch=%c\n",ch);

fscanf(fp,"%s",ss);
printf("ss=%s\n",ss);

fscanf(fp,"%d",&dt);
printf("dt=%d\n",dt);

fclose(fp);

return 0;
}
--------------------------------------------------

以上のプログラムで、プログラムの通り「bbb.txt」は、

AabcdeABCDE
1234

となっております。
そこで疑問なのですが、「ch=fgetc(fp);」は1文字読み込みなので、'A'だけと分かるのですが、「fscanf(fp,"%s",ss);」はfpからの読み込みで何故、

AabcdeABCDE
1234

の全部を読み込まず、'A'を抜かした、「abcdeABCDE」だけを読み込んでくれるのか?
後、「fscanf(fp,"%d",&dt);」は何故「AabcdeABCDE」を抜かした、「1234」だけを読み込んでくれるのかが分かりません。
「fscanf(fp,"%d",&dt);」については数値だけを読み込んでくれるのかと思い、

ch=fgetc(fp);
printf("ch=%c\n",ch);

fscanf(fp,"%s",ss);
printf("ss=%s\n",ss);

の部分を無くせば、「1234」だけを読み込んでくれるのかと思ったのですが、数値は正しく表示されません。

以上教えていただければ嬉しいです。

--------------------------------------------------
#include<stdio.h>
#include<stdlib.h>
int main()
{
FILE*fp;
int ch,dt;
char ss[80];

if((fp=fopen("bbb.txt","w"))==NULL){
printf("出力ファイルをオープンできません.\n");
exit(1);
}

fprintf(fp,"%c",'A');
fprintf(fp,"%s\n","abcdeABCDE");
fprintf(fp,"%d\n",1234);
fclose(fp);

if((fp=fopen("bbb.txt","r"))==NULL){
printf("入力ファイルをオープンできません.\n");
exit(1);
}

ch=fgetc(fp);
printf("ch=%c\n",c...続きを読む

Aベストアンサー

>%dは空白分を読み飛ばすとわかったのですが、以上のプログラムでも正常に動いたので、「%s」も空白文を読み飛ばしてくれるのですかね?

話が逆。

「空白(改行も含む)が読めるのは、%cだけ」ってのが本質。

「%cだけは、空白(改行も含む)の読み飛ばしをせず、今読める文字を1文字読むだけ」になっているのです。

今読める文字が空白だろうが改行だろうが1だろうがAだろうが、とにかく1文字読むだけです。

「%c」以外の「%d」や「%s」や「%何とか」は「まず、空白(改行も含む)を読み飛ばし、空白(改行も含む)以外の何かが出て来たら、読み込みを開始」します。そして「読み込めない文字(空白や改行も)が出て来たら、そこでヤメ」にします。

まとめると

・%cは、とにかく1文字読む。読み飛ばしとかはしない。

・%c以外は、とにかく、空白と改行を読み飛ばしてから読み込みを開始し、空白や改行が出て来たら読み込みをヤメる。

scanf(やfscanf)は「上記の2点がすべて」です。

「%dは~」とか「%sは~」とか、書式指定子個別に悩んではいけません。本質を把握すれば「みんな一緒」で、悩む必要はありません。

>%dは空白分を読み飛ばすとわかったのですが、以上のプログラムでも正常に動いたので、「%s」も空白文を読み飛ばしてくれるのですかね?

話が逆。

「空白(改行も含む)が読めるのは、%cだけ」ってのが本質。

「%cだけは、空白(改行も含む)の読み飛ばしをせず、今読める文字を1文字読むだけ」になっているのです。

今読める文字が空白だろうが改行だろうが1だろうがAだろうが、とにかく1文字読むだけです。

「%c」以外の「%d」や「%s」や「%何とか」は「まず、空白(改行も含む)を読み飛ばし...続きを読む

QC言語で複数列のデータを1列のみ読み込みたい

行m列の任意のデータの処理を行うプログラムで,
列ごとの統計を行うためにm列目のデータを取り出したいのですが,うまくいきません.
どのようなコードを書けばいいでしょうか?

自分で作ってみたのは以下のようなプログラムです(ファイルを開いて→m列目の読み込みの部分)
EOFを使っているためか,行数のiには全データ数が入ってしまいます.


void main (void)
{
FILE* fp;

int i, j;
i=0, j=0;

char FilePath[500];
char Folder[100];
char File[50];

printf("Folder Name:");
scanf("%s",&Folder);

printf("File Name:");
scanf("%s",&File);

sprintf(FilePath,"%s/%s",Folder,File);

if(( fp = fopen (FilePath,"r")) == NULL){
printf("cannot open '%s'\n", FilePath);
exit(1);
} //ここまではうまく動きます


while (fscanf(fp, "%lf", &A[i][0]) != EOF{
i++;
}
while (fscanf(fp, "%lf", &A[0][j]) != EOF){
j++;
}

printf("A[%d][%d]", i, j);
int n, m;              //n,mはこの後for文で使いたいので登場してもらいました
printf("input 'n':");
scanf("%d", &n);
printf("input 'm':");
scanf("%d", &m);

行m列の任意のデータの処理を行うプログラムで,
列ごとの統計を行うためにm列目のデータを取り出したいのですが,うまくいきません.
どのようなコードを書けばいいでしょうか?

自分で作ってみたのは以下のようなプログラムです(ファイルを開いて→m列目の読み込みの部分)
EOFを使っているためか,行数のiには全データ数が入ってしまいます.


void main (void)
{
FILE* fp;

int i, j;
i=0, j=0;

char FilePath[500];
char Folder[100];
char File[50];

printf("Folder Name:");
scanf("%s",&...続きを読む

Aベストアンサー

>どのようなコードを書けばいいでしょうか?

 http://okwave.jp/qa/q7114321.html #3

 読み込み時に配列に格納しないで、
 文字列として1行読み込んでから、(数値化し)配列に格納する例です。

 「m列目のデータ」の前には、m - 1 個の空白があるので、それをカウントし数値化します。
 (ただし、文字列には空白が連続しないこと)

 「実数」を「整数」に、「コンマ」を「空白」に置き換えればよいかと。

 http://www.bohyoh.com/CandCPP/C/Library/fgets.html
 http://www.bohyoh.com/CandCPP/C/Library/atoi.html

Qcsvファイルをfscanfで読み込むと変な文字が出てきます

csvファイルをfscanfで読み込もうとしているのですが
どうしてもおかしな文字が混じってしまいます

例えばcsvファイルのデータが

abc,efg
となっているとします

これを読み込みprintfで表示すると
abc"" efg""

というように表示されてしまいます

csvファイルを普通に開いてもこのような文字はありません
一体どこから沸いて出てくるのでしょうか?

%[^]を使って不要な文字を読み込まないように
%[^"]と記述しましたが
エラー番号c2143とc2059が出てしまいます

何か解決方法はございませんでしょうか?
よろしくお願いします。

Aベストアンサー

まずは、scanfの仕様をマニュアルなどでよく確認しましょう。

> while( ( ret = fscanf( fp, "%[^,],%[^,],%[^,],%[^,],%s", s, &n1, &n2, &f1, &f2 ) ) != EOF ){

最初の%[^,]に対して 「char型の配列」s で受けている(正解)のに、2番目以降が 「char型の配列へのポインタ」&n1, &n2 ...で受けています。これらに&は必要ありません。
手元のgccの実装では、配列のアドレスと、その配列へのポインタのアドレスがたまたま同じだったため、「正常」に動作しました。しかし、これがmalloc等で確保した領域への「char型へのポインタ」と、「『char型のポインタ』へのポインタ」だった場合は違うアドレスになり、正常に動作しません。

次にfscanfの取り込み方に関してです。
[^,]とした場合、**改行文字も取り込みの対象になります**。なので、2行目以降のsには、前入力行で取り込まれなかった改行文字が先頭に付くことになります。
また、1行にカンマが4つ無かった場合は、n1,n2,f1で「その行の改行文字まで+次の行の最初のカンマまで」を取り込みます。
sに改行コードを入れないために「fscanf( fp, " %[^\n,]....」と%の前にスペースを置いて、0個以上の空白文字(改行文字も含む)を読み飛ばします。カンマが足りないときのn1,n2,f1の方は[^\n,]として改行も含まない文字に追加します。

最後に、fscanfの戻り値です。
scanf系では、最終的に取り込んだ値の数を返します。
今回の場合、最後の行のあとに、残った改行がsに入るので、ret=1になります。EOFになるのは、その次のループになります。
一応、上の書式変更で「最後の行の後の改行文字をsに取り込む」ということはなくなりますが、ret==5でない時は正常な取り込みではないので、なんらかのエラー処理が必要でしょう。

fscanfは結構やっかいです。
上の改行もそうです。
取り込みエラーでもファイルの読み込み位置が変わらないので、次のループでまたエラーになる、といったこともあります。
1行単位で処理したい場合は、fgetsで1行読み込み→sscanfで処理 というのが常套手段です。

確認に使ったファイルを貼り付けておきましたので、修正前と修正後でどんな風に動いているか、ご自身で確認してみてください

入力:abc.csv
ab1,ef2,ab3,af4,ab5
bb1,bf2,bb3,bf4
cb1,cf2,cb3,cf4,cb5
zb1,zf2,zb3,zf4,zb5


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

int main(void)
{
FILE *fp;
char *fname = "abc.csv";
/*char s[100];*/
char *s = (char*)malloc(100); /* 比較のため、mallocでの領域確保 */
char n1[100];
char n2[100];
char f1[100];
char f2[100];
char buf[600]; /* fgets用 */
int ret;
int i=0;

fp = fopen( fname, "r" );
if( fp == NULL ){
printf( "%sファイルが開けません\n", fname );
return -1;
}

printf( "s=%p:&s=%p\nn1=%p:&n1=%p\nn2=%p:&n2=%p\nf1=%p:&f1=%p\nf2~%p:&f1=%p\n",
s, &s, n1, &n1, n2, &n2, f1, &f1, f2, &f2 );
/*↓ 1: 修正前, 0:修正後 */
#if 0
while( ( ret = fscanf( fp, "%[^,],%[^,],%[^,],%[^,],%s", s, n1,n2,f1,f2 ) ) != EOF ){
#else
while( fgets( buf,600, fp ) != NULL ) {
ret = sscanf( buf, " %[^,],%[^\n,],%[^\n,],%[^\n,],%s", s, n1,n2,f1,f2 ) ;
#endif
if ( ret != 5) {/* エラー処理 */ }

i ++ ;
printf( "No.%d::\nret=%d\n", i,ret );
printf( "s =%s\nn1=%s\nn2=%s\nf1=%s\nf2=%s\n", s, n1, n2, f1, f2 );
}

fclose( fp );
free(s);
return 0;
}

まずは、scanfの仕様をマニュアルなどでよく確認しましょう。

> while( ( ret = fscanf( fp, "%[^,],%[^,],%[^,],%[^,],%s", s, &n1, &n2, &f1, &f2 ) ) != EOF ){

最初の%[^,]に対して 「char型の配列」s で受けている(正解)のに、2番目以降が 「char型の配列へのポインタ」&n1, &n2 ...で受けています。これらに&は必要ありません。
手元のgccの実装では、配列のアドレスと、その配列へのポインタのアドレスがたまたま同じだったため、「正常」に動作しました。しかし、これがmalloc等で確保した領域への...続きを読む

Qc言語 ファイルから数字を読み込む

c言語初心者です。
forループをつかって、
ファイルから空白で区切られた数字を一つずつ読み込む
プログラムを作りたいのですが、
forループの中をどう書いたらいいかわかりません。

#include <stdio.h>

int main (int argc, char *argv[])
{
char *fileName = argv[1];

FILE *fp = fopen("fileName", "r");

int num;
int i;

for(i=0; i<10; i++){
fscanf(fp, "%d", &num);
printf("%d\n", num);
}
fclose(fp);
}

ファイルの内容は、10個の数字が書かれている設定です。

Aベストアンサー

FILE *fp = fopen("fileName", "r");
は、
FILE *fp = fopen(fileName, "r");
でしょうね。
他はいいと思いますが。

細かいことを言うと、argv[1] を参照する前に、argcの値をチェックすべき。

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が...続きを読む

Qscanf("%s", buf);でスペースを含んだ文字

コンソールプログラムで
scanf("%s", buf);
を使用してユーザに入力された文字によって処理を行いたいのですが、このままではスペースを含む文字列がスペースの手前で切られてしまいます。
C:\Program Filesなどを入力可能にさせたい場合にはどのようにするのがベターですか?

Aベストアンサー

お任せください!
そもそもscanfを使うというのはお勧めでは
ありません。scanfは文字+改行文字が入力
されないと完了しないためです。
が、それは良しとしましょう。
scanfの書式ですが、

int n = scanf("%[^\r\n]",buf);

という便利な書式があります。
perlでもおなじみの書式ですね。
上記の山文字"^"より前が読み込ませたい文字の集まりで、ハイフン指定が出来ます。
"^"より後ろが読込みを停止させたい文字の集まりです。上記の指定は復帰改行以外の文字が現れるまで読み込みます、という書式です。
下記のような指定も出来ます。

int n = scanf("%[a-zA-Z0-9\\: \t^\r\n]",buf);

なお、戻り値は読み込んだ項目数ですので、
if(n >= 1)
{
}
で判断できますね。

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言語で配列Array[N]の長さNの上限っていくらなんでしょうか?
もし可能なのであれば上限を2147483647にしたいのですが、方法を教えてください。

Aベストアンサー

そもそもWindowsの32bit版はアプリが仮想メモリ空間を2GBしか使えません。2GBを超えるには64bit版が必要です。
たとえ64bit版OSだとしても添え字が2147483647って、単純なintの配列だとしても4x2147483647=8GB必要ですね。実メモリ16GBとかのPCを用意しますか?
そもそも配列で2147483647個必要なアルゴリズムに問題ありだと思います。


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

人気Q&Aランキング

おすすめ情報