2017-04-27 90 views
0

我正在創建一個程序,用於檢查從起機場到目的地機場的可能航空公司(這兩個信息將由用戶輸入)。我有一個文件,其中包含所有的航空公司#及其相應的機場。例如,10A, LIM, LAX有航空公司號碼(10A),原始機場(LIM)和目的地機場(LAX)。每行包含航空公司#,原產地機場(縮寫)和目的地機場(縮寫)格式的信息。使用字符串和陣列

我會讓C讀取文件,它將使用fgets函數讀取每一行,直到它到達匹配起點和目的地機場的行。然後,它會返回航空公司號碼。如果沒有,那麼電腦會打印出沒有航空公司有這樣的航班。由於每行將被視爲一個字符串,將被存儲在我稱爲str[10000]的字符數組中。我想通過使用strcat函數來存儲航空公司號碼。我想要做的是strcat(str[0], str[1])這將加入,例如使用我有10A的例子是將10(將存儲在str [0]中)和A(將存儲在str [1]中) 。由於某種原因,這種方法似乎不起作用。

我已經創建了功能void route(char *origin, char *destination, char *airline[])來打印出航空公司號碼,但我不知道如何使用陣列並將它們存儲到*airline[]。我也已初始化爲*airline[20],因爲可能有多家航空公司從原點到用戶指定的目的地。

我只是想確保我最終可以使用strcmp來比較用戶輸入的來源機場和目的地機場,以便如果它匹配的航空公司號碼將被報告。

請幫我處理字符串和數組。當我嘗試編譯並運行該程序時,在輸入原點和目標機場後出現錯誤Abort Trap 6。我不知道爲什麼會發生這種情況。我會感謝任何人提供的幫助。提前致謝。

編輯這裏是我認爲主要的問題是脫出功能...

void route(char *origin, char *destination, char *airline[]) 
{ 
    char str[10000]; 

    while (fgets(str, sizeof(str), fp) != NULL) 

    strcat(str[0], str[1]); // Combining the first element (10) with second element (A) 
} 

請注意,此代碼仍然是不完整的,但這個我在哪裏了這麼遠因爲我被卡住了。

編輯 10A不是航空公司的可能選擇。它確實有三個要素,所有航空公司的選擇都只有兩個要素,例如3A。

編輯我補充說,使用fgets功能行:while (fgets(str, sizeof(str), fp) != NULL)

+1

是的,你可以使用'strcmp'來比較兩個字符串。如果您需要任何調試幫助,您需要發佈[mcve],因爲我們無法讀懂您的想法,並告訴您爲什麼您的程序錯誤。我會建議編輯你的問題,以減少很多文本;只是簡單描述你的目標,展示問題的最小代碼,說出你期望的輸出,並說出你得到的輸出。 –

+0

'strcat(str [0],str [1]);'肯定是一個問題。 'str *'適用於字符串,但是您提供了單個字符。你的意思是'str [0] = str [1];'而不是?這仍然是錯誤的,因爲'str'是未初始化的。但我認爲你有更多的代碼在初始化它? –

+0

「_10(將存儲在str [0]中)_」 - 不。你不能那樣做。 '10'包含_two_字符'1'和'0',它們需要存儲在不同的變量中。你不能在一個變量中存儲很多值,對吧? Maybd你需要'str [strchr(str,',') - str] ='\ 0';'? –

回答

0

從註釋中持續進行中(因爲它出現您需要幫助,以獲得「邏輯」電燈泡眨眼上),讓我們看看你在做什麼,不在做什麼,讓你整理出來。首先讓我們看一下你的宣言:

void route(char *origin, char *destination, char *airline[]); 

void是,你需要一些方法來衡量功能的成功/失敗的函數類型一個可怕的選擇(例如發現/你的情況未找到)。選擇一個typeroute所以你可以返回一個值表示成功/失敗需要時。 void有它的地方,例如就像在一個簡單的函數中打印輸出的地方一樣,你在之前驗證函數參數將它們傳遞給函數。否則,使用可以檢查返回值的類型來確定函數是成功還是失敗。在這裏,一個簡單的int類型很好,在失敗時返回0,並返回1(或任何非零數字,甚至是負數)以指示成功。

接下來,​​是一個指針類型的指針數組。這不是你想要傳遞的字符串,如3A這是一個類型的字符串char(它將在作爲函數參數傳遞時轉換爲指向char *的指針)或sting literal,它只是一個指針以字符。所以你實際上想要char *airline

接下來,除非你聲明fp全局文件流指針(壞主意),你需要通過FILE *fp作爲參數傳遞給route。一起把這個信息,你的聲明可用route可以是這樣的:

int route (char *origin, char *dest, char *airline, FILE *fp); 

從你在你的問題描述你需要使用fgets什麼,但它是在什麼實際可用解析不清楚airline,origindestination來自strfgets填充。因此,讓我們只是假設你有你可以用它來分隔字符串,我們使用的是始終可用的兩種基本方法(數組索引指針運算)來解析airline,從strorigindestination沒有其他功能。

這是從str開始處開始並漫遊指針(或使用數組索引)檢查每個字符的值並根據需要分配字符(解析字)直到獲得所有數據的基本方法您需要或到達str的末尾(您必須針對這兩種情況進行保護)。

當工作下來一個字符串,它是由來跟蹤你在哪裏,並預測到合理程度的下一步怎麼走,所以你可以測試每個字符(你需要什麼,以及至於字符串的結尾),將其保存在需要保存的位置,或者繼續保存到其他位置。當你這樣做時,你需要跟蹤你保存到每個單獨位置的字符數(例如分隔字符數組,如arln,orgdst,以便與要查找的airline,origindestination進行比較)確保你不寫超出了任何陣列,或分配的內存塊的結尾,記住保存+1 char在每個陣列的端部以保持'\0'NUL字節NUL-終止字符)或分配內存塊使每個有效字符串。(明白'\0'的NUL字節具有的簡單0一個字符值,所以你可以使用'\0'或者乾脆0終止字符串)

而不是通過解釋什麼可用route功能可能看起來像每行一步,讓我只是提供一個評論性的例子,它逐步地幫助你理解邏輯(以及C語言中幾乎任何事物所需要的思考和理解水平,你完全控制你如何使用內存,並且你有確保您正確使用它的全部責任 - 以巨大的權力來承擔重大責任)。儘管如此,請讓我知道你是否需要任何特定部分的幫助。

我故意使用兩種陣列中的示例索引指針運算,但對於一個正常執行這種類型的,我寧願指針運算在評論中所指出的原因。下面的一切可以做一些採用例如fscanf簡化讀取和一次或使用strtoksscanf解析strfgets充滿解析不同的方式。這些函數只是幫助你做任何你可以隨時通過沿着任何字符串走一個指針(或一對指針)手動執行的操作。

我已經驗證傳遞給routeroute作爲例子的參數,但通常你會想要讓您的呼叫route之前做的是,在調用函數(main這裏)。用,這裏是一個可用route一個例子,將步驟雖然含有線的輸入文件格式爲:

airline, origin, destination /* e.g. '3A, KOCH, KEGE' */ 

(所述commas必須存在於每個標識符的端部,因爲它是當前編碼的,但空格數量並不重要' 3A, KOCH, KEGE'會正常工作,以及你在這個完全控制,並簡單地通過改變每個字符的測試,你可以完全消除','要求,只是看0-9, a-z, A-Z彌補每個單詞。 - - 這一切都取決於你)

route將與數據文件讀取每一行。 fgets解析各個標識符爲arlnorgdst來比較airlineorigindestination傳遞給route,返回1如果發現匹配,或0出現錯誤時或沒有找到匹配。對於route的例子:

int route (char *origin, char *dest, char *airline, FILE *fp) 
{ 
    /* validate parameters - you can do this before calling route */ 
    if (!origin || !*origin) { 
     fprintf (stderr, "error: origin 'NULL' or empty.\n"); 
     return 0; 
    } 
    if (!dest || !*dest) { 
     fprintf (stderr, "error: dest 'NULL' or empty.\n"); 
     return 0; 
    } 
    if (!airline || !*airline) { 
     fprintf (stderr, "error: airline 'NULL' or empty.\n"); 
     return 0; 
    } 
    if (!fp) { 
     fprintf (stderr, "error: fp not open for reading.\n"); 
     return 0; 
    } 

    char str[LINE] = ""; 

    while (fgets (str, LINE, fp)) /* for each line in the input file */ 
    { 
     char org[PARTS] = "", dst[PARTS] = "", arln[PARTS] = "", 
      *o = org, *d = dst, *a = arln, *s = str; 
     size_t n; 

     /* check for trailing '\n' included by 'fgets' indicating 
     * complete line read into str, then remove '\n' by overwriting 
     * with nul-terminating character. 
     */ 
     n = strlen (str); 
     if (str[n - 1] == '\n') 
      str[--n] = 0; 

     /* read airline flight from str into arln, will skip leading 
     * whitespace copying all other chars up to first ',' or '\0'. 
     * (you can also use strtok to 'tokenize' the line) 
     */ 
     /* you can either use array indexing */ 
     for (n = 0; n < PARTS - 1 && s[n] && s[n] != ','; n++) { 
      if (s[n] == ' ') continue; /* skip space */ 
      a[n] = s[n]; 
     } 
     a[n] = 0; /* nul-terminate arln (already done, but...) */ 
     s += n;  /* indexing wont advance 's', advance to char after 'arln' 
        * (to the ',') to start looking for beginning of 'org'. 
        */ 
     /* or use pointer arithmetic (cleaner as 's' is advanced) 
     * 
     * for (n = 0; n < PARTS - 1 && *s && *s != ','; n++, a++, s++) { 
     *  if (*s != ' ') continue; 
     *  *a = *s; 
     * } 
     * *a = 0; 
     */ 

     /* add checks to validate 'arln' length here if desired, and the same 
     * following filling 'org' and 'dst' if desired 
     */ 

     /* compare arln to airline */ 
     if (strcmp (arln, airline) != 0) 
      continue; /* doesn't match, get next line */ 

     /* find start of origin (org) in str (using pointer arithmetic) 
     * skipping forward until you find next '0-9', 'a-z' or 'A-Z' 
     * (you can use while (*s && isalnum (*s)) from ctype.h instead) 
     */ 
     while (*s && ((*s < '0' || '9' < *s) && 
         (*s < 'a' || 'z' < *s) && 
         (*s < 'A' || 'Z' < *s))) 
      s++; 

     if (!*s) { /* validate you are not at end of str */ 
      fprintf (stderr, "error: no valid chars follow airline in str.\n"); 
      return 0; 
     } 

     /* fill org ICAO from str */ 
     for (n = 0; n < PARTS - 1 && *s && *s != ','; n++, o++, s++) 
      *o = *s; 
     *o = 0; 

     /* compare org to origin */ 
     if (strcmp (org, origin) != 0) 
      continue; /* doesn't match, get next line */ 

     /* find start of destination (dst) in str (using pointer arithmetic) 
     * skipping forward until you find next '0-9', 'a-z' or 'A-Z' 
     * (you can use while (*s && isalnum (*s)) from ctype.h instead) 
     */ 
     while (*s && ((*s < '0' || '9' < *s) && 
         (*s < 'a' || 'z' < *s) && 
         (*s < 'A' || 'Z' < *s))) 
      s++; 

     if (!*s) { /* validate you are not at end of str */ 
      fprintf (stderr, "error: no valid chars follow origin in str.\n"); 
      return 0; 
     } 

     /* fill dst ICAO from str */ 
     for (n = 0; n < PARTS - 1 && *s && *s != ','; n++, d++, s++) 
      *d = *s; 
     *d = 0; 

     /* compare dst to destination */ 
     if (strcmp (dst, dest) == 0) 
      goto found; /* match for airline, origin, destination found */ 
    } 

    return 0; /* return 0 - indicating no route found */ 

    found: 

    return 1; /* return 0 - indicating route found */ 
} 

注:route本質上是做同樣的事情三倍。開始在每個標識符的開始,讀取每個字符到適當的陣列,直到','(或* NUL字節)被發現,NUL,終止新的數組,然後移動到下一個字符str,跳過一切,直到找到0-9, a-z, A-Z(開始下一個標識符),然後重複。

其使用的簡短的例子是:

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

enum { PARTS = 8, LINE = 128 }; /* constants - adjust as required */ 

/* specify a meaningful return type to guage success/failure */ 
int route (char *origin, char *dest, char *airline, FILE *fp); 

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

    char *ar = "3A", *or = "KOCH", *ds = "KEGE"; /* flight to find */ 
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin; 

    if (!fp) { /* validate file open for reading */ 
     fprintf (stderr, "error: file open failed '%s'.\n", argv[1]); 
     return 1; 
    } 

    if (route (or, ds, ar, fp)) 
     printf ("airline '%s' origin '%s' destination '%s' -- found.\n", 
       ar, or, ds); 
    else 
     printf ("airline '%s' origin '%s' destination '%s' -- not found.\n", 
       ar, or, ds); 


    if (fp != stdin) fclose (fp);  /* close file if not stdin */ 

    return 0; 
} 

int route (char *origin, char *dest, char *airline, FILE *fp) 
{ 
    ... 
} 

實施例輸入文件

$ cat dat/route.txt 
1D, KEFD, KPRS 
3A, KOCH, KEGE 
8Z, KDT0, 3T2 

實施例使用/輸出雖然示例

$ ./bin/airline <dat/route.txt 
airline '3A' origin 'KOCH' destination 'KEGE' -- found. 

工作,確保你解開這一切,讓我知道如果你不(在你已經做出合理的搜索回答基本語法等問題你的自我)