2010-09-17 212 views
1
int main(void) { 
    char *input; 
    printf("prompt>"); 
    scanf("%s", input); 
    printf("%s", input); 
    return 0; 
} 

提示>輸入C語言編程輸入錯誤

運行失敗(退出值138,總時間:3秒)

有什麼不好的代碼?必須是scanf()或第二個printf()。輸入的長度未知。很多人都說只需創建一個長度爲「X」的char數組來保存輸入。只是想知道爲什麼這個代碼的作品。

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

int main(void) { 
    /* prompt */ 
    char input; 
    printf("prompt>"); 
    scanf("%s", &input); 
    printf("%s", &input); 
    return 0; 
} 
+1

是的,有時代碼可能有效。它只會覆蓋你的堆棧上的一些東西,導致崩潰或潛在的安全漏洞。 – wj32 2010-09-17 01:45:16

回答

3
char *input; 

只是一個指針 - 沒有數據空間分配商店SCANF收集數據。

試試這個,而不是

char input[100]; 
+0

如果輸入的長度未知或大於99個字符,該怎麼辦? – Spencer 2010-09-17 01:30:20

+3

這是一個單獨的問題,您應該更新您的原始問題或創建一個新問題。 – 2010-09-17 01:31:26

1

你可能想嘗試scanf("%c", input)一個while循環,有你的分界字符內。您還應該輸入一個數組char input[X],其中X是一個足夠數值的數字,以保存輸入的最可能值。我會盡量嘗試使輸入數組。

+0

如果輸入的長度未知,該怎麼辦? – Spencer 2010-09-17 01:32:03

+0

嘗試使輸入緩衝區足夠大以保存最有可能的值,如果您真的認爲需要可調整大小的緩衝區,那麼這是另一個問題。編輯顯示。 – bluevial 2010-09-17 01:36:44

1

你使用什麼編譯器?在Turbo C 3.0中它可以工作。 試試這個變種:

#include <stdio.h> 
#include <alloc.h> 
int main(void) 
{ 
    char *input = (char*)calloc(100, sizeof(char)); 
    printf("prompt>"); 
    scanf("%s", input); 
    printf("%s", input); 
    free(input); 
    return 0; 
} 
+0

Turbo C 3.0 ???? – 2010-09-17 01:38:36

+0

Turbo C是來自Borland的免費C++編譯器。它帶有一個IDE和調試器。它於1987年首次推出,其集成開發環境,體積小,編譯速度非常快,全面的手冊和低廉的價格而聞名。 http://www.brothersoft.com/turbo-c-182798.html – Spencer 2010-09-17 01:42:49

+0

現在,它也完全沒有必要(也不過分符合現代標準),它們來自MS的Code :: Blocks和Visual Express版本。 ) – paxdiablo 2010-09-17 01:46:43

1

你忘了使用您的指針之前,分配的內存。

試試:

int main(void) { 
    char input[256]; 
    printf("prompt>"); 
    scanf("%s", input); 
    printf("%s", input); 
    return 0; 
} 

甚至:

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

int main(void) { 
    char *input = (char *) malloc(sizeof(char) * 256)); 
    printf("prompt>"); 
    scanf("%s", input); 
    printf("%s", input); 
    return 0; 
} 
6

你的具體問題是,你的背後有沒有input存儲。這是一個未初始化的指針,指向內存中的隨機點,這不太可能有用。

您可以使用類似:

char *input = malloc (100); 
// check that input != NULL 
// use it 
free (input); 

或:

char input[100]; 

但你必須與你使用的scanf一個嚴重的問題(見下文)。


你應該從未使用scanf無界%s(或任何變體,除非你完全控制輸入)。這是一種容易發生緩衝溢出的危險做法,越早戒除就越好。這類似於gets()

從我之前的回答中,下面的這段代碼(與您的主代碼結合在一起)提供了一種獲取用戶輸入的安全方法。你傳遞一個可選的提示,緩衝區來加載輸入,以及緩衝區的大小。

它將返回輸入到緩衝區(如果有的剝去新行),然後清除掉,如果必要的,這樣不會影響接下來的輸入操作行的其餘部分的大小。它會在文件結束時返回OK或錯誤指示,或者輸入太長(如果您想對其執行某些操作,您仍會得到輸入的第一部分)。

一旦你的線,你可以sscanf它,安全,你的心臟的內容。然而,這不是你的要求,因爲你只是想獲得一個字符串。只需使用直接返回的緩衝區即可。

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

#define OK  0 
#define NO_INPUT 1 
#define TOO_LONG 2 
static int getLine (char *prmpt, char *buff, size_t sz) { 
    int ch, extra; 

    // Get line with buffer overrun protection. 
    if (prmpt != NULL) { 
     printf ("%s", prmpt); 
     fflush (stdout); 
    } 
    if (fgets (buff, sz, stdin) == NULL) 
     return NO_INPUT; 

    // If it was too long, there'll be no newline. In that case, we flush 
    // to end of line so that excess doesn't affect the next call. 
    if (buff[strlen(buff)-1] != '\n') { 
     extra = 0; 
     while (((ch = getchar()) != '\n') && (ch != EOF)) 
      extra = 1; 
     return (extra == 1) ? TOO_LONG : OK; 
    } 

    // Otherwise remove newline and give string back to caller. 
    buff[strlen(buff)-1] = '\0'; 
    return OK; 
} 

 

int main(void) { 
    char input[10]; 
    int rc = getLine ("prompt> ", input, sizeof (input)); 
    switch (rc) { 
     case NO_INPUT: printf ("\nNo input recieved\n"); break; 
     case TOO_LONG: printf ("Too long, truncated input below:\n"); 
     default: printf("Your input was [%s]\n", input); 
    } 
    return 0; 
} 

把那一個鏡頭,它比它自己使用scanf("%s")穩健得多。


至於你更新問爲什麼這個工程:

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

int main(void) { 
    /* prompt */ 
    char input; 
    printf("prompt>"); 
    scanf("%s", &input); 
    printf("%s", &input); 
    return 0; 
} 

這是不確定的代碼。期。您只爲字符分配空間,但您使用字符串進行掃描。由於字符串是所有字符後跟零字符的字符數組,因此您可以安全輸入的唯一字符串將是空字符。

其他任何東西都會寫入字符,無論發生什麼情況與堆棧上的字符相鄰。

這是分配char input[100]然後輸入200個字符沒有什麼不同,它仍然緩衝區溢出,應予以避免。以下討論基於C的特定實現,不一定全部實現。

有機會,你在這裏很幸運。編譯器可能會生成代碼來保持堆棧指針對齊,即使您要求輸入一個字節,也可以爲四個空間分配空間(甚至更多,這取決於體系結構 - 爲了簡單起見,我假設大多數類型都是四個字節)。另外,你可能會發現你也可以安全地覆蓋argc integer和argv指針的八個字節(即使你不使用它們,它們可能仍然存在,沒有一點指出有兩組不同的啓動指針, up代碼只是爲了保存堆棧中的幾個字節)。

如果您還寫的是,你最終會覆蓋從main返回地址到你的啓動代碼。 然後你會知道它,因爲當main退出時,你的代碼將進入la-la land。

未定義行爲,任何事情都有可能發生。有時候的任何東西都包含了它可以完美工作的可能性(類似於「在空中經常扔一副牌,他們最終會落入一個漂亮的整齊排列的堆中」,但是隨機少一點)。

這並不會使未定義的行爲更糟​​糕。

1

嘗試: -

int main(void) { 
char input[100]; 
printf("prompt>"); 
scanf("%99s", input); 
printf("%s", input); 
return 0; 

}

這將字符串限制爲99個字節。注意「%s」==由空格或換行符分隔的字符串,即。你只會得到第一個字!

我想你真正想要的是:

#include <stdio.h> 
int main(void) { 
    char input[99]; 
    printf("prompt>"); 
    fgets(input,99,stdin); 
    printf("->%s<-", input); 
    return 0; 
} 

你可能需要添加一些代碼來擺脫不必要的換行字符!