#include"stdio.h"
#include"math.h"
void main()
{
int i,j;
for(i=-7;i<=7;i++)
{
for(j=-7;j<=7;j++)
if(abs(i)+abs(j)==7)
printf("*");
else
printf(" ");
printf("\n");
}
} #include"stdio.h"
#include"math.h"
void main()
{
int i,j,n;
scanf("%d",&n);
for(i=-(n-1)/2;i<=(n-1)/2;i++)
{
for(j=-(n-1)/2;j<=(n-1)/2;j++)
{
if(abs(i)+abs(j)==(n-1)/2)
{
printf("*");
}
else
{
printf(" ");
}
}
printf("\n");
}
} 楼上很多空心菱形很精简啊 ,向大家学习
以下是对那个"变量都一样"的代码的自己的一点分析,不知道这样分析的对不对,不对之处还望指出
从没有见过这样来写,跟Nisy学到很多
int *b=x 其中x为某一个数字
int在内存中占两个字节,且以二进制存放,比如数字10,在内存中存放为
此时内存给它分配的空间就会有连个地址,设为1234、1235,那么00001010对应的地址应该就是1234了
当(char *)&b,因为char值占一个字节,所以它取的地址是1234,而(char *)&b+1取的就是下一个地址,也就是1235了,所以就*((char *)&b+1)就能理解为1235这个地址所对应的值,在上面数字10中对应的1235对应的值为0,即程序从第0位开始取a中的字符。所以整个程序可以这样理解#include "stdio.h"
#include "string.h"
void main()
{
int i;
char a[]="ChinaPYG!";
for(i=0;i<strlen(a);i++)
printf("%c",*(a+i));/*或则改为printf("%c",a);*/
printf("\n");
}当我们要第1位开始取值,把int *b=x中的值就应该下面的改法,看表
它对应的十进制是256,此时如果取地址1235的值,对应就是1了。
所以,只要更改x的值为256的倍数,就可以从第多少位开始取值了,而在两个相邻倍数中间的值跟上个倍数取得的一样。
int*b=x 其中(x<256),则输出结果为:ChinaPYG!
int*b=256; 则输出结果为:hinaPYG! 在256—512之间的值,运行的结果跟这个一样。
int*b=512; 则输出结果为:inaPYG!
int*b=768; 则输出结果为:naPYG!
int*b=1024; 则输出结果为:aPYG!
……
int*b=2048; 则输出结果为:!
int*b=2304; 则输出结果为:(什么也没有!后面没有了,为'\0')
而如果改成#include "stdio.h"
#include "string.h"
#define H strlen(a)
main()
{
char *a="ChinaPYG!";
int*b=0;
for( ; *((char *)&b) < H ; (*((char *)&b))++)
printf("%c",*(a + *((char *)&b)));
}只要改*b=x中的x值就行了,而这样的话,就只要是往上加1就行了,比如要从第0位开始取,那么x等于0,从第一位开始取,x=1,依次下去就行
[ 本帖最后由 unpack 于 2009-5-11 17:04 编辑 ]
代码的理解
早上看第二次视频看懵了,刚才不知道怎么回事突然间理解/*#define H strlen(a) //这个是错误的。
main()
{
char *a="ChinaPYG!";
char*b=0; // &b+2的地址超过了所分配的空间,导致错误,
//总之使用是不可以超过所分配的空间即可
//因为 char *b 等类型都是2个字节,因此加1不超过它的范围 //加1实际上是地址加1,只要不超过所申请(定义)的空间都是可以的
for(*((int *)&b+2)=0 ; *((int *)&b+2) < H ; (*((int *)&b+2))++)
printf("%c",*(a + (*((int *)&b+2))));
}
*/
/#define H strlen(a)//这个也是正确的
main()
{
char *a="ChinaPYG!";
char *b=0;
for(*((int *)&b)=0 ; *((int *)&b) < H ; (*((int *)&b))++)
printf("%c",*(a + (*((int *)&b))));
}
*/
总结:
最关键的是空间,只要你有空间就OK了。NISY的话内存中的数据你让它是什么就是什么#include "stdio.h"
#include <math.h>
main()
{
int i,j,N,F;
printf("please input a int:");
scanf("%d",&N);
if (N % 2 == 0 )
{
N=N+1;
goto ESLE;
}
else
{
ESLE: F = N/2;
for (i=0;i<N;i++)
{
for (j=0;j<=N;j++)
{
if (j == abs (F - i) || j == N - 1 - abs (F - i )) printf("*");
else if (j == N) printf("\n");
else printf(" ");
}
}
}
getch();
}
[ 本帖最后由 飘之叶 于 2009-5-13 19:05 编辑 ] 原帖由 飘之叶 于 2009-5-11 17:52 发表 https://www.chinapyg.com/images/common/back.gif
早上看第二次视频看懵了,刚才不知道怎么回事突然间理解
/*#define H strlen(a) //这个是错误的。
main()
{
char *a="ChinaPYG!";
char*b=0; // &b+2的地址超过了所分配的空间,导致错误 ...
红色的地方写的好 #define H strlen(a)
main()
{
char *a="ChinaPYG!";
//mov dword ptr ,offset string "ChinaPYG!"
//将字符串地址放入局部变量之中。所放的四个字节为从ebp-1到ebp-4
int*b=0;
//mov dword ptr ,0
//将0放入局部变量2中,该地址里面内容为0,作为指针指向地址0
//所放的位置为从ebp-5到ebp-8,四个字节。
for( ; *((char *)&b+1) < H ; (*((char *)&b+1))++)
/*
jmp main+30h (00401040)
mov al,byte ptr
//第一次循环结束跳转到这里,以后的每次循环都从这里开始。
//取b的一个字节到al
add al,1
//al自加1
mov byte ptr ,al
//将自加结果放回b中
movsx esi,byte ptr
//第一次直接跳到这里,ebp-7是取b的四字节中的一个字节
mov ecx,dword ptr
//ebp-4保存的是字符串地址,放入ecx中
push ecx
//ecx存入堆栈
call strlen (00401120)
//获得字符串长度
add esp,4
//strlen 由调用函数来恢复堆栈esp+4,使堆栈平衡
cmp esi,eax
jae main+5Fh (0040106f)
//esi如果大于等于eax,eax=字符串长度。就跳走,跳到的位置就是程序结束。否则,继续向下执行。
*/
printf("%c",*(a + *((char *)&b+1)));
/*
movsx edx,byte ptr
//b放入edx中
mov eax,dword ptr
//eax指向字符串
movsx ecx,byte ptr
//以字符串地址作为基址,以b作为偏移,取一个字节,放入ecx中。
push ecx
push offset string "%c" (0042201c)
call printf (004010a0)
//调用函数输出这一个字节。
add esp,8
//恢复堆栈
jmp main+28h (00401038)
//跳转到前面
*/
}
总结:关键是这句*((char *)&b+1),b本身就是一个指针,这句,取了b的地址,也就是堆栈中的地址,我的是0012ff78,
然后,强制转换0012ff78为字符类指针,大家都知道,字符类型指针指向的乃是一个字节,
所以,此时(char *)&b指向0012ff78这个地址的一个字节,该字节在堆栈中,然后是(char *)&b+1
该指针上移一位,指向0012ff79,因为内存是由高到底分配的,所以说是上移。
最后是一个取内容的“*”操作,取出0012ff79所存储的一个字节,也就是ebp-7中所存储的一个字节。 #define H strlen(a) //宏定义,H为字符串型指针a的长度
main()
{
char *a="ChinaPYG!"; //定义a为指向 "ChinaPYG!"的指针
int*b=0; // 定义整型指针b,其实就是开辟2个字节空间,并初始化为0。
for( ; *((char *)&b+1) < H ; (*((char *)&b+1))++) // *((char *)&b+1)相当于一个变量,指向b的第二个字节,即初始值为0。
printf("%c",*(a + *((char *)&b+1))); //逐位打印 "ChinaPYG!"中的字符
可以稍微修改下,实质是一样的。
*((char *)&b+1)改为*((char *)&b)
#define H strlen(a)
main()
{
char *a="ChinaPYG!";
int*b=0;
for( ; *((char *)&b) < H ; (*((char *)&b))++)
printf("%c",*(a + *((char *)&b)));
}
这里利用了指针的指针,变量定义的很巧妙。
打印菱形
#include"stdio.h"
#include"math.h"
void main()
{
int i,j,N;
scanf("%d",&N);
for(i=-(N-1)/2;i<=(N-1)/2;i++)
{
for(j=-(N-1)/2;j<=(N-1)/2;j++)
if(abs(i)+abs(j)==(N-1)/2) printf("*");
else printf(" ");
printf("\n");
}
}
[ 本帖最后由 qifeon 于 2009-5-11 23:24 编辑 ] // test.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "stdio.h"
#include "string.h"
#include "math.h"
int main(int argc, char* argv[])
{
int temp;
int i;
int j;
scanf("%d",&temp);
for (i=1;i<(temp+1)/2;i++)
{
printf(" ");
}
printf("*\n");
for (j=1;j<temp-1;j++)
{
for (i=1;i<temp+1;i++)
{
if (j== abs((temp+1)/2-i) || j-(temp+1)/2==(temp+1)/2-abs((temp+1)/2-i)-2)
{
printf("*");
}
else
{
printf(" ");
}
}
printf("\n");
}
for (i=1;i<(temp+1)/2;i++)
{
printf(" ");
}
printf("*\n");
return 0;
}
该程序在vc6下编译通过。
[ 本帖最后由 网际座山雕 于 2009-5-11 22:54 编辑 ]