2017-08-04 17 views
1

このプログラムは、パイプで区切られたファイルを構造体の配列に読み込むことを想定しています。パイプ区切りファイル*を構造体の配列に読み込むC

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

#define LEN_LINE 160 
#define LEN_NAME 40 
#define MAX_LINES 60 
#define LEAGUE_NAME 5 
#define PARK_NAME 35 
#define TEAM_ADDRESS 40 
#define TEAM_CITY 30 
#define TEAM_STATE 5 
#define ZIP_CODE 10 
#define PHONE_NUMBER 30 
#define WEB_ADDRESS 25 
#define LEN_TEAM 60 

typedef struct 
{ 
    char leagueName[LEAGUE_NAME + 1]; 
    char teamName[LEN_NAME + 1]; 
    char parkName[PARK_NAME + 1]; 
    char teamAddress[TEAM_ADDRESS + 1]; 
    char teamCity[TEAM_CITY + 1]; 
    char teamState[TEAM_STATE + 1]; 
    char zipCode[ZIP_CODE + 1]; 
    char phoneNumber[PHONE_NUMBER + 1]; 
    char webAddress[WEB_ADDRESS + 1]; 


} team_t; 

void displayTeams(team_t teams[], int count); 

int main(void) 
{ 
    team_t teams[LEN_TEAM] = { 0 }; 
    FILE *filePtr; 
    int index, count; 
    char line[LEN_LINE + 1] = {0}; 
    char *startPtr, *endPtr; 

    filePtr = fopen("MLBteams.txt", "r"); 
    if (filePtr == NULL) 
    { 
     printf("Error in opening file\n"); 
    } 
    else 
    { 
     index = 0; 
     while (index < LEN_TEAM && fgets(line, sizeof(line), filePtr)) 
     { 
      startPtr = line; 
      endPtr = strchr(startPtr, '|'); 
      strncpy(teams[index].leagueName, startPtr, endPtr - startPtr); 

      startPtr = endPtr + 1; 
      endPtr = strchr(startPtr, '|'); 
      strncpy(teams[index].teamName, startPtr, endPtr - startPtr); 

      startPtr = endPtr + 1; 
      endPtr = strchr(startPtr, '|'); 
      strncpy(teams[index].parkName, startPtr, endPtr - startPtr); 

      startPtr = endPtr + 1; 
      endPtr = strchr(startPtr, '|'); 
      strncpy(teams[index].teamAddress, startPtr, endPtr - startPtr); 

      startPtr = endPtr + 1; 
      endPtr = strchr(startPtr, '|'); 
      strncpy(teams[index].teamCity, startPtr, endPtr - startPtr); 

      startPtr = endPtr + 1; 
      endPtr = strchr(startPtr, '|'); 
      strncpy(teams[index].teamState, startPtr, endPtr - startPtr); 

      startPtr = endPtr + 1; 
      endPtr = strchr(startPtr, '|'); 
      strncpy(teams[index].zipCode, startPtr, endPtr - startPtr); 

      startPtr = endPtr + 1; 
      endPtr = strchr(startPtr, '|'); 
      strncpy(teams[index].phoneNumber, startPtr, endPtr - startPtr); 

      startPtr = endPtr + 1; 
      endPtr = strchr(startPtr, '|'); 
      strncpy(teams[index].webAddress, startPtr, endPtr - startPtr); 



      index++; 
     } 

     fclose(filePtr); 
     count = index; 

     displayTeams(teams, count); 
    } 

    return 0; 
} 

void displayTeams(team_t teams[], int count) 
{ 
    int index; 

    for (index = 0; index <= count - 1; index = index + 1) 
    { 
       printf("LEAGUE: %s\nTEAM: %s\nPARKNAME: %s\nADDRESS: %s\nCITY: %s\nSTATE: %s\nZIPCODE: %i\nPHONE#: %s\nWEBADDRESS: %s\n\n", 
                teams[index].leagueName, teams[index].teamName, teams[index].parkName, 
                teams[index].teamAddress, teams[index].teamCity, teams[index].teamState, 
                teams[index].zipCode, teams[index].phoneNumber, teams[index].webAddress); 
    } 
} 

このファイルを試してみるために使用しています。

A|Baltimore Orioles|Oriole Park|333 West Camden Street|Baltimore|MD|21201|(410) 685-9800|orioles.com 
A|Boston Red Sox|Fenway Park|4 Yawkey Way|Boston|MA|02215|(617) 267-9440|redsox.com 
N|St. Louis Cardinals|Busch Stadium|700 Clark Street|St. Louis|MO|63102|(314) 345-9600|cardinals.com 
N|Washington Nationals|Nationals Park|1500 South Capitol Street, SE|Washington|DC|20003-1507|(202) 675-6287|nationals.com 

ここにはいくつかの行(合計30チーム)があります。まあ私はプログラムを実行すると、すぐにクラッシュし、エラーメッセージが表示されません。私は誰かが私になぜコードが動作していない理由を説明することができれば感謝します。私は間違ってstrncpy機能を使用していると思います。

+0

デバッガで実行して、 'line'と他の変数がどのように見えるかを確認しましたか?あるいは単に値を 'stdout'に出力したでしょうか? –

答えて

0

あなたは正しいと思います!この場合は、手動で'\0'文字列を終了する必要があります。したがって、memcpy()を使用すると、明快さの点でも優れている可能性があります。問題の各stringため

string[endPtr - startPtr] = '\0'; 

+0

ありがとうございました、現在、私は変更をテストしています。 –

1

このコードでは、元の文字列を保持することは重要ではないようです。 strtok()を使用するように修正することをお勧めします。strtok()は、元の文字列をそのままNULに貼り付けて変更します。具体的には、最初の区切り文字が見つかる場所にNUL文字を置くので、strcpyを使ってトークンをコピーできます。その後、NULLのstrtokは元の文字列に戻り、次のトークンを見つけます。ウェブ上のstrtok()に関するすべてを読んでください。

while (index < LEN && fgets(line, sizeof(line), filePtr)) 
{ 
    char* token = strtok(line, "|"); 
    strcpy(teams[index].leagueName, token); 
    token = strtok(NULL, "|"); 
    strcpy(teams[index].parkName, token); 
    // and so forth 
} 

今、私が解決していない、とあなたがすべき問題は、与えられたテキストは、フィールドの長すぎると、この元も私の提案コードのアドレスでもないかもしれないということです。おそらく、

token = strtok(line, "|"); 
if (strlen(token) > LEAGUE_NAME) token[LEAGUE_NAME]=0; 
strcpy(teams[index].leagueName, token); 

また、あなたのstrchr()の結果、および上記の私のプロトタイプのコードでは、はstrtok()の結果は、チェックされません。入力行が予想よりも広い場合、fgets()の呼び出しによって制限された行は、行を切り捨てて区切り文字を省略することができます。 strchrまたはstrtokの結果はNULLになり、プログラムが停止します。

+0

ありがとうございました、現在私は変更をテストしています。 –

+0

私は#definesの長さを変更する必要があるのでしょうか? –

+0

私はそれが郵便番号を除いて正常に動作していることを意味します。私は郵便番号のコードを書いていなくても郵便番号を取得していました。それはかなり変です。 –

関連する問題