2016-07-14 10 views
2

にフロートと文字の混合物を読むためにだから私は、次の通りであるの.txtファイルを持っている:関数fscanfはC

私は3つの変数、都市、説明と価格に格納されている情報を取得したい
** Paris ** Flight,5 days,visiting various monuments. | 2999.99 | 
** Amsterdam ** By bus,7 days, local art gallery. | 999.99 | 
** London ** Flight,3 days,lots of free time. | 1499.99 | 

、しかし、私はラインをまったく救うことができません。

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

int main() 
{ 
    FILE *fp; 
    char city[256],desciption[256]; 
    float temp; 
    if(fp=fopen("Ponuda.txt","rt")==NULL){ 
     printf("ERROR\n"); 
     exit(1); 
    } 

    while(fscanf(fp,"** %s ** %s | %f |",city,description,&temp)==3){ 

     printf("** %s ** %s |%f|\n",city,description,temp); 
    } 
    return 0; 
+0

は '%のS'はわずか1つの単語を読み込みます。あなたはそれを使って説明全体を読むことはできません。 – Barmar

+0

「ニューヨーク」のように1単語以上の都市にも問題があります。 – Barmar

+0

私は、私が間違ったアプローチをしているように見えます。 – Rowry

答えて

2

IMO fgetsと、各ファイルの行を読み、[区切り文字列"*|"と各ラインを分割するstrtokを使用する方がはるかに簡単です。

それから私は、構造体の中にテキスト文字列を複製するstrdupを使用し、そして、それは内部的にmallocを呼び出すように私は、strdupからの戻り値をテストしている必要があります。第三トークンからの運賃を抽出するsscanf

私も詐欺がある場合、私はのみを使用しますdouble代わりのfloatを(使用しますひずみ)。

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

#define MAX 10 

typedef struct { 
    char *city; 
    char *descrip; 
    double fare; 
} flight_t; 

int main() 
{ 
    FILE *fp; 
    flight_t visit[MAX] = {0}; 
    char buffer [1024]; 
    char *tok; 
    int records = 0, i; 
    if((fp = fopen("Ponuda.txt", "rt")) == NULL) { 
     printf("Error opening file\n"); 
     exit(1); 
    } 

    while(fgets(buffer, sizeof buffer, fp) != NULL) { 
     if((tok = strtok(buffer, "|*")) == NULL) { 
      break; 
     } 
     if(records >= MAX) { 
      printf("Too many records\n"); 
      exit(1); 
     } 
     visit[records].city = strdup(tok);   // add NULL error checking 

     if((tok = strtok(NULL, "|*")) == NULL) { // pass NULL this time 
      break; 
     } 
     visit[records].descrip = strdup(tok);  // add NULL error checking 

     if((tok = strtok(NULL, "|*")) == NULL) { // pass NULL this time 
      break; 
     } 
     if(sscanf(tok, "%lf", &visit[records].fare) != 1) {  // read a double 
      break; 
     } 
     records++; 
    } 

    fclose(fp); 

    // print the records 
    for(i = 0; i < records; i++) { 
     printf("** %s ** %s |%.2f|\n", visit[i].city, visit[i].descrip, visit[i].fare); 
    } 

    // free the memory given by strdup 
    for(i = 0; i < records; i++) { 
     free(visit[i].city); 
     free(visit[i].descrip); 
    } 
    return 0; 
} 

プログラムの出力:

** Paris ** Flight,5 days,visiting various monuments. |2999.990000| 
** Amsterdam ** By bus,7 days, local art gallery. |999.990000| 
** London ** Flight,3 days,lots of free time. |1499.990000| 
+0

まさに私が必要としていたもの、多くのことを学んだ、ありがとう! – Rowry

+0

私が分かりませんが、区切り記号 "| *"はどういう意味ですか? – Rowry

+0

['strtok' man page](https://msdn.microsoft.com/en-us/library/2c8d19sb.aspx)を読むことをお勧めします。それは文字の*セット*であり、そのいずれかが文字列を任意の組み合わせで分割します。 –

1

これは@Barmarが指摘したように、都市名が複数の単語であってもよいし、以来、単一関数fscanf文で行うことは非常に困難です。 (fgetsを使用して)行全体を読み込んだ後で、自分自身で行を解析する方がはるかに簡単です。それを解析するには、次の

  1. は、後の最初の非空白文字を検索する「**」
  2. "が先行しているの後、最後の非空白文字を、検索**」
  3. それらのインデックス間のテキストを意志
  4. 説明は、手順2で見つかった "**"と次の "|"の間のテキストです。その後は
  5. コストはそれに続く文字列です '|'