[英]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.