Yahoo奇摩知識+ 將於 2021 年 5 月 4 日 (美國東部時間) 終止服務。自 2021 年 4 月 20 日 (美國東部時間) 起,Yahoo奇摩知識+ 網站將會轉為唯讀模式。其他 Yahoo奇摩產品與服務或您的 Yahoo奇摩帳號都不會受影響。如需關於 Yahoo奇摩知識+ 停止服務以及下載您個人資料的資訊,請參閱說明網頁。

C語言 陣列

我想請問一下大大們

我要用陣列寫一個C程式,

功能是,

讓使用者決定輸出幾行後換行,

程式可以讀取一個(.txt)檔裡面的資料顯示在DOS上面,

比如說我有一個檔名叫水果.txt檔裡面有很多水果名子(以下是水果.txt裡面的資料)

西瓜

番茄

芭樂

橘子

柳丁

蘋果

木瓜

榴槤

釋迦

棗子

香蕉

香瓜

蓮霧

草莓

水梨

(到此為止)

比如說使用者輸入3

那DOS畫面輸出就要是

西瓜 番茄 芭樂

橘子 柳丁 蘋果

木瓜 榴槤 釋迦

棗子 香蕉 香瓜

蓮霧 草莓 水梨

目前我已經寫了如下所示

#include <stdio.h>

main()

{

FILE *fp;

char **ch,n,m,i,j;

if((fp=fopen("水果.txt", "r"))==NULL)

{

printf("無法開啟檔案");

exit(1);

}

printf("請輸入一個 N X N 的矩陣: ");

scanf("%d", &n);

printf("請輸入一個 M X M 的矩陣: ");

scanf("%d", &m);

ch = (char**) malloc(sizeof(char*) * n);

for (i = 0; i < n; i++)

ch[i] = (char*) malloc(sizeof(char) * m);

for (i = 0; i < n; i++){

for (j = 0; j < m; j++) {

while((ch[i][j]=fgetc(fp))!=EOF) fputc(ch[i][j],stdout);

}}

fclose(fp);

return 0;

}

但是不知道哪裡錯誤

請大大們幫小弟我解答

已更新項目:

Tai大大:

你有幫小弟我修改程式碼,

但由於修改後的程式碼

還是無法呈現出小弟我所需要的

想跟大大深入討論,

請問大大方便留下聯絡方式嗎?

5 個解答

評分
  • Tai
    Lv 5
    7 年前
    最佳解答

    while((ch[i][j]=fgetc(fp))!=EOF) fputc(ch[i][j],stdout);

    這行不斷地讓 file data 讀入 ch[0][0] 直到檔案結束。

    之後 ch[0][1], ch[0][2] 等等, 檔案早就讀完, 無值可讀.

    char **ch;

    以指標產生二維陣列( or 矩陣),不幸的是這只是產生 char 矩陣。一個 char 不足夠長放各水果詞 "西瓜","水梨"。每個中文字用 two characters 存,兩個中文字的詞,至少需要長度 5 (2+2+1結尾) 的 char 陣列才夠存放。改為

    char ***ch;

    以下是依照版大的架構改 code,請注意上述兩點。

    #include <stdio.h>

    #include <malloc.h>

    int main()

    {

    FILE *fp;

    char ***ch,n,m,i,j;

    if((fp=fopen("水果.txt", "r"))==NULL)

    {

    printf("無法開啟檔案");

    return 1; //exit(1);

    }

    printf("請輸入一個 N X M 的矩陣: ");

    scanf("%d %d", &n, &m);

    ch = (char***) malloc(sizeof(char**) * n);

    for (i = 0; i < n; i++) {

    ch[i] = (char**) malloc(sizeof(char*) * m);

    for (j = 0; j < m; ++j)

    ch[i][j] = (char*) malloc(sizeof(char)*5);

    }

    for (i = 0; i < n; i++){

    for (j = 0; j < m; j++) {

    fscanf(fp, "%s\n", ch[i][j]);

    }}

    fclose(fp);

    for (i = 0; i < n; i++) {

    for (j = 0; j < m; ++j) printf("%s ", ch[i][j]);

    printf("\n");

    }

    // free

    for (i = 0; i < n; i++) {

    for (j = 0; j < m; ++j) free(ch[i][j]);

    free(ch[i]);

    }

    free(ch);

    return 0;

    }

    2013-12-23 01:58:39 補充:

    雙精確度在 C/C++ 中是指 double, 而不是 two characters.

    2013-12-23 17:56:01 補充:

    Hi, 這是執行結果, 應該是你要的結果.

    注意一下輸入的部分, 已經改寫成 scanf("%d %d" ..)

    請輸入一個 N X M 的矩陣: 5 3

    西瓜 番茄 芭樂

    橘子 柳丁 蘋果

    木瓜 榴槤 釋迦

    棗子 香蕉 香瓜

    蓮霧 草莓 水梨

    2013-12-23 18:04:39 補充:

    To ㄚ魚, 有問題就趕快寫信或是貼文吧.

    printf("請輸入一個 N X N 的矩陣: ");

    scanf("%d", &n);

    printf("請輸入一個 M X M 的矩陣: ");

    scanf("%d", &m);

    你上述寫法其實是想輸出一個 N x M 矩陣吧.

    所以併入一行, 由使用者輸入 n 和 m

    scanf("%d %d", &n, &m);

    2013-12-23 18:04:52 補充:

    而如果你的水果超過兩個字, 比如 "鳳梨釋迦",

    就配給每個詞更大的空間, 而不只是 char[5]

    2013-12-23 18:06:17 補充:

    To ㄚ魚, 你目前執行結果為何? 貼出來或寄信過來才好 debug.

    2013-12-23 18:44:30 補充:

    如果只要輸入每行有幾個水果, 又要保持你原程式的架構,

    那可先掃過檔案, 累計水果數目 (行數) 後, 再配置記憶體, 重新讀入.

    printf("請輸入每行水果個數 M: ");

    scanf("%d", &m);

    for(n=0; NULL != (fgets(line, sizeof(line), fp)); n++); // 讀總共有個水果 n

    fseek(fp, 0, SEEK_SET); // 重回檔頭

    n /= m;

    2013-12-24 12:47:37 補充:

    那已經確定能讀到檔案了嗎 ? 我這裡是可行的

    2013-12-24 16:57:55 補充:

    出現 "輸入一個 NXM 的矩陣"

    表示讀檔成功

    一步步往下 trace 吧.

    依照 DevC++ 的方式設斷點,

    或是在所有輸入的部分, 都寫相對應的 printf

    印出是哪裡有問題

    scanf("%d %d", &n, &m);

    printf("%d %d\n", n, m);

    ..

    2013-12-24 16:59:35 補充:

    想不出程式碼錯誤就請 trace 吧

    在我的主機上是可執行, 我是 VC2008

    2013-12-25 11:49:56 補充:

    你回去仔細看第十二樓

    如果你只想要輸入每行有三個水果,

    那就改變輸入, 得到 m 後,

    內部先對 "水果.txt" 掃過一遍知道有幾個水果後, 再建立陣列

    把那段 code 換掉你原有的輸入 nxm 的 code,

    就可以了 ~^~

    2013-12-25 12:06:15 補充:

    阿魚啊, 我以為你當初的題目, 是老師要求做陣列練習,

    否則這種只有印出的題目, 根本不用多維陣列

    只要 "讀到就印出" 就可以了. 類似下面 (沒驗證, 自己確認)

    char buf[100];

    for (i = 0; fscanf(fp, "%s\n", buf)!=0; ++i) {

    printf("%3s", buf);

    if (0==(i%3)) printf("\n");

    }

    2013-12-25 13:42:26 補充:

    意見區的跳脫字元 \\ 會不見, 你自己看著吧

    2013-12-25 17:40:55 補充:

    你去看 fgets 的使用說明, 去看第一個參數是什麼, 和範例是什麼, 就知道了

    取代哪裡, 自己去理解, 一行行的去理解, 就知道放到哪裡了

    2013-12-25 18:07:47 補充:

    26 樓要改成

    fscanf(fp, "%sn", buf)>0

    2013-12-25 18:25:41 補充:

    就參考這三個版本吧

    http://ideone.com/qz9Ely

    http://ideone.com/q0g1IV

    http://ideone.com/atyJ8n

    2013-12-28 02:10:14 補充:

    非常好, 你能舉一反三了 :D

    寫 %3 是我偷懶寫死了, 基本上就是 bug

    你能找出來太好了, 就這麼改吧

    2013-12-29 15:28:45 補充:

    這段 code

    是預期 grade 是大寫英文再轉成小寫英文字母

    grade 若原是小寫字母不適用 !

    ASCII 表中 'A'~'Z' 和 'a'~'z' 都是連續的

    要產生 'C', 只要數與 'A' 差幾個字母就可

    grade 若是 'C', 與 'A' 的差值為 'C'-'A'=2

    從 'a' 補上差值 2, 就可得到 'a'+2 = 'c'

    2013-12-29 15:29:22 補充:

    如果不確定使用者是大寫還是小寫 ('A'=65, 'a'=97), 但都要轉成小寫

    grade = grade >= 'a' ? grade : 'a'+(grade-'A');

    2013-12-29 21:01:48 補充:

    唉, 我的 C 語言能力算是普通的,

    你問的那些也不算深入研究啊 XD

    你主要是基礎語法還要再熟悉,

    最好能用方便 debug 的 IDE 練習程式

    能加深印象也可以立刻回饋

    至於 C語言書籍, 最近才有人問過, 很多前輩回答了

    http://tw.knowledge.yahoo.com/question/question?qi...

    2014-01-02 16:20:15 補充:

    有m幾行. 比如你的需求是 m=3

    for (i = 0; fscanf(fp, "%s\n", line)>0; ++i) // fscanf() < 0 停止, i 從零累計

    {

    printf("%s ", line);

    if (0==(i+1)%m)

    printf("\n");

    }

    2014-01-02 16:21:27 補充:

    if (0==(i+1)%m) printf("n");

    上述是每次輸入水果後印出, 而每 m 個水果分行

    i=0 時, (0+1)%3=1 => 0 != 1

    i=1 時, (1+1)%3=2 => 0 != 2

    i=2 時, (2+1)%3=0 => 0 ==0 成立, 分行

    2014-01-02 16:24:02 補充:

    總之, 我們利用累計的水果個數 (i+1),

    和餘數運算, 每次第 m 個, 餘數為零就分行

  • 阿平
    Lv 5
    7 年前

    注意一下輸入的部分, 已經改寫成 scanf("%d %d",&n,&m);

    所以要宣告成

    int n,m;//好個bug,我太大意了

  • 卸貨
    Lv 5
    7 年前

    其實中文不一定佔兩個位元組,在我電腦上一個中文佔三個位元組。

  • 7 年前

    Tai大大你好:

    我依照你幫我所修改的程式碼,

    還是沒有辦法讓(水果.txt)

    這個檔案依我想要的方式顯示在DOS畫面上

    想跟大大討論大大幫我修改的程式碼

    是否還有須修改的地方???

    2013-12-23 13:55:39 補充:

    請問樓上的大大,

    依我現在的程式碼

    我需要在哪裡做修正

    才會讓我的城市正常運作呢!!!

    2013-12-23 14:55:41 補充:

    各位大大們,

    只要能解結小弟當前遇到的問題

    那就是好答案,

    請大大們針對問題回答

    拜託了,小弟目前很急!

    還是有那位大大可以留聯絡的方式!!!

    2013-12-23 18:54:28 補充:

    to Tai大大

    我已經寄信給你了

    請大大過目

    2013-12-23 19:31:30 補充:

    Tai大大

    我把你幫我所修改的程式碼輸入到DEV C++裡面

    但是執行時DOS畫面出現

    請輸入一個 N X M 的矩陣:(我輸入了)5 3 

    程式沒有出現水果的名子

    直接跳回執行的地方

    我在資料夾裡面有放.txt檔

    但是我找不出問題的所在

    請大大幫我解答

    2013-12-24 08:45:13 補充:

    樓上的大大

    因為我已經將c語言都讀過了

    實在是想不出程式碼錯誤的地方

    所以才想說在知識家跟前輩們討論

    希望能找出我思考不足的地方

    才請大大們幫助小弟

    2013-12-24 13:50:39 補充:

    Tai 大大

    我這裡測試讀不到(水果.txt)這個檔案

    執行程式時

    只出現

    請輸入一個 N X M 的矩陣:

    程式就結束了!!!

    請問大大我這邊是哪個環節出錯了!!!

    2013-12-24 14:04:46 補充:

    Tai大大

    我是使用DEV C++

    程式執行時出現

    請輸入一個 N X M 的矩陣:

    5 3(我輸入)

    請按任意鑑繼續.....

    是哪裡出錯了

    2013-12-24 21:26:57 補充:

    請問Tai大大

    是否有相關的資訊能給我

    因為我在網路上尋找 trace相關資訊

    實在是太多太雜

    請大大給我指點

    2013-12-25 11:16:50 補充:

    Tai大大

    我DEBUG好了

    我想請問大大!!!

    也就是說我想只設定M

    就可以輸出三個水果就換行直到輸出結束

    (比如說我輸入3,出現三個水果明子直到程式結束)

    西瓜 番茄 芭樂

    橘子 柳丁 蘋果

    木瓜 榴槤 釋迦

    棗子 香蕉 香瓜

    蓮霧 草莓 水梨

    (不用再輸入兩個數,比如說我輸入3與3)

    西瓜 番茄 芭樂

    橘子 柳丁 蘋果

    木瓜 榴槤 釋迦

    (變成只輸出九個水果名子,沒有全部輸出)

    我想請問大大,如果這樣是否就不用用到三維

    請大大指點給我一個方向

    2013-12-25 16:37:28 補充:

    Tai 大大

    我想請問你

    是把12樓這個取代哪裡

    把那段 code 換掉你原有的輸入 nxm 的 code

    不是很懂這句話的意思

    for(n=0; NULL != (fgets(line, sizeof(line), fp)); n++); // 讀總共有個水果 n

    這段程式碼當中line是甚麼意思???

    2013-12-26 11:25:39 補充:

    Tai 大大:

    感謝你的指導,

    讓我對於C程式有更上一層樓的見解

    非常感謝你

    2013-12-26 13:57:01 補充:

    Tai大大:

    我發現你提供給我參考的範例之中

    http://ideone.com/atyJ8n

    這個範例的

    if (0==(i+1)%3) printf("\n");

    是否該修改成

    if (0==(i+1)%m) printf("\n");

    這樣才對呢?

    2013-12-29 10:53:53 補充:

    Tai大大:

    我想請問你

    grade = 'a' + (grade - 'A');

    以上這段程式碼是輸入大小寫都可

    在網路上查詢了許久

    請問大大能為我解答他的動作原理嗎!!!

    2013-12-29 19:07:19 補充:

    Tai大大:

    太感謝Tai大大了,

    Tai大大對C程式語言有那麼深的研究

    小弟最近讀完一本C程式語言

    想請Tai大大推薦一本C程式語言的書

    給小弟閱讀

    讓小弟在C程式語言也能像Tai大大一樣厲害

    2014-01-01 11:24:38 補充:

    Tai大大:

    想請問你

    if (0==(i+1)%m) printf("\n");

    這段程式碼我知道他的意思是輸出幾行的設定

    但我對前半段的程式碼不是很了解其中的意思

    %是代表顯示出餘數

    m是代表行

    0==(i+1)這是什麼是思

    請大大解答

    2014-01-05 10:25:37 補充:

    感謝Tai大大無私分享

    讓困惑我已久的問題得到解答

  • 您覺得這個回答如何?您可以登入為回答投票。
  • 7 年前

    請用「雙精確數」設定

    中文是兩個字元

    英文是一個字元

    2013-12-23 14:25:19 補充:

    第二個回答者,描述成「倍精確數」來解決,也是一種技巧。

    2013-12-23 14:27:10 補充:

    標準的 DOS 中文字碼,都是二個字元組,只有延伸字碼表,才有少數用到三個位元。

    沒去用到「延伸字碼表」,就沒有三位元的問題................

    這年頭?我就不信,還有誰會跟我一樣知道「延伸字碼表」的事情。

    2013-12-23 14:27:33 補充:

    就算知道?也沒幾個人,會多明白背後的真相。

    2013-12-23 21:10:49 補充:

    阿魚

    去把「C++」宣告字串的方式,在多看幾次!

    好麼?

    參考資料: http://hr-no.blogspot.com/ 「官僚文化」年度主題
還有問題?馬上發問,尋求解答。