C言語初心者です。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
じゃがバター

C言語初心者です。

#1

投稿記事 by じゃがバター » 9年前

C言語に関する質問です。

csvファイルを読み込んで、そのデータを降順に並び替えて別ファイルに保存するプログラムについて教えてください。

佐藤 1.5 2 4.2 12
鈴木 1.2 5 4.8 15
高橋 1.4 7 4.4 11

というcsvファイルがあるとして、この4.2・4.8・4.4を降順に並び替え、
それに応じて他の要素も入れ替え、新たにcsvファイルを作成し保存するには
どのようなプログラムになりますか?

最終的に以下のようになれば良いのですが。
鈴木 1.2 5 4.8 15
高橋 1.4 7 4.4 11
佐藤 1.5 2 4.2 12

コード:


#include<stdio.h>

#define NUMBER 200

typedef struct{
  char s1[100]
  int n1, n2;
  float f1, f2;
}test;

int main (void)
{
  FILE *fp;
  char fname[20];
  int n=0;
  test base[NUMBER];

  printf("ファイルを入力してください。:");
  scanf("%s",fname);

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

  while(fscanf( fp, "%[^,],f1,n1,f2,n2",
                    base[n].s1,&base[n].f1,&base[n].n1,
                    &base[n].f2,&base[n].n2)!=EOF){

        printf("%s,%f,%d,%f,%d",
                 base[n].s1,base[n].f1,base[n].n1,
                 base[n].f2,base[n].n2);
  }

  fclose(fp);
  return 0;

}

ファイルを読み込むまでのプログラムは何とか出来たのですが、
ここから降順に並び替えて新たなファイルを作成し書き込むプログラムが分かりません。

使用しているのはwindows、Microsoft Visual C++ 2010 Expressです。

C言語初心者の質問ですみません。
よろしくお願いします。

box
記事: 2002
登録日時: 14年前

Re: C言語初心者です。

#2

投稿記事 by box » 9年前

じゃがバター さんが書きました: csvファイルを読み込んで、そのデータを降順に並び替えて別ファイルに保存するプログラムについて教えてください。

佐藤 1.5 2 4.2 12
鈴木 1.2 5 4.8 15
高橋 1.4 7 4.4 11

というcsvファイルがあるとして、
csvとおっしゃっている割にはカンマ区切りになっていないのは何か理由がありますか?
じゃがバター さんが書きました: ファイルを読み込むまでのプログラムは何とか出来たのですが、
本当ですか?
じゃがバター さんが書きました:

コード:

  while(fscanf( fp, "%[^,],f1,n1,f2,n2",
f1,n1,f2,n2
というのは書式文字列として成立していないように見えるのですが…。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: C言語初心者です。

#3

投稿記事 by みけCAT » 9年前

box さんが書きました:f1,n1,f2,n2
というのは書式文字列として成立していないように見えるのですが…。
「f1,n1,f2,n2」は「f1,n1,f2,n2」という文字列にマッチする有効な書式文字列です。
ただし、今回のプログラムには適さないでしょう。
N1256 7.19.6.2 The fscanf function さんが書きました: 6 A directive that is an ordinary multibyte character is executed by reading the next
characters of the stream. If any of those characters differ from the ones composing the
directive, the directive fails and the differing and subsequent characters remain unread.
Similarly, if end-of-file, an encoding error, or a read error prevents a character from being
read, the directive fails.
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: C言語初心者です。

#4

投稿記事 by みけCAT » 9年前

じゃがバター さんが書きました: ファイルを読み込むまでのプログラムは何とか出来たのですが、
ここから降順に並び替えて新たなファイルを作成し書き込むプログラムが分かりません。
まずは読み込んだ内容をそのまま新たなファイルに書き込むプログラムを作りましょう。
オフトピック
ここに貼ってあるのが出来た「ファイルを読み込むまでのプログラム」だとは言ってない。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: C言語初心者です。

#5

投稿記事 by みけCAT » 9年前

オフトピック
ファイルが開けなかった時に、fopenから返ってきたNULLをそのままfscanfに突っ込むのは良くない気がするなあ…
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

じゃがバター

Re: C言語初心者です。

#6

投稿記事 by じゃがバター » 9年前

box さんが書きました:csvとおっしゃっている割にはカンマ区切りになっていないのは何か理由がありますか?
失礼しました。その通りですね。
訂正します。
佐藤,1.5,2,4.2,12
鈴木,1.2,5,4.8,15
高橋,1.4,7,4.4,11
みけCAT さんが書きました:まずは読み込んだ内容をそのまま新たなファイルに書き込むプログラムを作りましょう。
今作ってみましたが、こんな感じでいいのでしょうか?
一応、新たなファイルの作成は出来ました。

コード:

#include<stdio.h>

#define NUMBER 200

typedef struct{
  char s1[100];
  int n1, n2;
  float f1, f2;
}test;

int main (void)
{
  FILE *fp, *sf;
  char fname[20], sname[20];
  char str[256];
  test base[NUMBER];

  printf("開くファイル名を入力してください。:");
  scanf("%s",fname);

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

  printf("作成するファイル名を入力してください。:");
  scanf("%s",sname);

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

  while(fgets(str,256,fp))
  {
     printf("%s",str);

     fputs(str,sf);
  }

  fclose(sf);

  fclose(fp);

  return 0;
}

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: C言語初心者です。

#7

投稿記事 by みけCAT » 9年前

なるほど、確かに

コード:

中村,1.0,5,4.7,15
のような小数点以下に0がある場合も「そのまま」出力できるいいプログラムですね。

次は、入力ファイルの内容を一旦行ごとに線形リストまたは配列に格納し、その格納した内容を新しいファイルに書き込むプログラムを作ってみてください。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

じゃがバター

Re: C言語初心者です。

#8

投稿記事 by じゃがバター » 9年前

みけCAT さんが書きました:次は、入力ファイルの内容を一旦行ごとに線形リストまたは配列に格納し、その格納した内容を新しいファイルに書き込むプログラムを作ってみてください。
遅くなりました。
丁寧にありがとうございます。

ここまで作ったのですが、上手くいきません。
配列の表示と、新しいファイルの作成は出来たのですが、
ファイルの中は空っぽで、数字が大量に羅列されプログラムが停止してしまいます。
どこを直したら良いでしょうか?

コード:

#include<stdio.h>
#include<math.h>
 
#define NUMBER 200
 
typedef struct{
  char s1[100];
  int n1, n2;
  float f1, f2;
}test;
 
int main (void)
{
  FILE *fp, *sf;
  char fname[20], sname[20];
  char str[256];
  int i, j, t=0;
  test base[20];
  test data;
 
  printf("開くファイル名を入力してください。:");
  scanf("%s",fname);
 
  fp = fopen(fname, "r");

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

  printf("作成するファイル名を入力してください。:");
  scanf("%s",sname);
 
  sf = fopen(sname, "w");
  if(sf == NULL){
    printf("%sファイルが開けません\n");
    
  }
 

  while(fscanf( fp, "%[^,],%f,%d,%f,%d\n",
                    base[t].s1,&base[t].f1,&base[t].n1,&base[t].f2,&base[t].n2)!=5){

        printf("%s,%f,%d,%f,%d",
                    base[t].s1,&base[t].f1,&base[t].n1,&base[t].f2,&base[t].n2);
  
  {t++;}
  }

  for(i=0; i<5; ++i){
   for(j=i+1; j<5; ++j){
   if(base[i].f2<base[j].f2){
   data=base[i];
   base[i]=base[j];
   base[j]=data;
   }
  }
  }
 
 
  fclose(sf);
 
  fclose(fp);
 
}


アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: C言語初心者です。

#9

投稿記事 by みけCAT » 9年前

とりあえずインデントを整えるのと、while文の条件式を修正するのがいいと思います。
現状の「fscanfの戻り値が5でない」という条件だと、最初に入力エラーがあった場合無限ループになってしまいます。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: C言語初心者です。

#10

投稿記事 by みけCAT » 9年前

  • 35行目: 書式文字列に対してデータが足りない
  • 44行目: 第3引数~第6引数の型が違う
これらの間違いはundefined behaviorになります。

また、ファイルが開けなかった場合にfscanfの第1引数にNULLが渡されるのもまずいかもしれません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

box
記事: 2002
登録日時: 14年前

Re: C言語初心者です。

#11

投稿記事 by box » 9年前

じゃがバター さんが書きました: ファイルの中は空っぽ

コード:

  FILE *fp, *sf;
  char fname[20], sname[20];
  printf("作成するファイル名を入力してください。:");
  scanf("%s",sname);
  sf = fopen(sname, "w");
  fclose(sf);
sfに書き込んでいる形跡がないからです。
sfに対してfprintfしないと…。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

閉鎖

“C言語何でも質問掲示板” へ戻る