精华内容
下载资源
问答
  • 椭圆曲线密码的C语言设计实现

    千次阅读 2013-11-13 13:05:45
    基于TOM算法库的ECC加密算法的C语言设计实现 研究生 徐立均 内容: 一、源代码下载 二、ECC算法的设计思想三、椭圆曲线参数的选取和基点的确定 四、椭圆曲线的加和纯量乘法 五、加密文件的读入输出 六、密文的...

    基于TOM算法库的ECC加密算法的C语言设计与实现 研究生 徐立均 内容: 一、源代码下载 二、ECC算法的设计思想三、椭圆曲线参数的选取和基点的确定 四、椭圆曲线的点加和纯量乘法 五、加密文件的读入与输出 六、密文的存取和读入 七、ECC加密的实现八、ECC解密的实现 九、测试结果及分析   

    一、源代码下载

    
    本文使用了TOM算法库实现了椭圆曲线公钥密码体制,能对各类不同的磁盘文件进行加密
    和解密。
    
    1 请下载可执行程序MY_ECC.exe,此程序无需任何额外的LIB或DLL,可在Windows下
    独立运行,运行情况如下:
     
    
    椭圆曲线密码的C语言设计与实现
         
    
    椭圆曲线密码的C语言设计与实现
         
    
    2 请下载源代码source.rar:
      编译此源代码需要使用TOM的高精度算法库
                    MathLib.lib
    和相关的头文件
                    tommath.h
                    tommath_class.h
                    tommath_superclass.h
    一并打包在source.rar中,请下载
    
    3 对于TOM的高精度算法库的详细说明,请看本站C语言:
    
      
    

    二、 ECC算法的设计思想

    
      根据椭圆曲线进行加密通信的过程,首先选定一个适合加密的椭圆曲线Ep(a,b),并取
    椭圆曲线上一点,作为基点G。选择一个私有密钥k,并生成公开密钥K=kG。加密时,将
    明文编码到Ep(a,b)上一点M,并产生一个随机整数r(r < n)。计算点C1=M+rK;C2=rG。
    将C1、C2存入密文。解密时,从密文中读出C1、C2,计算C1-kC2,根据:
    
      C1-kC2=M+rK-k(rG)=M+rK-r(kG)=M,
    
    解得的结果就是点M,即明文。
      
      
    

    三、椭圆曲线参数的选取和基点的确定

    
      并不是所有的椭圆曲线都适合加密,y^2=x^3+ax+b是一类可以用来加密的椭圆曲线,也
    是最为简单的一类。下面我们就选用y^2=x^3+ax+b作为我们的加密曲线。这条曲线定义在Fp
    上:两个满足下列条件的小于p(p为素数)的非负整数a、b:4a3+27b2≠0 (mod p) 则满足
    下列方程的所有点(x,y),再加上 无穷远点∞ ,构成一条椭圆曲线。y^2=x^3+ax+b(mod p) 
    其中 x,y属于0到p-1间的整数,并将这条椭圆曲线记为Ep(a,b)。
    
      参数P的选取:p 当然越大越安全,但越大,计算速度会变慢,200位左右可以满足一
    般安全要求;我们将p取为200比特位的素数。
    
      参数a、b的选取:先随机产生小于P-1的正整数作为参数a,依据条件
    4a3+27b2≠0 (mod p)判断随机产生的小于P-1的正整数是否适合作为参数b.
    
      基点的确定:随着参数a,b,p确定,这条曲线y^2=x^3+ax+b就定下来了。先随机产生0
    到p-1间的整数作为基点x坐标,计算x^3+ax+b的结果再开方就得出基点y坐标。
    上述具体程序实现如下:
    
     ……
    while(1)
    {
      //4a3+27b2≠0 (mod p)
      GetPrime(b,40);//先随机产生一个参数B
      mp_expt_d(a, 3, &temp1);
      mp_sqr(b, &temp2);
      mp_mul_d(&temp1, 4, &temp3);
      mp_mul_d(&temp2, 27, &temp4);
      mp_add(&temp3, &temp4, &temp5);
      mp_mod(&temp5,p,&temp);
      if(mp_cmp(&temp, &compare)!=0 )
      {
                break;  //满足条件跳出循环
      }
    }
      //y2=x3+ax+b,随机产生X坐标,根据X坐标计算Y坐标
      GetPrime(x1,30);// 随机产生30比特长的X坐标
      mp_expt_d(x1, 3, &temp6);
      mp_mul(a, x1, &temp7);
      mp_add(&temp6, &temp7, &temp8);
      mp_add(&temp8, b, &tempx);
      mp_sqrt(&tempx, y1);//得到Y坐标
      ……..
    私钥的确定:随机选取1到P-1之间的素数作为私钥d.
    公钥的确定:由d乘我们所确定的基点得到公钥K,即K=dG。
    
      
    

    四、 椭圆曲线的点加和纯量乘法

    
      对于一般的椭圆曲线方程y^2+a1xy+a3y=x^3+a2x^2+a4x+a6, 设点P(x1,y1),Q(x2,y2)的和
    R(x3,y3)的坐标。R(x3,y3)的计算公式如下:
    
    x3=k^2+ka1+a2+x1+x2;  
    y3=k(x1-x4)-y1-a1x4-a3;
    
    其中k= (y1-y2)/(x1-x2) 
    
    当P≠Q时
    k=(3x2+2a2x+a4 -a1y) /(2y+a1x+a3) 
    
    当P=Q时,对于椭圆曲线方程Y^2=X^3+aX+b,上述的公式变为:
    x3=θ2- x1-x2;
    y3=θ(x1-x3)-y1
    其中θ=(y1-y2)/(x1-x2) 当P≠Q时;
        θ=(3x1^2-a)/2y1    当P=Q时
    
      由上述运算公式,可以得出点积mP的运算,即mP=P+P+…+P,共m个P相加,这里m∈N.
    具体算法为:设m的二进制表示为
    
    m=(m_n-1m_n-2…m1m0),其中m_n-1=1,Q=P,从左到右依次计算:
    for(I=n-2 to 0)
    {   Q=2Q;
      if(mi ==1) Q=Q+P;
    }
    则Q=mP. 
    Return ;
    
    函数原形为:
    
    bool Ecc_points_mul(mp_int *qx,mp_int *qy, mp_int *px, mp_int *py,mp_int *d,mp_int 
    *a,mp_int *p)  
    成功返回true。
    
    int Two_points_add(mp_int *x1,mp_int *y1,mp_int *x2,mp_int *y2,mp_int *x3,mp_int 
    *y3,mp_int *a,bool zero,mp_int *p)  
    成功返回1。
    
      
    

    五、加密文件的读入与输出

    
    mp_digit只用28比特,因此一个单元最多可存放三个半字节。为充分利用存取空间,采用
    一个单元放三个半字节。
    
    1.      函数putin()实现将明文的二进制比特串赋给mp_int数a:
    
    主要循环部分及说明如下:
    
            //chlong为要存入的字符数组长
      for(j=0;j<<="(mp_digit)CHAR_BIT;" 存入高8位并向左移8位,以便放入下一个字符="" 存入字符="" 左移8位="" 并向左移4位,以便放入下一个字符的高四位="" *temp--="" 255)="">> 4); //存放被切分的字符的高四位,temp跳回前一个单元
      
           //存入第一单元
                    *temp |= (mp_digit)(ch[i-4] & yy);      //存放被切分的字符的低四位,yy=(mp_digit)15
           *temp <<= (mp_digit)CHAR_BIT;      //向左移8位,以便放入下一个字符
           *temp |= (mp_digit)(ch[i-5] & 255);      //存入字符
                    *temp <<= (mp_digit)CHAR_BIT;      //左移8位
           *temp |= (mp_digit)(ch[i-6] & 255);      //存入字符
                    *temp <<= (mp_digit)CHAR_BIT;      //左移8位
           *temp++ |= (mp_digit)(ch[i-7] & 255);   //存放被切分的字符的低四位,temp跳到后一个单元
                    temp++;       //再向后跳一单元,这样和下次的++temp实现每次循环跳两个单元
            }
    
    函数原型为:int putin(mp_int *a,char *ch,int chlong)   
    成功返回0
    
    2.函数chdraw()实现将mp_int数a中的比特串还原为字符串并赋给字符串ch:
    chdraw和putin是相反过程,将putin存入字符的过程反过来取出字符。
    
    函数原型为:int chdraw(mp_int *a,char *ch)  
    成功返回0
    
      
    

    六、密文的存取和读入

    
      此过程难点是如何保证存入文件后,再从文件中读取密文并存入mp_int型数后,和原
    存放密文的mp_int型数不能有一个比特位的改变。
    
      存取时先存*mp->dp的最高8位,再依次往下存后面3个8位。依据*mp->dp的特点,
    最高8位为0000xxxx,因此,可将255作为一个密文段的结束标志,把前一密文段和后一
    密文段区分开。这样在密文文件中,密文的存取结构为:
    
    0000xxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|0000xxxx|……|11111111|0000xxxx|xxxxxxxx|…..
     0字节   1字节   2字节   3字节   4字节      4x字节  下一加密段
                      x为1或0
    
    利用fgetc每次读取一个字符,并赋值给一个字符数组。当a[i]=255,且i%4=0时截止。
    读出之后赋值就简单了。
    
    存密文:int  chmistore(mp_int *a,FILE *fp)  成功返回0
    把密文赋给mp_int型数a:int  miwendraw(mp_int *a,char *ch,int chlong)  成功返回0
     
      
    

    七、ECC加密的实现

    
      加密时因P长度取值为200比特,所以所取明文长度应在0到199比特之间,另外需
    要一个附加的标志字节char(255),所以一次取明文最大长为191比特。在本程序中一次取
    20字节。和RSA不同,ECC运算是基于点的运算。一个点有两个参数,一个X坐标,一
    个Y坐标。所以取明文时需一次取两段,前一段做X坐标,后一段做Y坐标。因此,一次
    加密明文为40字节。由于每次加密要取两段,引发了另外一个问题:当加密文件末尾所剩
    明文长度小于20字节时的处理。在本程序中,我们的解决是将剩余明文取作X,而将Y取
    作0,且不加标志字节char(255),这样解密时,程序在Y中找不到标志字节char(255),就
    不会往解密文中存任何东西。
    
      取得明文后,产生一个随机整数r(r<有限域p),计算点C1=M+rK;C2=rG。将点C1、
    C2坐标c1x,c1y,c2x,c2y依次存入密文文件。
    
            for(i=0; i 0)// Residue为剩余字符数
            {
                 if (Residue <= enlongtemp ) 
                    {
                            fread(miwenx,1,Residue,fp);//读入字符串
                            miwenx[Residue]=char(255);
         
                            putin(&mx, miwenx,Residue+1);//文件存入 
                            mp_zero(&my);
            
                    }
                    else
                    {
                            fread(miwenx,1,enlongtemp,fp);//读入字符串
                            miwenx[enlongtemp]=char(255);
                            fread(miweny,1,Residue-enlongtemp,fp);//读入字符串
                            miweny[Residue-enlongtemp]=char(255);
    
                             putin(&mx, miwenx,enlongtemp+1);//文件存入 
                            putin(&my, miweny,Residue-enlongtemp+1);//文件存入 
                    }
            //加密
                    Ecc_points_mul(&c2x,&c2y,px,py,&r,a,p); //C2=rG
                Ecc_points_mul(&tempx,&tempy,qx,qy,&r,a,p); // rK
                    Two_points_add(&mx,&my,&tempx,&tempy,&c1x,&c1y,a,zero,p);// C1=M+rK
    
            //保存密文      
                chmistore(&c1x,fq); 
                    chmistore(&c1y,fq);
                    chmistore(&c2x,fq);
                    chmistore(&c2y,fq);  
            }
    
    函数原型为:void Ecc_encipher(mp_int *qx,mp_int *qy, mp_int *px, mp_int *py,mp_int 
    *a,mp_int *p);
    
      
    

    八、ECC解密的实现

    
      解密时,依据存密文时放入的结束标志255,读入密文。依次取4段,调用miwendraw
    将密文存入mp_int型数中,还原为加密时存入的点C1和C2坐标c1x,c1y,c2x,c2y。依据
    C1-dC2=M+rK-k(rG)=M+rK-r(kG)=M。计算C1-dC2 (d为私钥),得到明文点坐标mx,my。其
    中两点减的计算可如下:
    
      -Q=(X,-Y);P-Q=P+(-Q);-Y=P-Y;
    
      计算C1-dC2完毕后调用chdraw取出mp_int中的明文比特串,依次存入解密文件中,
    完成解密。
    
      while(!feof(fp))
      {
        //取C1点X坐标
        i=0;
        while(1)
        {
          stemp[i]=fgetc(fp);
          if(i%4==0)
          {
            if(int(stemp[i]&0xFF) == 255 ) goto L1;
          }
          i++;
        }
    L1:     miwendraw(&c1x, stemp, i);
        ………… //取其他坐标
        Ecc_points_mul(&tempx, &tempy, &c2x, &c2y, k, a, p); // 计算dC2
        mp_neg(&tempy, &temp);// -Q=(X,-Y)
        Two_points_add(&c1x,&c1y,&tempx,&temp,&mx,&my,a,zero,p);
    
        int chtem;
        chtem=chdraw(&mx,stemp);//从ming中取出字符串
    
        //保存解密结果
    
        for(int kk=0;kk < chtem;kk++)
        {
            fprintf(fq,"%c",stemp[kk]);
        }
        chtem=chdraw(&my,stemp);//从ming中取出字符串
    
        //保存解密结果
        for(kk=0;kk < chtem;kk++)
        {
            fprintf(fq,"%c",stemp[kk]);
        }
      }
    
    函数原型为:void Ecc_decipher(mp_int *k, mp_int *a,mp_int *p); 
    
      
    

    九、测试结果及分析

    
       为验证系统的加密解密功能, 对系统进行了如下测试:
    测试环境
      Intel p4 CPU 1.5G       256M RAM       windows2000 advanted server
    测试结果
      利用系统对文本文件、BMP、WORD、EXCEL、EXE等文件进行加密,然后解密。
    验证结果表明,给定的明文经系统加密后再解密的结果完全一致,没有一个比特的偏差。较好
    的实现了ECC的功能。
    转载http://210.40.7.188/NEW/ECC_XLJ/index.htm

    展开全文
  • 在平面直角坐标系中,给定一个圆的圆心坐标Ox,Oy以及半径R,在再给定一个点的坐标PX,Py,请判断这个点与圆的位置关系。 输入格式: 先输入三个正整数,分别代表圆心的横纵坐标x,Oy和半径R。 在输入两个正整数,分别...

     

    在平面直角坐标系中,给定一个圆的圆心坐标Ox,Oy以及半径R,在再给定一个点的坐标PX,Py,请判断这个点与圆的位置关系。

    输入格式:

    先输入三个正整数,分别代表圆心的横纵坐标x,Oy和半径R。 在输入两个正整数,分别代表给定点的横纵坐标PX,Py。 输入的所有数据均不超过100

    输出格式:

    如果点再圆内,输出IN, 如果点再圆上,输出ON, 如果点再圆外,输出OUT, 输出答案后需要输出回车换行。

    输入样例:

    #include<stdio.h>
    #include<stdio.h>
    int main()
    {
        int a,b,c,d,e;
        scanf("%d %d %d",&a,&b,&c);
        scanf("%d %d",&d,&e);
        if((d-a)*(d-a)+(e-b)*(e-b)<c*c)
        {
            printf("IN");
        }
        if((d-a)*(d-a)+(e-b)*(e-b)==c*c)
        {
            printf("ON");
        }
        if((d-a)*(d-a)+(e-b)*(e-b)>c*c)
        {
            printf("OUT");
            
        }
        return 0;
    }

     

    展开全文
  • C语言 使用结构体计算的面积

    千次阅读 2017-10-13 13:48:25
    结构体使用类次面向队形的类对象,元素可以使用点号运算符进行访问。 下面是一个简单的例子: /** 就算的面积,周长使用结构体 */ //定义的结构 typedef struct { double x; double y; }Point

    结构体是自定义的数据结构,类次数组,在内存中也是线性存储的。不同的是数组的每一个元素的数据类型必须一致,结构可以存放不同数据类型的元素。

    结构体使用类次面向队形的类与对象,元素可以使用点号运算符进行访问。

    下面是一个简单的例子:

    /**
    就算圆的面积,周长使用结构体
    */
    //定义点的结构
    typedef struct
    {
        double x;
        double y;
    }Point;
    //定义圆的结构
    typedef struct
    {
        Point p;//圆心
        double r;//圆的半径
    }Circle;
    
    #include<stdio.h>
    const double PI=3.141592653;
    void main()
    {
        Point p;//定义圆心
        Circle c;
        printf("输入圆心的坐标(x,y):");
        scanf("%lf,%lf",&p.x,&p.y);
        c.p=p;
        printf("输入圆的半径:");
        scanf("%lf",&c.r);
        printf("圆心为:(%.2lf,%.2lf)\n",c.p.x,c.p.y);
        printf("面积为:%lf\n",c.r*PI*PI);
        printf("周长为:%lf\n",2*c.r*PI);
        printf("Point占%d字节的内存\n",sizeof(Point));//8+8=16
        printf("Circle占%d字节的内存\n",sizeof(Circle));//16+8=24
    }
    
    测试:

    输入圆心的坐标(x,y):2,3
    输入圆的半径:2
    圆心为:(2.00,3.00)
    面积为:19.739209
    周长为:12.566371
    Point占16字节的内存
    Circle占24字节的内存
    
    Process returned 21 (0x15)   execution time : 5.507 s
    Press any key to continue.
    


    展开全文
  • C语言再学习 -- 关键字sizeofstrlen

    千次阅读 2016-08-22 16:04:19
    还有一点,sizeof是否使用括号取决于你是想获取一个类型的大小还是想获取某个具体量的大小。括号对于类型是必需的,而对于具体量则是可选的。也就是说,您应该使用sizeof(char)或sizeof(float),但是可

    sizeof 

    一、简单介绍

    sizeof 是 C 语言的一种单目操作符,如 C 语言的其他操作符++、--等。它并不是函数C 规定 sizeof 返回 sieze_t 类型的值。这是一个无符号整数类型。C99更进一步,把%zd 作为用来显示 size_t 类型值的 printf() 说明符。如果你的系统没有实现 %zd,你可以试着使用 %u 或者 %lu 代替它。

    sizeof 操作符以字节形式给出了其操作数的存储大小。操作数可以是一个表达式或括在括号内的类型名。操作数的存储大小由操作数的类型决定。


    二、使用方法

    1、用于数据类型

    sizeof 使用形式: sizeof (type)

    数据类型必须用圆括号括住。如:sizeof (int)


    2、用于变量

    sizeof 使用形式:sizeof (var_name) 或 sizeof var_name

    变量名可以不用圆括号括住。如:sizeof (6.08) 或 sizeof 6.08 等都是正确的形式。带括号的用法更普遍,大多数程序员采用这种形式。

    注意:sizeof 操作符不能用于函数类型,不完全类型和位字段。不完全类型指具有未知存储大小的数据类型,如未知存储大小的数组类型未知内容的结构或联合类型void类型等。如:


    sizeof (max) 若此时变量 max 定义为 int max ( ),

    sizeof (char_v) 若此时 char_v 定义为 char char_v [MAX] 且 MAX 未知

    sizeof (void)

    上述例子,都是不正确的形式。


    3、sizeof 的结果

    sizeof 操作符的结果类型是 size_t,它在头文件中 typedef 为 unsigned int 类型。该类型保证能容纳实现所建立的最大对象的字节大小。

    1)在windows,32位系统中
    char         1个字节
    short        2个字节
    int            4个字节
    long         4个字节
    double    8个字节
    float         4个字节


    看看这三个分别是什么?
    1,‘ 1‘,“ 1”。

    第一个是整形常数, 32 位系统下占 4 个 byte;
    第二个是字符常量,占 1 个 byte;
    第三个是字符串常量,占 2 个 byte。

    三者表示的意义完全不一样,所占的内存大小也不一样,初学者往往弄错。


    2)当操作数为指针时,sizeof 依赖于编译器。一般unix的指针为 4个字节

    #include <stdio.h>
    
    int main (void)
    {
    	char ptr[] = "hello";
    	char *str = ptr;
    	printf ("sizeof (str) = %d\n", sizeof (str));
    	return 0;
    }
    输出结果:
    sizeof (str) = 4

    在 32 位系统下,不管什么样的指针类型,其大小都为 4 byte。可以测试一下 sizeof( void *)。


    3)当操作数具有数组类型时,其结果是数组的总字节数

    #include <stdio.h>
    
    int main (void)
    {
    	int ptr[20] = {1,2,3,4,5};
    	printf ("sizeof (ptr) = %d\n", sizeof (ptr));
    	return 0;
    }
    输出结果:
    sizeof (ptr) = 80
    


    4)联合类型操作数的 sizeof 是其最大字节成员的字节数,结构体类型操作数的sizeof,需要考虑内存对齐补齐。

    参看:C语言再学习 -- 结构和其他数据形式

    [cpp] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. #include <stdio.h>  
    2.   
    3. typedef union {  
    4.     char ch;  
    5.     int num;  
    6. }UN;  
    7.   
    8. int main (void)  
    9. {  
    10.     printf ("sizeof (UN) is %d\n"sizeof (UN));  
    11.     return 0;  
    12. }  
    13. 输出结果:  
    14. sizeof (UN) is 4  

    结构体内存对齐与补齐

    一个存储区的地址一定是它自身大小的整数倍(双精度浮点类型的地址只需要4的整数倍就行了),这个规则也叫数据对齐,结构体内部的每个存储区通常也需要遵守这个规则。数据对齐可能造成结构体内部存储区之间有浪费的字节。
    结构体的大小一定是内部最大基本类型存储区大小的整数倍,这个规则叫数据补齐
    [cpp] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. #include <stdio.h>  
    2. typedef struct  
    3. {  
    4.     char ch;  
    5.     int num;  
    6.     char ch1;  
    7. }str;  
    8.   
    9. int main (void)  
    10. {  
    11.     printf ("sizeof (str) is %d\n"sizeof (str));  
    12.     return 0;  
    13. }  
    14. 输出结果:  
    15. sizeof (str) is 12  


    5)如果操作数是函数中的数组形参或函数类型的形参,sizeof给出其指针的大小

    #include <stdio.h>
    
    char ca[10];
    
    void foo (char ca[100])
    {
    	printf ("sizeof (ca) = %d\n", sizeof (ca));
    }
    int main (void)
    {
    	char ca [25];
    	foo (ca);
    	return 0;
    }
    输出结果:
    sizeof (ca) = 4
    

    三、主要用途

    1、sizeof操作符的一个主要用途是与存储分配和I/O系统那样的例程进行通信。例如:void *malloc(size_t size), size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)  

    2、sizeof的另一个的主要用途是计算数组中元素的个数。例如:void *memset(void *s,int c,sizeof(s))

    3.在动态分配一对象时,可以让系统知道要分配多少内存。如:int *p=(int *)malloc(sizeof(int)*10);

    4.由于操作数的字节数在实现时可能出现变化,建议在涉及到操作数字节大小时用sizeof来代替常量计算。

    5.如果操作数是函数中的数组形参或函数类型的形参,sizeof给出其指针的大小。


    四、注意的地方

    1、在混合类型的算术运算的情况下,较小的类型被转换成较大的类型。反之,可能会丢失数据。

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    int main (void)
    {
    	int a = 10;
    	printf ("sizeof ((a > 5) ? 4 : 8.0) = %d\n", sizeof ((a > 5) ? 4 : 8.0));
    	return 0;
    }
    输出结果:
    sizeof ((a > 5) ? 4 : 8.0) = 8
    

    2、判断表达式的长度并不需要对表达式进行求值

    #include <stdio.h>
    int main (void)
    {
    	int a = 10;
    	int b = 0;
    	int c = sizeof (b = a + 12);
    	printf ("a = %d, b = %d, c = %d\n", a, b, c);
    	return 0;
    }
    输出结果:
    a = 10, b = 0, c = 4
    

    所以sizeof (b = a + 12)并没有向 a 赋任何值。


    strlen

    strlen首先是一个函数,只能以char * 做参数返回的是字符的实际长度,不是类型占内存的大小。其结果是运行的时候才计算出来的。

    #include <string.h>
    size_t strlen(const char *s);

    函数功能:用来统计字符串中有效字符的个数

    功能实现函数:

    [cpp] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. size_t strlen (const char *s)  
    2. {  
    3.     const char *sc;  
    4.     for (sc = s; *sc != '\0'; ++sc)  
    5.     /"nothing"/  
    6.     return sc - s;  
    7. }  

    strlen()函数被用作改变字符串长度,例如:

    [cpp] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. #include <stdio.h>  
    2. #include <string.h>  
    3. void fit (char *, unsigned int);  
    4. int main (void)  
    5. {  
    6.     char str[] = "hello world";  
    7.     fit (str, 7);  
    8.     puts (str);  
    9.     puts (str + 8);  
    10.     return 0;  
    11. }  
    12.   
    13. void fit (char *string, unsigned int size)  
    14. {  
    15.     if (strlen (string) > size)  
    16.         *(string + size) = '\0';  
    17. }  
    18. 输出结果:  
    19. hello w  
    20. rld  

    可以看出:fit()函数在数组的第8个元素中放置了一个'\0'字符来代替原有的o字符。puts()函数输出停在o字符处,忽略了数组的其他元素。然而,数组的其他元素仍然存在。

    puts (str + 8);

    表达式str + 8是str[8]即'r'字符的地址。因此puts()显示这个字符并且继续输出知道遇到原字符串中的空字符。


    sizeof 与 strlen 的区别

    参看:C语言再学习 -- 字符串和字符串函数

    谈两者的区别之前,先要讲一下什么是字符串,字符串就是一串零个或多个字符,并且以一个位模式为全 0 的 '\0' 字节结尾。如在代码中写 "abc",那么编译器帮你存储的是 "abc\0"。

    siezeof运算符提供给你的数目比strlen大1,这是因为它把用来标志字符串结束的不可见的空字符('\0')也计算在内。

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    int main (void)
    {
    	char *str1 = "abcde";
    	char str2[] = "abcde";
    	char str3[8] = "abcde";
    	char str4[] = {'a', 'b', 'c', 'd', 'e'};
    	char *p1 = malloc (20);
        
    	printf ("sizeof (str1) = %d, strlen (str1) = %d\n", sizeof (str1), strlen (str1));
    	printf ("sizeof (*str1) = %d, strlen (str1) = %d\n", sizeof (*str1), strlen (str1));
    	printf ("sizeof (str2) = %d, strlen (str2) = %d\n", sizeof (str2), strlen (str2));
    	printf ("sizeof (str3) = %d, strlen (str3) = %d\n", sizeof (str3), strlen (str3));
    	printf ("sizeof (str4) = %d, strlen (str4) = %d\n", sizeof (str4), strlen (str4));
    	printf ("sizeof (p1) = %d, sizeof (*p1) = %d\n", sizeof (p1), sizeof (*p1));
    	printf ("sizeof (malloc(20)) = %d\n", sizeof (malloc (20)));
    	return 0;
    }
    输出结果:
    sizeof (str1) = 4, strlen (str1) = 5
    sizeof (*str1) = 1, strlen (str1) = 5
    sizeof (str2) = 6, strlen (str2) = 5
    sizeof (str3) = 8, strlen (str3) = 5
    sizeof (str4) = 5, strlen (str4) = 5
    sizeof (p1) = 4, sizeof (*p1) = 1
    sizeof (malloc(20)) = 4


    总结:

    1. sizeof 操作符的结果类型是 size_t,它在头文件中typedef为 unsigned int 类型。该类型保证能容纳实现所建立的最大对象的字节大小。

    2. sizeof 是算符,strlen 是函数

    3. sizeof可以用类型做参数strlen只能用char*做参数且必须是以''\0''结尾的。sizeof 还可以用函数做参数,比如:

    short f();
    printf("%d\n",sizeof(f()));
    输出的结果是sizeof(short),即2。

    4.数组做 sizeof 的参数不退化,传递给 strlen 就退化为指针了。

    5.大部分编译程序 在编译的时候就把 sizeof 计算过了 是类型或是变量的长度这就是 sizeof(x) 可以用来定义数组维数的原因
    charstr[20]="0123456789";
    int a=strlen(str);//a=10;
    int b=sizeof(str);//而b=20;

    6. strlen 的结果要在运行的时候才能计算出来,是用来计算字符串的长度,不是类型占内存的大小

    7. sizeof 后如果是类型必须加括弧,如果是变量名可以不加括弧。这是因为sizeof是个操作符不是个函数。

    8. 当适用了于一个结构类型时或变量, sizeof 返回实际的大小,当适用一静态地空间数组, sizeof 归还全部数组的尺寸。sizeof 操作符不能返回动态地被分派了的数组或外部的数组的尺寸。

    9. 数组作为参数传给函数时传的是指针而不是数组,传递的是数组的首地址,如:
    fun(char [8])
    fun(char [])
    都等价于 fun(char *)
    在C++里参数传递数组永远都是传递指向数组首元素的指针,编译器不知道数组的大小如果想在函数内知道数组的大小, 需要这样做:进入函数后用memcpy拷贝出来,长度由另一个形参传进去
    fun(unsiged char*p1, int len)
    {
        unsigned char* buf= new unsigned char[len+1]
        memcpy(buf, p1,len);
    }

    我们能常在用到 sizeof 和 strlen 的时候,通常是计算字符串数组的长度看了上面的详细解释,发现两者的使用还是有区别的,从这个例子可以看得很清楚:

    charstr[20]="0123456789";
    int a=strlen(str);//a=10; >>>> strlen 计算字符串的长度,以结束符 0x00 为字符串结束。
    int b=sizeof(str);//而b=20; >>>> sizeof 计算的则是分配的数组 str[20] 所占的内存空间的大小,不受里面存储的内容改变。
    上面是对静态数组处理的结果,如果是对指针,结果就不一样了

    char* ss ="0123456789";
    sizeof(ss) 结果4 ===》ss是指向字符串常量的字符指针,sizeof 获得的是一个指针的之所占的空间,应该是 长整型的,所以是4
    sizeof(*ss) 结果1 ===》*ss是第一个字符 其实就是获得了字符串的第一位'0' 所占的内存空间,是char类 型的,占了 1 位
    strlen(ss)= 10 >>>> strlen 计算字符串的长度,以结束符 0x00 为字符串结束


    面试题:

    1、sizeof( int) *p 表示什么意思?

    需要明白 sizeof 后跟数据类型,必须要用圆括号括住的,强制类型转换也应该是 (int*) p,所以这句话所表达的意思是 sizeof (int) 乘以 p

    #include <stdio.h>
    
    int main (void)
    {
    	int p = 1;
    	printf ("%d\n", sizeof (int)*p); 
    	return 0;
    }
    输出结果:
    4

    #include <stdio.h>
    
    int main (void)
    {
    	int p = 1;
    	printf ("%d\n", sizeof ((int *)p));  //强制类型转换
    	return 0;
    }
    输出结果:
    4

    2、在 32 位系统下:
    int *p = NULL;
    sizeof(p)的值是多少?
    sizeof(*p)呢?

    sizeof (p) = 4;  因为 p为指针,32位系统 指针所占字节为 4个字节

    sizeof (*p) = 4;  因为 *p 为 指针所指向的变量为int类型,整型为 4个字节

    #include <stdio.h>
    
    int main (void)
    {
    	short *p = NULL;
    	int i = sizeof (p);
    	int j = sizeof (*p);
    	printf ("i = %d, j = %d\n", i, j);
    	return 0;
    }
    输出结果:
    i = 4, j = 2

    3、int a[100];
    sizeof (a) 的值是多少?
    sizeof(a[100])呢? //请尤其注意本例。
    sizeof(&a)呢?
    sizeof(&a[0])呢?

    sizeof (a) = 400;  因为 a是类型为整型、有100个元素的数组,所占内存为400个字节

    sizeof (a[100]) = 4;  因为 a[100] 为数组的第100元素的值该值为 int 类型,所占内存为4个字节。

    sizeof (&a) = 4;  因为 &a 为数组的地址即指针,32位系统 指针所占字节为 4个字节

    sizeof (&a[0]) = 4; 因为&a[0] 为数组的首元素的地址即指针,32位系统 指针所占字节为 4个字节

    #include <stdio.h>
    
    int main (void)
    {
    	int a[100];
    	printf ("sizeof (a) = %d\n", sizeof (a));
    	printf ("sizeof (a[100] = %d\n", sizeof (a[100]));
    	printf ("sizoef (&a) = %d\n", sizeof (&a));
    	printf ("sizeof (&a[0] = %d\n)", sizeof (&a[0]));
    	return 0;
    }
    输出结果:
    sizeof (a) = 400
    sizeof (a[100] = 4
    sizoef (&a) = 4
    sizeof (&a[0] = 4
    

    4、int b[100];
    void fun(int b[100])
    {
    sizeof(b);// sizeof (b) 的值是多少?
    }

    sizeof (b) = 4;  因为函数中的数组形参或函数类型的形参,sizeof给出其指针的大小。参数传递数组永远都是传递指向数组首元素的指针。

    #include <stdio.h>
    
    void fun (int b[100]) //指针做形参
    {
    	printf ("sizeof (b) = %d\n", sizeof (b));
    }
    
    int main (void)
    {
    	int a[10];
    	fun (a);
    	return 0;
    }
    输出结果:
    sizeof (b) = 4

    #include <stdio.h>
    void foo (void)
    {
    	printf ("111\n");
    }
    
    void fun (foo) //函数做形参
    {
    	printf ("sizeof (foo) = %d\n", sizeof (foo));
    }
    int main (void)
    {
    	fun ();
    	return 0;
    }
    输出结果:
    sizeof (foo) = 4




    展开全文
  • c语言经典案例

    2014-10-30 08:06:57
    实例276 绘制红色间隔填充的 多边形 424 实例277 绘制五角星 425 实例278 颜色变换 427 实例279 彩色扇形 428 实例280 输出不同字体 429 实例281 相同图案的输出 431 实例282 设置文本及背景颜色 433
  • 巧记:非→算数→关系→和→赋值 在六个关系运算符中,<,<=,>,>=的优先级相同,高于==和!=,==和!=的优先级相同。 逻辑关系中:&& 的高于其他||… 优先级【高到低】: 第一级: 括号【()...
  • c语言代码程序

    2013-11-19 21:07:12
    输入数组,最大的第一个元素交换,最小的最后一个元素交换,输出数组 有n个整数,使其前面各数顺序向后移m个位置,最后m个数变成最前面的m个数 有n个人围成一圈,顺序排号。从第一个人开始报数(从1到3报数),...
  • C语言及程序设计(公开课)主页

    千次阅读 2016-11-15 09:22:13
    1.1 人人学程序设计 1.2 程序设计语言 1.3 搭建C语言的运行平台 1.4 C语言程序初体验 实践任务:链接 参考解答:1-星号拼字母 2-长方形周长和面积 3-并联电阻 4-圆柱表面积 1.5分支结构程序体验 第2章 ...
  • c语言实战105例源码

    2018-03-01 18:19:49
    关于C语言一些简单的实例,里面有些思想值得借鉴 1 一个价值“三天”的BUG  2 灵活使用递增(递减)操作符  3 算术运算符计算器  4 逻辑运算符计算器 5 IP地址解析  6 用if…else语句解决奖金发放问题...
  • c语言实用代码举例

    2012-02-10 11:01:51
     实例39黄黑相间的矩形与圆  实例40六叶图案  实例41特殊图案  实例42国际象棋棋盘  实例43制作楼梯  实例44使用线类型函数设置多个汉字  实例45彩色群  实例46饼图  买例47产品折线图  实例48直方图  ...
  • C语言 poj1328题

    2018-09-16 17:15:50
    岛屿以d为半径做x轴的两个交点构成一条线段,能够扫到该岛屿的雷达一定在该线段上,将所有的线段按左端点大小从左到右排序,若前一个岛屿的右端比后一个岛屿的左端点大,则两个岛屿能共用一个雷达,否则不能...
  • C语言实例解析精粹 PDF

    热门讨论 2010-08-17 00:20:25
    本书主要讲解C语言编程涉及的各类常见实例,共分8篇,以“基础篇→数据结构篇→数值计算趣味数学 篇→图形篇→系统篇→常见试题解答篇→游戏篇→综合实例篇”具体展开,共汇集220个实例,基本涵盖 了目前C语言...
  • C语言不仅提供了极为丰富的库函数(如Turbo C,MS C 都提供了三百多个库函数),还允许用户建立自己定义的函数。用户可把自己的算法编成一个个相对独立的函数模块,然后用调用的方法来使用函数。  可以说C程序的...
  • C语言实战105例源码

    2012-04-11 18:41:37
    (无需积分)C语言实战105例源码 其他的都是要分值的,转来的不要积分 第1部分 基础篇 实例1 一个价值“三天”的BUG 2 实例2 灵活使用递增(递减)操作符 5 实例3 算术运算符计算器 7 实例4 逻辑运算符...
  • C语言编程100例精选源码

    热门讨论 2009-10-29 01:31:44
    共分为8篇,包括基础篇、数值计算数据结构篇、文本屏幕文件操作篇、病毒安全篇、图形篇、系统篇、游戏篇、综合篇,基本涵盖了目前C语言编程的各个方面。  全部以实例为线索展开讲解,注重对实例的分析、对...
  • C语言经典算法100例.rar

    热门讨论 2008-09-09 20:05:04
     实例39黄黑相间的矩形与圆  实例40六叶图案  实例41特殊图案  实例42国际象棋棋盘  实例43制作楼梯  实例44使用线类型函数设置多个汉字  实例45彩色群  实例46饼图  买例47产品折线图  实例48直方图  ...
  • C语言实战105例》

    2012-12-07 21:45:48
    C语言实战105例》 目录 实例1 一个价值“三天”的BUG 2 实例2 灵活使用递增(递减)操作符 5 实例3 算术运算符计算器 7 实例4 逻辑运算符计算器 9 实例5 IP地址解析 11 实例6 用if…else语句解决奖金发放...
  • C语言经典例题100道

    2011-01-10 13:14:03
    学习putpixel画 63.画椭圆ellipse 64.利用ellipse and rectangle画图 65.画个最优美的图案 66.输入3个数字按大小顺序输出 67.输入数组交换元素重新输出 68.多个整数后移位置问题 69.圆圈报数问题 70.计算一个字符...
  • 同时在后会分别介绍GCC编译器Clang编译器的C语言语法扩展。通过阅读本书,读者能够完全掌握新标准的C语言编程。并且对C语言设计思想、实现方式也能有个大概的了解。 前言 第一篇 预备知识篇 第1章 C魔法概览 /2 ...
  • C语言实战105个例子

    2011-04-03 21:55:58
    第2部分 数值计算数据结构篇 实例16 常用的几种排序方法 46 实例17 广度优先搜索及深度优先搜索 53 实例18 实现基本的串操作 59 实例19 计算各到源点的最短距离 62 实例20 储油问题 65 实例21 中奖...
  • 数据结构(c语言)汉诺塔(Hanno)递归实现 一、 汉诺塔(Hanno) ...我们对Markdown编辑器进行了一些功能拓展语法支持,除了标准的Markdown编辑器功能,我们增加了如下几新功能,帮助你用它写博客:
  • C++题目:定义一个类,输入半径,输出元的面积和周长 33%(259/784) 68% 2020-4-23 1061 C++题目:用于存放图书的栈类 45%(38/84) 55% 2019-12-16 1062 C++题目:利用重载求最小值 39%(104/267) 62% 2019-12-16 ...
  • 实例39 黄黑相间的矩形与圆 114 实例40 六叶图案 116 实例41 特殊图案 118 实例42 国际象棋棋盘 119 实例43 制作楼梯 121 实例44 使用线类型函数设置多个汉字 123 实例45 彩色群 125 实例46 饼图 126 实例...
  • 到直线的垂足,关于直线的对称,线段关于直线的反射线 绕给定点旋转 判断在三角形(和椭圆)内 直线(和线段)三角形碰撞,三角形三角形碰撞 两平行矩形碰撞,平行矩形椭圆碰撞
  • 就拿传统的圆与正方形问题为例子,基类是Shape,每个类定义虚函数showShape(),从而体现多态。 大概思想就是每个结构体头都一样(当作某个基类),这样可以用结构体头指针指向任何结构体,虚函数就是在这个结构体...

空空如也

空空如也

1 2 3 4 5 6
收藏数 106
精华内容 42
关键字:

c语言点与圆

c语言 订阅