2014-01-15 35 views
0

來源:C語言編程 - 編譯錯誤:格式「%s」的預期輸入「字符*」

/* 
* Name: Adam Chubbuck 
* Date: 1/12/2014 
* Class: CSC-1720 
* Comment: Assignment #1 (Load-Sort-Print) v1 
*/ 

#include<stdio.h> 

int load(char fileName[], int array[]); 
int sort(int array[], int length); 
int print(int length, int array[]); 

int main() { 

    char fileName[100]; 
    int numList[300]; 
    int length; 

    printf("File Name: "); 
    scanf("%s", &fileName); 

    length = print(sort(numList,load(fileName, numList)), numList); 
    printf("\nLength: %i\n", length); 

    printf("Finished execution.\n"); 

    return 0; 
} 

int load(char fileName[], int array[]) { 

    FILE *input = fopen(fileName, "r"); 

    int length = 0, i = 0; 

    if(input == NULL) { 
     fprintf(stderr, "Error accessing file.\n"); 
    } else { 
     while(fscanf(input, "%i", &array[i]) != EOF) { 
     i++; 
     length++; 
     } 
    } 

    fclose(input); 
    return length; 
} 

int sort(int array[], int length) { 
    int a, b, c; 

    for (a = 0 ; a < (length - 1); a++) { 
    for (b = 0 ; b < length - a - 1; b++) { 
     if (array[b] > array[b+1]) { 
     c = array[b]; 
     array[b] = array[b+1]; 
     array[b+1] = c; 
     } 
    } 
    } 
    return length; 
} 

int print(int length, int array[]) { 
    int i; 

    printf("\n[NUMBERS]\n\n"); 
    for (i = 0; i< length; i++) { 
     printf("[N]%i\n", array[i]); 
    } 
    return length; 
} 

我已經通過對這個問題類似主題的閱讀和他們建議我從scanf函數刪除符號語句,但是當我這樣做並使用I/O重定向到文件時,它似乎陷入了一個無限循環,暗示它無法爲文件名字符數組賦值。

./a.out <test.txt> output.txt 
+0

刪除&。這是一個編譯器錯誤,如果你刪除它,它會被解決。另一件事是因爲你有多個錯誤... – deviantfan

回答

0

數組默認作爲指針傳遞。用這個代替...

scanf("%s", fileName); 

另外我讀過的地方不應該使用EOF來檢查文件是否完成讀取。

+0

我很感謝你的建議,但請在提供建議之前閱讀整個主題。我知道如何通過刪除&符號來解決該問題,但是這引發了我的主題中描述的另一個錯誤。 –

1

您聲明瞭char fileName[100]。這幾乎相當於char*已經。當你做

scanf("%s", &fileName); 

它變得相當於通過一個char**

:你可以在指針與數組之間進行谷歌搜索,看看有什麼區別,但是對於傳遞參數他們基本上是一樣的。當您使用

scanf("%99", filename); 

其中「99」是要接受輸入的最大長度,文件名「」沒有符號(因爲要指向第一filenamechar

1

在C的陣列是(幾乎)相同的指針。所以取一個數組的地址給出一個指針指針。 C中的字符串只是char的數組。因此,在您發言

scanf("%s", &fileName); 

你傳遞指針的指針scanf這是什麼期望。你應該只寫

scanf("%s", fileName); 

但是請注意,這是一個潛在的緩衝區溢出。 fileName只有有限的空間,如果輸入的內容更長,它將寫入超出fileName的長度。安全的解決辦法是:

scanf("%99s", fileName); 

[1]的顯着區別是sizeof運營商的行爲。如果它在數組標識符上使用,它會給出對象佔用的實際大小char。如果它用在指針上,它會將指針類型的大小賦予該對象。

+0

@jweyrich:是的,這在這個特定的設置中是安全的。但是,您通常希望將最大長度作爲變量傳遞,而不是作爲格式字符串(您可以在之前使用printf創建格式字符串)。不幸的是,scanf不支持'*'格式修飾符通過變量傳遞最大長度。然而,'m'修飾符會使scanf根據需要執行分配,但之後必須傳遞(char **)並釋放該數組。 – datenwolf

+0

我們同意。格式字符串中的硬編碼長度是_bad_,但是如果他想使用'scanf',那麼他可以做一件事來保證安全。我相信一個更安全的選擇,因爲他的場景是'fgets'。 – jweyrich

1

當傳遞給函數作爲參數時,數組名會衰減到指針(有一些例外)。fileName衰減到指向數組的第一個元素的指針fileName。這是char *類型,即它是該數組的第一個元素的地址。
另一方面,&fileName是整個陣列的地址,並且類型爲char (*)[100]

%s說明符預計類型爲char *的參數。您需要通過fileNamescanf作爲參數。
當您通過&fileName作爲scanf的參數時,編譯器會發現它不是函數scanf的預期類型的​​參數,因此會引發錯誤。
變化

scanf("%s", &fileName); 

scanf("%s", fileName); 

側面說明:切勿使用scanfgets讀取一個字符串,因爲它不檢查約束陣列..最好使用fgets

fgets(fileName, 100, stdin);