首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

关于字符数组,字符串与指针的学问,输出结果的疑问

2013-09-17 
关于字符数组,字符串与指针的知识,输出结果的疑问?先说说自己的理解吧,在主函数中先调用f(a,0,strlen(a)-1

关于字符数组,字符串与指针的知识,输出结果的疑问?
先说说自己的理解吧,在主函数中先调用f(a,0,strlen(a)-1)此时strlen(a)-1的值为2,也就是f(a,0,2).顺序执行进入f(,,)函数,根据判断条件执行for语句。执行swap(&a[begin],&a[i]);此时为swap(&a[0],&a[0]) 这个&a[0]在内存中存储的内容为“123”,调用swap(,)因为swap形参类型为char也就是,交换char值也就是1和1进行交换。然后在执行f(a,1,2)递归。就像这样执行到,f(a,2,2)的时候执行printf,输出结果:123。也就是说for循环中的递归结束了。现在轮到下面的swap()执行了,但是交换的还是相同的值啊。此时i的值为1<2。继续执行for循环swap(&a[1],&a[2])而&a[1]与&a[2]所存的内容分别为“23”,“3”,也就是说是2和3进行交换,再次执行f(a,2,2)输出结果132,这趟递归结束。执行下一个swap(),swap(&a[1],&a[2])还是2和3交换。i的值为2至此该程序就应该结束了啊  

以下是程序代码,对这个程序的递归执行流程不清楚,烦请理解的人帮忙分析下,谢谢!


#include <stdio.h>
#include <string.h>
void swap(char *a,char *b)
{
char temp;
temp=*a;
*a=*b;
*b=temp;
}
void f(char *a,int begin,int end)
{
int i;
if(begin==end)
printf("%s\n",a);
else 
for(i=begin;i<=end;i++)
{
swap(&a[begin],&a[i]); 
f(a,begin+1,end);
swap(&a[begin],&a[i]);
}
}
void main()
{
char  a[10]="123";
f(a,0,strlen(a)-1);
}

输出结果是:
123
132
213
231
321
312
 
[解决办法]
首先,一般不大推荐使用递归,但楼主是想要学习这方面另说了(递归效率比较慢)

其次,楼主要干嘛? 是想把调换位置么?例如:123456789,调换成987654321?
      也就是说把第一个和最后一个对换,第二个和倒数第二个对换? 
      下次,请先将你要完成的目标写下,这样大家给你解决问题,也知道要怎么去解决?

最后,楼主,还要继续理解下递归的原理,感觉楼主的写代码(需要加油哦)

已经修正

输出如下:
123456789
987654321
请按任意键继续. . .

// 654151.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <stdio.h>
#include <string.h>
void swap(char *a,char *b)
{
char temp;
temp=*a;
*a=*b;
*b=temp;
}
void f(char *a,int begin,int end)
{
int i;
if(begin>=end) {
//printf("%s\n",a);
return;
}

else 
{
swap(&a[begin],&a[end]); 
f(a,begin+1,end-1);
}
}
void main()
{
char  a[]="123456789";
printf("%s \n", a);


f(a,0,strlen(a)-1);
printf("%s \n", a);
return;
}


[解决办法]
你这个的确是到i=2就结束了,但是你会发现一个问题就是他会加深一层for循环,就是他里面的f()函数还会
有一层循环
[解决办法]
我自己的分析过程,感觉还是这样写出来比较清晰点吧

关于字符数组,字符串与指针的学问,输出结果的疑问
[解决办法]
画递归树

字数补丁
[解决办法]
在F(2,2)的时候就输出了。。
[解决办法]
引用:
Quote: 引用:

首先,一般不大推荐使用递归,但楼主是想要学习这方面另说了(递归效率比较慢)

其次,楼主要干嘛? 是想把调换位置么?例如:123456789,调换成987654321?
      也就是说把第一个和最后一个对换,第二个和倒数第二个对换? 
      下次,请先将你要完成的目标写下,这样大家给你解决问题,也知道要怎么去解决?

最后,楼主,还要继续理解下递归的原理,感觉楼主的写代码(需要加油哦)

已经修正

输出如下:
123456789
987654321
请按任意键继续. . .

// 654151.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <stdio.h>
#include <string.h>
void swap(char *a,char *b)
{
char temp;
temp=*a;
*a=*b;
*b=temp;
}
void f(char *a,int begin,int end)
{
int i;
if(begin>=end) {
//printf("%s\n",a);
return;
}

else 
{
swap(&a[begin],&a[end]); 
f(a,begin+1,end-1);
}
}
void main()
{
char  a[]="123456789";
printf("%s \n", a);
f(a,0,strlen(a)-1);
printf("%s \n", a);
return;
}


其实这是个考研题,就是让我读这个程序看这个的输出结果是什么的。估计是为了考察对指针和递归的理解吧!


哦,明白了,个人感觉这个代码实际工作是不可能会这样的。递归又和循环,而且递归后面还有代码,且代码 值还会根据递归进行变化。好吧我承认这道题目有些纠结。不知道咋了,还是花了不少时间去分析下。

有耐心的话,这道题目还是蛮好解的,这道题目耐心是关键。
下面是解的过程。。


for:--a
i=0
swap(0,0)
f(1, 2)---1
for:i=1
swap(1,1)
f(2, 2)---2
printf: 123
回到f(2, 2)---2 回
for:--b
i=1
swap(1,1)
i=2
swap(1,2)**交换12 132
f(2, 2)---3
printf: 132
回到f(2, 2)---3 回
swap(1,2)**交换12   123
i=3
结束for --b
回到f(1, 2)---1 回


swap(0,0)
i=1
f(1, 2)---4
swap(0,1)**交换01   213
f(1, 2)---5
for:--c
 i=1
 swap(1,1)
 f(2, 2)---6
printf: 213
 回到f(2, 2)---6 回
 swap(1,1)
 i=2
 swap(1,2)**交换12   231
 f(2, 2)---7
 printf: 231
 f(2, 2)---7 回
 swap(1,2)**交换12   213
 i=3
 结束for --c
回到f(1, 2)---5 回
swap(0,1)**交换01   123
i=2
swap(0,2)  **交换02   321
f(1, 2)---8
for--d
i=1
swap(1,1)
f(2, 2)---9
printf: 321
回到f(2, 2)---9 回
swap(1,1)
i=2
swap(1,2)**交换12   312
f(2, 2)---10
printf: 312
回到f(2, 2)---10 回
swap(1,2)**交换12   321
i=3
结束for --d
回到f(1, 2)---8 回
swap(0,2)
i=3
结束for--a
[解决办法]
上面是简单的解析过程,其实画个递归图可能更好理解一些。

就是递归+循环把人容易搞晕。
而且递归后面有操作。。。。
[解决办法]
计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构……

对学习编程者的忠告:
眼过千遍不如手过一遍!
书看千行不如手敲一行!
手敲千行不如单步一行!
单步源代码千行不如单步对应汇编一行!

VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。
(Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)

想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!
指针即地址。“地址又是啥?”“只能从汇编语言和计算机组成原理的角度去解释了。”
但我又不得不承认:
 有那么些人喜欢或者适合用“先具体再抽象”的方法学习和理解复杂事物;
 而另一些人喜欢或者适合用“先抽象再具体”的方法学习和理解复杂事物。
而我本人属前者。

这辈子不看内存地址和内存值;只画链表、指针示意图,画堆栈示意图,画各种示意图,甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗?本人深表怀疑!
这辈子不种麦不收麦不将麦粒拿去磨面;只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头,压面条,烤面包,……能从本质上理解面粉、理解面食吗?本人深表怀疑!!

提醒:
“学习用汇编语言写程序”

“VC调试(TC或BC用TD调试)时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
想要从本质上理解C指针,必须学习C和汇编的对应关系。”
不是一回事!

不要迷信书、考题、老师、回帖;
要迷信CPU、编译器、调试器、运行结果。
并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。
任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实!

有人说一套做一套,你相信他说的还是相信他做的?


其实严格来说这个世界上古往今来所有人都是说一套做一套,不是吗?

不要写连自己也预测不了结果的代码!

电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址;
人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……

十字链表交换任意两个节点C源代码(C指针应用终极挑战)http://download.csdn.net/detail/zhao4zhong1/5532495

热点排行