C程序输入错误

C程序输入错误,c,input,printf,scanf,C,Input,Printf,Scanf,提示>输入 运行失败退出值138,总时间:3s 代码怎么了?必须是scanf或第二个printf。输入的长度未知。很多人都说只需创建一个长度为“X”的字符数组来保存输入。我只是想知道为什么这段代码有效 int main(void) { char *input; printf("prompt>"); scanf("%s", input); printf("%s", input); return 0; } 只是一个指针-没有分配数据空间来存储scanf

提示>输入

运行失败退出值138,总时间:3s

代码怎么了?必须是scanf或第二个printf。输入的长度未知。很多人都说只需创建一个长度为“X”的字符数组来保存输入。我只是想知道为什么这段代码有效

int main(void) {
    char *input;
    printf("prompt>");
    scanf("%s", input);
    printf("%s", input);
    return 0;
}
只是一个指针-没有分配数据空间来存储scanf收集的数据

试试这个

  char *input;
只是一个指针-没有分配数据空间来存储scanf收集的数据

试试这个

  char *input;

您可能希望尝试scanf%c,在具有定界字符的while循环中输入。您还应该将输入设置为数组char input[X],其中X是一个足够大的值,可以保存输入的最可能值。不过,我会先尝试将输入设置为数组

您可能希望尝试scanf%c,在具有定界字符的while循环中输入。您还应该将输入设置为数组char input[X],其中X是一个足够大的值,可以保存输入的最可能值。不过,我会先尝试将输入设置为数组

您使用什么编译器?在Turbo C 3.0中,它可以工作。 尝试以下变体:

char input[100];

你用什么编译器?在Turbo C 3.0中,它可以工作。 尝试以下变体:

char input[100];

您在使用指针之前忘记分配内存

试试看:

#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 <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;
}
或:

但是您在使用scanf时遇到了一个严重的问题,请参见下文

除非完全控制输入,否则不应在scanf或其任何变体中使用无界%s。这是一种危险的做法,很容易出现缓冲区溢出,你越早摆脱这种习惯越好。这类似于以那种方式进入

根据我先前的回答,下面的这段代码以及包含在其中的主代码提供了获取用户输入的安全方法。您将传入一个可选提示、要加载输入的缓冲区以及缓冲区的大小

如果有换行符,它会将输入返回到去掉换行符的缓冲区大小,然后在必要时清除行的其余部分,这样就不会影响下一个输入操作。它将在文件末尾返回OK或错误指示,或者如果输入太长,您仍然会得到输入的第一部分,以防您想对其进行处理

一旦你有了这条线路,你就可以安全地尽情地享受它。然而,这在您的案例中不是必需的,因为您只是尝试获取字符串。只需使用直接返回的缓冲区

char input[100];
试一试,它比单独使用scanf%s要健壮得多

关于您的更新,询问为什么这样做:

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;
}
这是未定义的代码。时期只为字符分配空间,但扫描字符串。由于字符串是所有字符后跟零字符的字符数组,因此唯一可以安全输入的字符串将是空字符串

任何其他内容都将写入字符以及堆栈上与字符相邻的内容

这与分配字符输入[100]然后输入200个字符没有什么不同,这仍然是缓冲区溢出,应该避免

下面的讨论基于C的一个特定实现,而不一定是所有实现

你在这里很幸运。编译器可能会生成保持堆栈指针对齐的代码,这样,即使您请求一个字节,也可能会获得分配给四个或更多字节的空间,具体取决于体系结构-为了简单起见,我假设大多数类型都是四个字节

此外,您可能会发现,您还可以安全地覆盖argc integer和argv pointer的八个字节,即使您不使用它们,它们可能仍然存在,没有必要为了在堆栈上保存几个字节而使用两组不同的启动代码

如果您写得比这更远,您最终将覆盖从main到启动代码的返回地址。然后你就会知道了,因为你的代码会在主出口时进入洛杉矶

对于未定义的行为,任何事情都可能发生。有时候,任何事情都有这样一种可能性,那就是它的工作原理非常类似于经常向空中扔一副牌,最终它们会整齐地堆成一堆,但随机性要小一些


这并不意味着未定义的行为不再是一件坏事。

您的具体问题是输入后没有存储空间。它是一个未初始化的指针,指向内存中的随机点,在任何地方都不可能有用

您可以使用以下内容:

#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;
}
或:

但是你有一个严重的问题 使用scanf的问题见下文

除非完全控制输入,否则不应在scanf或其任何变体中使用无界%s。这是一种危险的做法,很容易出现缓冲区溢出,你越早摆脱这种习惯越好。这类似于以那种方式进入

根据我先前的回答,下面的这段代码以及包含在其中的主代码提供了获取用户输入的安全方法。您将传入一个可选提示、要加载输入的缓冲区以及缓冲区的大小

如果有换行符,它会将输入返回到去掉换行符的缓冲区大小,然后在必要时清除行的其余部分,这样就不会影响下一个输入操作。它将在文件末尾返回OK或错误指示,或者如果输入太长,您仍然会得到输入的第一部分,以防您想对其进行处理

一旦你有了这条线路,你就可以安全地尽情地享受它。然而,这在您的案例中不是必需的,因为您只是尝试获取字符串。只需使用直接返回的缓冲区

char input[100];
试一试,它比单独使用scanf%s要健壮得多

关于您的更新,询问为什么这样做:

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;
}
这是未定义的代码。时期只为字符分配空间,但扫描字符串。由于字符串是所有字符后跟零字符的字符数组,因此唯一可以安全输入的字符串将是空字符串

任何其他内容都将写入字符以及堆栈上与字符相邻的内容

这与分配字符输入[100]然后输入200个字符没有什么不同,这仍然是缓冲区溢出,应该避免

下面的讨论基于C的一个特定实现,而不一定是所有实现

你在这里很幸运。编译器可能会生成保持堆栈指针对齐的代码,这样,即使您请求一个字节,也可能会获得分配给四个或更多字节的空间,具体取决于体系结构-为了简单起见,我假设大多数类型都是四个字节

此外,您可能会发现,您还可以安全地覆盖argc integer和argv pointer的八个字节,即使您不使用它们,它们可能仍然存在,没有必要为了在堆栈上保存几个字节而使用两组不同的启动代码

如果您写得比这更远,您最终将覆盖从main到启动代码的返回地址。然后你就会知道了,因为你的代码会在主出口时进入洛杉矶

对于未定义的行为,任何事情都可能发生。有时候,任何事情都有这样一种可能性,那就是它的工作原理非常类似于经常向空中扔一副牌,最终它们会整齐地堆成一堆,但随机性要小一些

这并不会使未定义的行为成为一件坏事。

试试:-

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

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

这将字符串限制为99字节。注意%s==由空格或换行符分隔的字符串,即。您只得到第一个单词

我想你真正想要的是:

int main(void) { 
char input[100]; 
printf("prompt>"); 
scanf("%99s", input); 
printf("%s", input); 
return 0; 
您可能需要添加一些代码来消除不需要的新行字符

试试看:-

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

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

这将字符串限制为99字节。注意%s==由空格或换行符分隔的字符串,即。您只得到第一个单词

我想你真正想要的是:

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

您可能需要添加一些代码来消除不需要的新行字符

如果输入的长度未知或大于99个字符怎么办?这是一个单独的问题,您应该更新原始问题或生成一个新问题。如果输入的长度未知或大于99个字符怎么办?这是一个单独的问题,您应该更新原始问题或生成一个新问题。如果输入的长度未知?尝试使输入缓冲区足够大以容纳最可能的值,如果您确实认为需要可调整大小的缓冲区,则这是另一个问题。编辑以显示。如果输入长度未知怎么办?尝试使输入缓冲区足够大以容纳最可能的值,如果您确实认为需要可调整大小的缓冲区,则这是另一个问题。Turbo C是Borland的一个免费C++编译器。它带有一个IDE和调试器。它于1987年首次推出,以其集成开发环境、小规模、非常快的编译速度、全面的手册和低廉的价格而闻名。这也是完全不必要的,也不是过于现代的标准,符合当今的Code::Blocks和微软的Visual Express版本:-你为什么要使用冷战时期的编译器?我正在学习,在我们大学里,我们有冷战时期的非常非常旧的计算机,这就是为什么我使用它来完成纯C相关的任务。为了我自己的目的,我正在使用VS6.012008.turbo c改进一个
RelayRealTurbo C是Borland的一个免费C++编译器。它带有一个IDE和调试器。它于1987年首次推出,以其集成开发环境、小规模、非常快的编译速度、全面的手册和低廉的价格而闻名。这也是完全不必要的,也不是过于现代的标准,符合当今的Code::Blocks和微软的Visual Express版本:-你为什么要使用冷战时期的编译器?我正在学习,在我们大学里,我们有冷战时期的非常非常旧的计算机,这就是为什么我使用它来完成纯C相关的任务。为了我自己的目的,我正在使用VS6.0,2008.turbo c提高一个人的耐力是的,代码有时可能会工作。它只会覆盖堆栈上的一些内容,导致崩溃或潜在的安全漏洞。是的,代码有时可能会工作。它只会覆盖堆栈上的某些内容,导致崩溃或潜在的安全漏洞。