2011-08-26 52 views
0

我在编译下面的代码时遇到了一些问题,我认为问题与将gmplib链接到编译器有关。在Windows上编译cpp代码与gmplib时的链接问题

我无法理解如何在Windows上设置lib或如何编译它。这是我的代码。变量名称和评论用法语编写。对不起。

// projet(essai final).cpp : Defines the entry point for the console application. 
// 

//****** la classe rsa_gmp.h ******* 
#include "stdafx.h" 
#include<iostream> 
#include <string.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <gmp.h> 
#include <time.h> 
using namespace std; 


class Class_one { 
private: 
    string fichierSource; 
    string fichierDest; 
    int tailleBloc ; 
public: 
    Class_one(); 
    void PGCD (mpz_t ,mpz_t,mpz_t); 
    void puissance(mpz_t,mpz_t,mpz_t,mpz_t); 
    void test_primalite(mpz_t,mpz_t); 
    void InitialiseRandom(gmp_randstate_t); 
    void nextprime (mpz_ptr , mpz_srcptr) ; 
    void Genere_publicKey(mpz_t ,mpz_t , mpz_t ,gmp_randstate_t ); 
    void Genere_privateKey (mpz_t , mpz_t , mpz_t) ; 
    void Genere_nbPremier(mpz_t , mpz_t , int , gmp_randstate_t ) ; 
    void chiffre_Msg(mpz_t , mpz_t , mpz_t , mpz_t); 
    void dechiffre_Msg(mpz_t , mpz_t , mpz_t , mpz_t); 
    short int SetFichiers(string nomFichierDest, string nomFichierSource); 
    string DeTranscoder(mpz_t ); 
    mpz_t Transcoder(string) ; 
    ~Class_one(); 
} 


Class_one::Class_one(){ 

    this->fichierDest=""; 
    this->fichierSource=""; 
    this->tailleBloc=256; 
}; 
Class_one::~Class_one(){}; 

void Class_one::PGCD (mpz_t resultat, mpz_t a , mpz_t b) 
{ 
    mpz_t r , r1 ,r2; 

    //intialiser les variables 
    mpz_init(r); 
    mpz_init(r1); 
    mpz_init(r2); 

    // affectation 
    mpz_set (r , a) ; 
    mpz_set (r1 , b) ; 

    while (mpz_cmp_ui (r1, 0) != 0) 
    { 
     mpz_mod (r2, r, r1); 
     mpz_set (r , r1) ; 
     mpz_set (r1 , r2) ; 
    } 

    mpz_set (resultat , r) ; 
    // liberer l'espace de variable 
    mpz_clear(r); 
    mpz_clear(r1); 
    mpz_clear(r2); 

} 


void Class_one::puissance (mpz_t resultat ,mpz_t a, mpz_t e, mpz_t n) 
{ 
    mpz_t temp,t,a_bis,e_bis ; 
    // initialise la variable local 
    mpz_init(temp); 
    mpz_init(t); 

    mpz_init(a_bis); 
    mpz_set(a_bis , a); 

    mpz_init(e_bis); 
    mpz_set(e_bis , e); 

    mpz_set_ui (temp , 1); 

    while (mpz_cmp_ui (e_bis,0)> 0) 
    { 
     mpz_mod_ui(t , e_bis , 2); 
     if(mpz_cmp_ui(t , 0) != 0) 
     { 
      mpz_mul(temp , temp , a_bis); 
      mpz_mod(temp , temp ,n); 
     } 
     mpz_mul(a_bis , a_bis, a_bis); 
     mpz_mod (a_bis, a_bis, n); 

     mpz_tdiv_q_ui(e_bis,e_bis,2); 
    } 

    mpz_set(resultat , temp); 
    // liberer l'espace utilisé 
    mpz_clear(temp);mpz_clear(t); 
    mpz_clear(a_bis);mpz_clear(e_bis); 

} 


/* 
La test_primalite verifie si un nombre est premier,c'est une application 
de Miller_Rabin 
@ param long a, n(mod n) 
@return 1 ou 0 
*/ 
void Class_one::test_primalite (mpz_t resultat , mpz_t n) 
{ 
    mpz_t var ,p, e, m , i , k ,temp ; 
    // initialiser les variables locals 
    mpz_init(var) ;mpz_init(p) ;mpz_init(e) ;mpz_init(temp) ; 
    mpz_init(m) ;mpz_init(i) ;mpz_init(k) ; 

    mpz_sub_ui (m , n , 1); 
    mpz_sub_ui (e , n , 1); 
    mpz_set_ui(var , 10); 

    mpz_set_ui (k , 0); 
    mpz_mod_ui (temp , e , 2); 

    while (mpz_cmp_ui (temp , 0)== 0) 
    { 
     mpz_tdiv_q_ui(e , e , 2); 
     mpz_add_ui (k , k , 1); 
     mpz_mod_ui (temp , e , 2); 
    } 

    Class_one::puissance(mpz_t p ,mpz_t var ,mpz_t e , mpz_t n); 

    if(mpz_cmp_ui (p , 1) == 0) 
    { 
     mpz_set_ui(resultat , 1); 
     return; 
    } 

    mpz_set_ui(i , 0); 

    while(mpz_cmp (i , k) < 0) 
    { 
     if(mpz_cmp(p , m)== 0) 
     { 
      mpz_set_ui(resultat , 1); 
      break ; 
     } 

     if(mpz_cmp_ui(p , 1)== 0) 
     { 
      mpz_set_ui(resultat , 0); 
      break ; 
     } 

     mpz_mul(p, p , p); 
     mpz_mod(p , p , n) ; 

     mpz_add_ui (i, i , 1); 
    } 


    // liberer l'espace utilisé par les variables locals 
    mpz_init(var) ;mpz_init(p) ; mpz_init(e) ;mpz_init(temp) ; 
    mpz_init(m) ;mpz_init(i) ;mpz_init(k) ; 
} 


// la fonction initializeRandom permet d,initialiser le generateur de nombre aleatoire 
void Class_one::InitialiseRandom(gmp_randstate_t r_state) 
{ 
    /* Initialisation de nombre aleatoire*/ 
    unsigned long int seed; 
    seed = time(0); 

    gmp_randinit_default (r_state); 
    gmp_randseed_ui(r_state, seed); 
} 


// le nextprime permet de calculer le nombre premier suivant 
void Class_one::nextprime (mpz_ptr p, mpz_srcptr t) 
{ 
    mpz_t test ; 
    mpz_init(test); 
    mpz_add_ui (p, t, 13); 

    void Class_one::test_primalite (mpz_t test ,mpz_t p); 
    while (mpz_cmp_ui(test , 0)!= 1) 
    { 
     mpz_add_ui (p, p, 13); 
     void Class_one::test_primalite (mpz_t test , mpz_t p); 
    } 

} 



// la fonction genere_PK() permet de créer la clé public e 

void Class_one:: Genere_publicKey(mpz_t e ,mpz_t p , mpz_t q ,gmp_randstate_t state) 
{ 
    mpz_t a , b , c, r , y ,rand_Num; 

    // initialiser les avriable locale 
    mpz_init(a); 
    mpz_init(b); 
    mpz_init(c); 
    mpz_init(y); 
    mpz_init(r); 
    mpz_init(rand_Num); 

    mpz_sub_ui(a, p, 1); 
    mpz_sub_ui(b, q, 1); 

    mpz_mul(y, a, b); 

    //Définition d'une valeur max de E. 
    mpz_t max; 
    mpz_init(max); 
    mpz_set_str (max , "97" ,0); 

    mpz_urandomm(rand_Num, state, max); 
    mpz_add_ui (rand_Num , rand_Num , 3); 
    mpz_mod(c,rand_Num,y); 
    void Class_one::PGCD(mpz_t r , mpz_t c, mpz_t y); 

    while ((mpz_cmp_ui(r,1)!= 0) ||mpz_cmp(c ,max)>0 ||mpz_cmp_ui(c ,0) ==0) 
    { 
     mpz_urandomm(rand_Num, state, max); 
     mpz_add_ui (rand_Num , rand_Num , 3); 
     mpz_mod(c,rand_Num,y); 
     void Class_one::PGCD(mpz_t r , mpz_t c, mpz_t y); 
    } 
    mpz_set(e ,c) ; 
    // effacer les espaces utilisées par les variables 
    mpz_clear(a);mpz_clear(b);mpz_clear(y);mpz_clear(r); 
    mpz_clear(rand_Num);mpz_clear(max);mpz_clear(c); 


} 



// La fonction genere_privateKey permet de determiner la clé public 
// algorithme euclide etendu 
void Class_one::Genere_privateKey (mpz_t d , mpz_t e , mpz_t phi) 
{ 
    mpz_t e0,t0 , t , q, r, n0, temp ,temp2; 

    // initialiser les variables 
    mpz_init (e0);mpz_init (t0);mpz_init (t);mpz_init (q); 
    mpz_init (r);mpz_init (n0);mpz_init (temp);mpz_init (temp2); 

    mpz_set_ui(t , 1) ; 
    mpz_set (n0 , phi); 
    mpz_set (e0 , e); 
    mpz_tdiv_q(q , n0 , e0); 
    mpz_mod (r ,n0 , e0) ; 

    while(mpz_cmp_ui (r, 0) > 0) 
    { 
     mpz_mul(temp , q, t); 
     mpz_sub(temp , t0, temp); 

     if(mpz_cmp_ui (temp , 0) >= 0) 
     { 
      mpz_mod (temp , temp ,phi); 
     } 
     else 
     { 
      mpz_mod(temp , temp , phi); 
     } 

     mpz_set(t0 , t); 
     mpz_set(t , temp); 
     mpz_set(n0, e0); 
     mpz_set(e0, r); 
     mpz_tdiv_q(q , n0 , e0); 
     mpz_mod (r ,n0 , e0) ; 

    } 
    mpz_set (d , t); 
    // liberer l'espaces des variables 
    mpz_clear(e0);mpz_clear(t0);mpz_clear(t);mpz_clear(q); 
    mpz_clear(r);mpz_clear(n0);mpz_clear(temp);mpz_clear(temp2); 
} 




/* 
La fonction Genere_nbPremier retourne les deux entiers P et Q 
aleatoires et premiers 
*/ 

void Class_one::Genere_nbPremier(mpz_t p, mpz_t q, int n, gmp_randstate_t state) 
{ 
    //création de varaiable locale 
    mpz_t rand, nb_aleatoire, max , min , varp , varq; 

    // initialiser les variables 
    mpz_init(rand); mpz_init(nb_aleatoire); mpz_init(max); 
    mpz_init(min);mpz_init(varp);mpz_init(varq); 

    // calcule du Borne Superieur 
    mpz_ui_pow_ui(max, 2, n+1); 
    // calcule du borne inferieur 
    mpz_ui_pow_ui(min, 2, n); 

    // Génère un nombre compris entre 0 et max et le stocke dans rand. state initialise le générateur aléatoire. 
    do 
    { 
     mpz_urandomm(rand, state, max); 

    }while(mpz_cmp(rand, min) > 0); 
    // Vérifie que rand est supérieur à la borne inférieure 
    void Class_one::nextprime (mpz_ptr p ,mpz_srcptr rand); 

    // Génère un nombre Q compris entre 0 et max et le stocke dans rand. state initialise le générateur aléatoire. 
    do 
    { 
     mpz_urandomm(nb_aleatoire, state, max); 

    }while((mpz_cmp(nb_aleatoire, min) > 0)|| (mpz_cmp (p , q) == 0)); 
    // Vérifie que rand est supérieur à la borne inférieure 
    void Class_one::nextprime(mpz_ptr q ,mpz_srcptr nb_aleatoire); 

    // clear l'espace utilisé 
    mpz_clear(nb_aleatoire);mpz_clear(rand);mpz_clear(max); 
    mpz_clear(min);mpz_clear(varq);mpz_clear(varp); 

} 

// fonction de chiffrement de message 
void Class_one::chiffre_Msg(mpz_t chiffre, mpz_t message , mpz_t e, mpz_t n) 
{ 
    mpz_t cipher; 
    mpz_t i; 
    mpz_t temp; 

    mpz_init(cipher); 
    mpz_init(i); 
    mpz_init(temp); 
    mpz_set_si(cipher,1); 

    void Class_one::puissance (mpz_t cipher ,mpz_t message,mpz_t e,mpz_t n); 
    mpz_set(chiffre,cipher); 

    mpz_clear(cipher); 
    mpz_clear(temp); 
} 


// fonction dechiffrement de message 
void Class_one:: dechiffre_Msg(mpz_t message2, mpz_t chiffre , mpz_t d, mpz_t n) 
{ 
    mpz_t message; 
    mpz_t i; 
    mpz_t temp; 

    mpz_init(message); 
    mpz_init(i); 
    mpz_init(temp); 
    mpz_set(temp,chiffre); 

    void Class_one::puissance (mpz_t message,mpz_t temp ,mpz_t d,mpz_t n); 
    mpz_set(message2,message); 

    mpz_clear(message); 
    mpz_clear(temp); 
} 

short int Class_one::SetFichiers(string nomFichierDest, string nomFichierSource) 
{ 
    FILE *f1; 
    FILE *f2; 
    f1=fopen(nomFichierSource.c_str(), "rb"); 
    f2=fopen(nomFichierDest.c_str(), "wb"); 

    if(f1==NULL || f2==NULL) 
    { 
     if (f1!=NULL) fclose(f1); 
     if (f2!=NULL) fclose(f2); 
     return -1; 
    } 

    fclose(f1); 
    fclose(f2); 
    this->fichierDest=""+nomFichierDest; 
    this->fichierSource=""+nomFichierSource; 
    return 0; 
} 
mpz_t Class_one::Transcoder(string str)/* 
La méthode Transcoder : Cette méthode prend une chaine de caractères, puis la transforme en un nombre équivalent. Le nombre est égale à la somme du 
code ascii dernier caractère, l’avant dernier multiplié par 256, l’avant avant dernier multiplié par 2562…etc 
*/ 
{ 
    mpz_t Somme; 
    mpz_t var; 
    mpz_t M; 
    mpz_t Mul; 
    mpz_t resultat ; 
    signed long long int i; 
    //initialisation des variables 
    mpz_init(Somme);mpz_init(var); 
    mpz_init(Mul); 
    mpz_init(resultat); 

    //affectation 
    mpz_set_ui(M,1); 


    for(i=(signed long long int)(str.length()-1); i>=0; i--) 
    { 


     aux =(unsigned char)str[(unsigned int)i];//La classe string est composé de signed char 
     void Class_one::puissance(mpz_t resultat ,mpz_t 256 , mpz_t i, mpzt n); 
     mpz_mul(Mul,resultat,aux); 
     mpz_add(Somme,Somme, Mul); 
    } 
    return Somme ; 
    mpz_clear(Somme);mpz_clear(var);mpz_clear(Mul);mpz_clear(resultat); 
} 

string Class_one::DeTranscoder(mpz_t msg) 
/*La méthode DeTranscoder : En prenant un nombre en paramètre, 
elle génère une chaine de caractères équivalente, le nombre va être divisé par 256 en concaténant la chaine 
déjà trouvée et le caractère dont le code ascii est le reste de la division par 256.*/ 

{ 
    mpz_t div; 
    mpz_t aux; 
    mpz_t reste; 
    string str; 
    //initialiser les variables 
    mpz_init(div);mpz_init(aux);mpz_init(reste); 
    // affectation 
    mpz_set(aux,msg); 
    mpz_set_ui(div,256); 
    while(aux.size()>1 || aux!=0) 
    { 
     aux=mpz_div(aux, div, reste); 
     str=(char)reste + str; 
    } 
    return str; 
    //liberer les variables 
    mpz_clear(div); mpz_clear(aux); mpz_clear(reste); 
} 


class Cryptage{ 
    void crypter_RSA(); 
} 

// la fonction principal du rsa en mode Standard 

void Cryptage::crypter_RSA() 
{ 
    // Variable locales 
    mpz_t p , q , e,d , n , phi , message,msg_chiffre,cipher ; 
    int choix ; 

    //initialiser les variables locales 
    mpz_init(msg_chiffre); mpz_init(cipher); 
    mpz_init(e); mpz_init(n); mpz_init(p); 
    mpz_init(q); mpz_init(d); mpz_init(phi); 
    ;mpz_init(message); 

    // initialisationn du generateur 
    gmp_randstate_t state; 
    Class_one::InitialiseRandom(gmp_randstate_t state); 
    Class_one::Genere_nbPremier(mpz_t p,mpz_tq ,mpz_t 512, gmp_randstate_t state); 

    // la valeur de N 
    mpz_mul (n , p , q); 

    // les variablesP et Q 
    gmp_printf ("\n\n \t P \t: \t%Zd \n", p); 
    gmp_printf ("\n\n \t Q \t: \t%Zd \n", q); 

    // Generer la clé public 
    Class_one::Genere_publicKey(mpz_t e, mpz_t p ,mpz_t q , gmp_randstate_t state); 
    gmp_printf("\n\n \t clef pubic : \t%Zd \n",e); 

    // Calculer la valeur de phi 
    mpz_sub_ui(p , p , 1); 
    mpz_sub_ui(q , q , 1); 
    mpz_mul(phi , p , q) ; 

    // genere la cle privee 
    Class_one::Genere_privateKey (mpz_t d ,mpz_t e , mpz_t phi); 
    gmp_printf("\n\n \t clef prive : \t%Zd \n",d); 

    // set fichier 
    short int index= Class_one::SetFichiers(string nomFichierDest, string nomFichierSource); 
    while (index!=0) { 
    index= Class_one::SetFichiers(string nomFichierDest, string nomFichierSource); 
    } 

    // le message a chiffre // le message a chiffre 
    printf("\n\n\n\t Entrez le message a crypter: "); 
    gmp_scanf("%Zd",&message); 

    cout<<"entrer \n 1)crypter\ n2)decrypter "<<endl; 
    cin>>choix; 
    switch(choix) 
    { 
    case 1 : 
    //dechiffrement du message 
      unsigned long long int j,nbZero,m; 
     FILE *f1;   
     FILE *f2; 
     string str; 
     string str2="e"; 
     string str3; 
     mpz_t msg; 
     if(fichierSource.length()<1) break ; 
     f1=fopen(this->fichierSource.c_str(), "rb"); 
     f2=fopen(this->fichierDest.c_str(), "wb"); 
     fseek(f1,0,SEEK_SET); 
     for(j=0,m=1, nbZero=0;j<8;j++,m*=256) nbZero+=fgetc(f1)*m; 
     str2[0]=fgetc(f1); 
     while(str2[0]!=EOF) 
     { 
      str=""+str2; 
      for(j=1;j<this->tailleBloc_; j++) 
      { 
       str2[0]=fgetc(f1); 
       str=str+ str2 ; 
      } 
      str2[0]=fgetc(f1); 

      msg=Class_one::Transcoder(str); 
      Class_one::CrypterDecrypter(mpz_t msg,mpz_t ,mpz_t ,mpz_t); 

      if (str2[0]==EOF) 
      { 
       for(j=0;j<(this->tailleBloc - nbZero); j++) 
        fputc((int)str[j], f2); 
      } 
      else 
       for(j=0;j<this->tailleBloc ; j++) fputc((int)str[j], f2); 
     } 
     fclose(f1); 
     fclose(f2); 

    Class_one::dechiffre_Msg (mpz_t cipher, mpz_t msg_chiffre ,mpz_t d ,mpz_t n); 
    gmp_printf("\n\n\t Le message dechiffre :\t%Zd\n\n",cipher); 
    break ; 

    case 2 : 
    //chiffrement du message 
    mpz_init_set_str(cipher, "1",0); 
    unsigned long long int j,aux; 
      FILE *f1, *f2; 
      unsigned char c; 
      unsigned long long int nbZero ; 
      string str ; 
      string str2="e"; 
      mpz_t msg; 

      if(fichierSource.length()<1) return -1; 
      f1=fopen(this->fichierSource.c_str(), "rb"); 
      f2=fopen(this->fichierDest.c_str(), "wb"); 
      str2[0]=fgetc(f1); 
      if (str2[0]==EOF) break ; 
      fseek(f1, 0, SEEK_END); 
      //fpos_t <==> long long int pour notre compilateur 
      fgetpos(f1,(fpos_t *)&nbZero); 
      nbZero=nbZero%this->tailleBloc; 
      if(nbZero!=0) nbZero=this->tailleBloc - nbZero; 

      aux=nbZero; 
      for(j=0;j<8;j++) 
      { 
       c=aux%256; 
       aux=aux/256; 
       fputc(c,f2); 
      } 

      fseek(f1,0, SEEK_SET); 
      str2[0]=fgetc(f1); 
      while(str2[0]!=EOF) 
      { 
       str=""+str2; 
       for(j=1;j<(this->tailleBloc); j++) 
       { 
        str2[0]=fgetc(f1); 
        str=str+str2 ; 
       } 
       str2[0]=fgetc(f1); 
       if(str2[0]==EOF) 
       { 
        for(j=this->tailleBloc-nbZero; j< this->tailleBloc; j++) 
         str[j]=0; 
       } 
       /*for(j=str.length();j<this->tailleBloc_; j++) 
        str=str2+str;*/ 
       msg=Class_one::Transcoder(str); 
       Class_one::chiffre_Msg(mpz_t msg , mpz_t msg , mpz_t e , mpz_t n); 
       str=Class_one::DeTranscoder(msg); 
       for(j=str.length();j<this->tailleBloc_; j++) 
         fputc((int)0, f2); 
       for(j=0;j<str.length(); j++) 
         fputc((int)str[j], f2); 
      } 
      fclose(f1); 
      fclose(f2); 

    break ; 
    } 
    // liberer les variables locales 
    mpz_clear(p); mpz_clear(q); 
    mpz_clear(e);mpz_clear(phi);mpz_clear(n); 
    mpz_clear(message);mpz_clear(msg_chiffre); 


} 
int main(){ 
    void Cryptage::crypter_RSA(); 


} 
+0

您需要说明您正在使用哪种编译器,以及错误消息的内容。没有这些信息就不会很容易帮忙。 – john

+0

编译器给你什么错误? – Daniel

+2

gmp在Windows上很难设置。你应该使用[MPIR](http://mpir.org/),它是专门为Windows修改的gmp版本。 – john

回答

0

我试图在Windows上安装/构建GMP以及MPIR。非常困难。首先需要编译和构建库

一会儿后,我发现C++大整数库从马特MCCUTCHEN

https://mattmccutchen.net/bigint/

C++源代码只。使用非常简单。在10分钟内整合。

0

GMP不适用于Visual Studio,您应该使用MPIR代替。你不需要改变你的代码,只需要你使用的库。

+0

请提供给我更多信息 – Rahil

+0

@ user914710:您应该查看[MPIR](http://www.mpir.org/)网站。还有法语版的介绍http://tcuvelier.developpez.com/tutoriels/c/mpir/introduction/ – john

+0

1> ------重建所有开始:项目:projet(essai final),配置:Debug Win32 ------ 1>开始建造26/08/2011 22:57:13。 1> _PrepareForClean: 1>删除文件“Debug \ projet(essai final).lastbuildstate”。 1> InitializeBuildStatus: 1>触摸“Debug \ projet(essai final).unsuccessfulbuild”。 (essai final)\ projet(essai final)1>编辑: 1> stdafx.cpp 1> projet(essai final).cpp 1> c:\ users \ sondes \ documents \ visual studio 2010 \ projects \ projet .cpp(10):致命错误C1083:无法打开包含文件:'gmp.h':无此文件或目录 1> 1> Build FAILED。 – Rahil

1

一些建议,即使它不是一个真正的答案......即使对于这样一个小型项目,您也无法像那样工作:您必须一次解决一个问题。

基本上,你试图编写你的整个程序,然后然后只能编译它:你需要编写你的不同功能并单独测试它们,特别是因为你是初学者。

举例来说,如果你想与gmplib编译,写的是这样的:

#include <gmp.h> 

int main() 
{ 
    mpz_t x; 
    return 0; 
} 

尝试编译它,看看会发生什么。如果你有一个编译错误,你可以在这里发布一小段代码:添加编译器的确切消息,这里的人将帮助你,而不是关闭你的问题(再次...)。

这将是第一个问题:与另一个库编译。一旦这个工作,你可以添加一个小块你自己的代码,重新编译它,并测试你到目前为止。

例如,与功能的最小定义添加类声明:不写的执行,只是几乎是空的身体,如:

class OneClass { 
    void pgcd (mpz_t, mpz_t, mpz_t) { /* empty function */ } 
    // etc 
}; 

,你将能够(hopfully,它会很容易)发现你在类声明结束时错过了一个分号,并且你的Transcoder函数返回一个mpz_t,这是非法的,因为mpz_t是一个数组的typedef。

然后,当这个工作时,将你的函数的实现一个接一个地添加,让你在编写它们时测试它们

你会更有效率,因为它会更容易知道你的问题来自。

总之,在你刚刚添加的两行找到一个错误(如果你都知道了是正确的)很容易,但要找到这么大的文件中的所有错误是漫长的,不好受......

编写一段代码,编译它,测试它,然后只写下一个代码:它会付钱!

编辑:实际上,您需要使用库中的一个函数来测试您是否可以正确链接它,但它是相同的想法。

+0

感谢Nicolas :) – Rahil