鱼C论坛

 找回密码
 立即注册
查看: 10040|回复: 44

c语言每次循环输入多个数据出错?见证基本功的时候到了各位~想挑战的来吧!~~

[复制链接]
发表于 2013-1-22 19:46:39 | 显示全部楼层 |阅读模式
10鱼币
本帖最后由 压寨宝宝 于 2013-1-23 16:59 编辑
  1. #include<stdio.h>
  2. int main()
  3. {
  4.        int a[20],i;
  5.      scanf("%d,%d",&i,&a[i]);
  6.      return 0;
  7. }
复制代码
我已经知道了程序出错在scanf处,然后发现原因可能是i的值在一个scanf里面不能及时传送到后面要输入进去的a的i里面然后会导致段异常之类的错误。。我个人的猜测是,输入完成后,scanf先扫描缓冲区的第一个数值,然后赋给i,接着扫描第二个数值,接着赋给a,那么此时的a应该是指定了哪个元素了的。现在假定i不大于20吧。
但是事实上这样的代码运行时程序会自动出错中断。
那么,scanf内部扫描赋值的真实过程是什么呢???
之前有很多热心的朋友帮忙解答,谢谢你们!
但是我现在不讨论其规范性,我就是想单纯的知道起内部的过程。谢谢各位啦!~~~~~~~
另外scanf中赋值顺序调换是不起作用的!
即:
  1. #include<stdio.h>
  2. int main()
  3. {
  4.        int a[20],i;
  5.      scanf("%d,%d",&a[i],&i);
复制代码
这样也不行。
谢谢各位热心的朋友啦!~~~~~~~~~~

最佳答案

查看完整内容

既然你问了,我就反汇编解释一下 程序段初始化不说了,直接看这句: 4: int a[20],i; 5: scanf("%d,%d",&i,&a); 0040102E 8B 45 AC mov eax,dword ptr [ebp-54h] ;[ebp-54h]是变量i的内容,VC的 debug模式下,初始是0xCCCCCCCC 00401031 8D 4C 85 B0 lea ecx,[ebp+eax*4-50h] ;ebp-50h是数组a的起始地址,其中eax*4是偏移,因为此时的i是0xCCCC ...
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
发表于 2013-1-22 19:46:40 | 显示全部楼层
既然你问了,我就反汇编解释一下
程序段初始化不说了,直接看这句:
4:        int a[20],i;
5:        scanf("%d,%d",&i,&a[i]);
0040102E 8B 45 AC             mov         eax,dword ptr [ebp-54h] ;[ebp-54h]是变量i的内容,VC的                       debug模式下,初始是0xCCCCCCCC

00401031 8D 4C 85 B0          lea         ecx,[ebp+eax*4-50h]  ;ebp-50h是数组a的起始地址,其中eax*4是偏移,因为此时的i是0xCCCCCCCC,显然ecx中存放的a[i]地址溢出,产生异常,这个就是bug的原因
00401035 51                   push        ecx
00401036 8D 55 AC             lea         edx,[ebp-54h]
00401039 52                   push        edx
0040103A 68 1C 50 42 00       push        offset string "%d,%d" (0042501c)
0040103F E8 2C 00 00 00       call        scanf (00401070)
00401044 83 C4 0C             add         esp,0ch
底下的我就不说了,可见scanf是先寻址(寄存器优化?),你输入的数字在后面才会填充,而填充的时候,a[i]早已越界,朋友努力学汇编吧,底层代码之前,没有秘密。

希望对你有帮助
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2013-1-22 20:24:15 | 显示全部楼层
for (int j=0;j<3;j++)
{
    scanf("%d,%d,"&i,&a[i]);            这里你的a[i]是几有说明吗?
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2013-1-22 20:55:30 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2013-1-22 20:58:40 | 显示全部楼层
如果你是想放3个值进数组里··应该是a[j]
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2013-1-22 21:05:13 | 显示全部楼层
52077643 发表于 2013-1-22 20:58
如果你是想放3个值进数组里··应该是a[j]

不定是放几个值进去的。抱歉。是我没简化我的问题。。
那么现在简化成一句话。。
scanf("%d,%d",&i,&a);
运行也会出错的。不用循环。跟循环没关系的。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2013-1-22 21:07:08 | 显示全部楼层
你这样会错误吗?你这样的话你输入的时候输入10,20你自己看看是不是你想要的?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2013-1-22 21:08:15 | 显示全部楼层
记得要打逗号做间隔···如果canf("%d%d",&i,&a);这样的话就是输入的时候用空格隔开两个数!比如10 20
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2013-1-22 21:11:29 | 显示全部楼层
还有你不能设置数组了再拆开 应该定义的时候 int a,i; 这里就是canf("%d%d",&i,&a);
如果定义的是int a[20],i;这里就是canf("%d%d",&i,&a[0到19的数或者变量]);
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2013-1-22 21:17:21 | 显示全部楼层
52077643 发表于 2013-1-22 21:07
你这样会错误吗?你这样的话你输入的时候输入10,20你自己看看是不是你想要的?

不是的,会错误的。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2013-1-22 21:20:25 | 显示全部楼层
52077643 发表于 2013-1-22 21:11
还有你不能设置数组了再拆开 应该定义的时候 int a,i; 这里就是canf("%d%d",&i,&a);
如果定义的是int a[20 ...

为什么scanf("%d,%d",&i,&a);不行。。
int j=1;
scanf("%d,%d",&i,a[j]);这样可以。
前面一种不是先赋值给i 了么,然后才是a赋值
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2013-1-22 21:30:13 | 显示全部楼层
scanf()这里应该是没有前后之分的··你输入的时候没有按回车之前是应该是还没赋值··i 还是个未知数,所以
a[i]cpu就不知道是哪个位置!你的意思应该是想输入第1个数的时候才让a[i]等于是数组的第几位吧!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2013-1-22 21:32:45 | 显示全部楼层
本帖最后由 思无邪 于 2013-1-22 21:37 编辑

int a[20],i;
看看你这一句 int i; 只声明 没有初始化,下面你scanf的时候 a【i】系统不知道你要指向那个单元。 这是导致段错误的原因。

应该 int i = 0; 初始化一下


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2013-1-22 21:54:44 | 显示全部楼层
本帖最后由 hy19970612 于 2013-1-22 22:02 编辑

这个 你得看看汇编 你就知道 怎么运行的了!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2013-1-22 21:59:18 | 显示全部楼层
52077643 发表于 2013-1-22 21:30
scanf()这里应该是没有前后之分的··你输入的时候没有按回车之前是应该是还没赋值··i 还是个未知数,所以 ...

恩恩,我是这个意思的。。
scanf不应该是一个一个扫描缓冲区里面输入的值,然后一个一个赋值给变量嘛。。
先扫到赋给i的,然后i有值了,接着再扫描赋给a的,然后就给a赋值。
不过以上也只是我想象的,我不了解它底层怎么处理的。所以想请大家帮忙解释下。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2013-1-22 22:00:08 | 显示全部楼层
思无邪 发表于 2013-1-22 21:32
int a[20],i;
看看你这一句 int i; 只声明 没有初始化,下面你scanf的时候 a【i】系统不知道你要指向那个单 ...

恩恩。这样的确可以。。
但是我还是想知道scanf这个东西是怎么执行扫描赋值的过程的额。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2013-1-22 22:03:36 | 显示全部楼层
hy19970612 发表于 2013-1-22 21:54
这个  是不会产生错误的!  还有 for(int j=0;;) 这样 在 C 里面是不允许的 .cpp 可以 。
scanf("%d,%d" ...

额。好吧。这个是我在cpp下面写的c。。恩恩,对的。在*.c里面的确是不可以的。
我也知道scanf(“%d,%d”,&i,&a);是对的。
我就是想知道scanf它是怎么扫描赋值的。。
为什么scanf(“%d,%d”,&i,&a)不行,i不是用户给输入进值了么
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2013-1-22 22:04:40 | 显示全部楼层
hy19970612 发表于 2013-1-22 21:54
这个 你得看看汇编 你就知道 怎么运行的了!

汇编才学一点,不懂呀。。求解释
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2013-1-22 22:06:46 | 显示全部楼层
压寨宝宝 发表于 2013-1-22 22:00
恩恩。这样的确可以。。
但是我还是想知道scanf这个东西是怎么执行扫描赋值的过程的额。。

scanf()是格式输入。
后面输入的参数要和前面的一一对应
比如:scanf(“%d;%d”,&a,&b)
你在输入的时候要 保证    整数 ; 整数  这样的格式才能正确
scanf(“%f;%c”,&a,&b)
你在输入的时候要 保证    实数 ; 字符  这样的格式才能正确
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2013-1-22 22:06:57 | 显示全部楼层
压寨宝宝 发表于 2013-1-22 22:04
汇编才学一点,不懂呀。。求解释

你把汇编代码 反上来 我帮你解释 我没 VS
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-24 16:26

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表