Kei*_*fer 7 c segmentation-fault
这是我用C编写的第一件事,所以请随意指出它的所有缺陷.:)我的问题是这样的:如果我按照我认为最干净的方式编写程序,我会得到一个破碎的程序:
#include <sys/queue.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* Removed prototypes and non related code for brevity */
int
main()
{
char *cmd = NULL;
unsigned int acct = 0;
int amount = 0;
int done = 0;
while (done==0) {
scanf ("%s %u %i", cmd, &acct, &amount);
if (strcmp (cmd, "exit") == 0)
done = 1;
else if ((strcmp (cmd, "dep") == 0) || (strcmp (cmd, "deb") == 0))
debit (acct, amount);
else if ((strcmp (cmd, "wd") == 0) || (strcmp (cmd, "cred") == 0))
credit (acct, amount);
else if (strcmp (cmd, "fee") == 0)
service_fee(acct, amount);
else
printf("Invalid input!\n");
}
return(0);
}
void
credit(unsigned int acct, int amount)
{
}
void
debit(unsigned int acct, int amount)
{
}
void
service_fee(unsigned int acct, int amount)
{
}
Run Code Online (Sandbox Code Playgroud)
就目前而言,上面在编译时没有产生错误,但在运行时给了我一个段错误.我可以通过在调用scanf和strcmp时通过引用更改程序来传递cmd来解决这个问题.段错误消失,在编译时每次使用strcmp时都会被警告取代.尽管有警告,但受影响的代码仍可正常工作.
警告:从不兼容的指针类型传递'strcmp'的arg 1
作为一个额外的好处,修改scanf和strcmp调用允许程序进展足够远以执行return(0),此时事件与Abort陷阱崩溃.如果我换出return(0)退出(0),那么一切都按预期工作.
这让我有两个问题:为什么原始程序错了?我怎样才能比我更好地修复它?
关于需要使用退出而不是返回的一点让我特别困惑.
sam*_*moz 11
这是因为scanf语句而发生的.
看看cmd是如何指向NULL的.当scanf运行时,它会写入cmd的地址,该地址为NULL,从而生成段错误.
解决方案是为cmd创建缓冲区,例如:
char cmd[20];
Run Code Online (Sandbox Code Playgroud)
现在,您的缓冲区可以容纳20个字符.但是,如果用户输入超过20个字符,您现在需要担心缓冲区溢出.
欢迎来到C.
编辑:此外,请注意您的信用卡,借记卡和服务费功能将无法按预期编写.这是因为参数是按值传递的,而不是通过引用传递的.这意味着在方法返回后,将丢弃任何更改.如果您希望它们修改您提供的参数,请尝试将方法更改为:
void credit(unsigned int*acct,int*amount)
然后称他们为:
credit(&acct, &amt);
Run Code Online (Sandbox Code Playgroud)
这样做会通过引用传递参数,这意味着即使在函数返回后,您在credit函数内所做的任何更改都会影响参数.
小智 5
正如其他人所指出的那样,你还没有为scanf分配任何内容.但是你也应该测试scanf的返回值:
if ( scanf ("%s %u %i", cmd, &acct, &amount) != 3 ) {
// do some error handling
}
Run Code Online (Sandbox Code Playgroud)
scanf函数返回成功转换的次数,因此如果有人在期望您希望能够检测并处理它的整数时键入XXXX.但坦率地说,使用scanf()的用户界面代码永远不会成为这种事情的证明.scanf()实际上是用于读取格式化文件,而不是来自人类的随机输入.
| 归档时间: |
|
| 查看次数: |
451 次 |
| 最近记录: |