[英]C Programming Input Error
int main(void) {
char *input;
printf("prompt>");
scanf("%s", input);
printf("%s", input);
return 0;
}
提示>輸入
RUN FAILED(退出值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;
}
您的特定問題是您在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")
使用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整數和argv指針的八個字節(即使您不使用它們,它們也可能仍然存在,沒有意義的是,只有兩套不同的啟動代碼可以在堆棧上保存幾個字節)。
如果您編寫的內容超出此范圍,最終將覆蓋從main
到您的啟動代碼的返回地址。 然后您將了解它,因為當main
出口退出時,您的代碼將進入la-la land。
具有不確定的行為, 任何事情都會發生。 有時, 任何事情都包括它可能完美運行的可能性(類似於“經常在空中扔一副紙牌,它們最終會落入一個整齊,整齊的分類堆中”,但隨機性要小一些)。
這樣做不會使未定義的行為成為一件壞事。
char *input;
只是一個指針-沒有分配的數據空間存儲scanf收集的數據。
試試這個代替
char input[100];
您可能希望在具有分隔字符的while
循環內嘗試scanf("%c", input)
。 您還應該使輸入成為數組char input[X]
,其中X是足以容納輸入的最可能值的數量。 我會嘗試首先使輸入成為數組。
您使用什么編譯器? 在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;
}
您忘記了在使用指針之前分配內存。
試試吧:
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;
}
嘗試:-
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;
}
您可能需要添加一些代碼來擺脫不需要的換行符!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.