none
coder une union RRS feed

  • Question

  • J'ai une variable qui doit être  "null" au premier appel et recevoir un numérique au second appel. J'ai donc utilisé une union mais ca ne compile pas. Comment faire?

    Jean Noël Martin

    vendredi 6 juin 2014 16:43

Réponses

Toutes les réponses

  • WHAT!, quel rapport avec une union ?

    Pourquoi cette valeur n'est-elle pas passée en paramètre de la fonction ?

    Pourquoi ne pas utiliser une static de fonction ? (avec des threadguard)

    ...

    Mais bon, la présentation du problème semble montrer un problème de conception plus qu'autre chose. Même pas d'indication sur le scope de la variable etc...


    Paul Bacelar, Ex - MVP VC++

    vendredi 6 juin 2014 17:50
    Modérateur
  • Dans l'union les variables sont déclarées static

    je dois passer la valeur à une fonction et quand je code NULL la valeur passée est 0


    Jean Noël Martin

    vendredi 6 juin 2014 20:13
  • Je ne comprends toujours pas ce que vous tentez de faire.

    NULL est une MACRO C qui à une valeur égale à 0 dans quasiment tous les systèmes.

    Que cherchez-vous à faire réellement ?


    Paul Bacelar, Ex - MVP VC++

    jeudi 12 juin 2014 00:34
    Modérateur
  • J'ai constaté que SQL Server 2012 voyait différemment la chaine "null" et la valeur 0.

    J'ai besoin, quand la valeur est 0 de passer la chaine "null" et dans les autres cas de passer la valeur


    Jean Noël Martin

    jeudi 12 juin 2014 07:55
  • Bonjour,

    Effectivement SQL Server, mais également toutes les autres bases de données, ne considèrent pas null et zéro de la même façon. Null signifie "il n'y a aucune valeur  de renseignée" alors que zéro correspond à "il y a une valeur, elle vaut zéro".

    Le null et le zéro ne sont donc sémantiquement pas pareils. Comme le précise Paul, NULL est une macro ; le problème de C++ étant  d'avoir  amalgamer null avec un entier. Voici ce que Stroustrup, l'inventeur du C++, dit lui même (http://www.stroustrup.com/bs_faq2.html#null) : 

    Should I use NULL or 0?

    In C++, the definition of NULL is 0, so there is only an aesthetic difference. I prefer to avoid macros, so I use 0. Another problem with NULL is that people sometimes mistakenly believe that it is different from 0 and/or not an integer. In pre-standard code, NULL was/is sometimes defined to something unsuitable and therefore had/has to be avoided. That's less common these days.

    If you have to name the null pointer, call it nullptr; that's what it's called in C++11. Then, "nullptr" will be a keyword.

    Ainsi dans d'autres langages, on s'est débarrassé du problème. En Java, C#, VB.NET, null et zéro n'ont absolument rien à voir. C++ 11 amène une nouveauté pour combler cette lacune, on se doit d'utiliser nullptr... Mais null pourra toujours se convertir en zéro !

    Dans votre cas de figure, vous pouvez vous  comporter avec la base de données comme on le ferait d'en d'autres langages. Regardez par exemple comment C#, gère le concept d'entier qui peut être "nullable" (http://msdn.microsoft.com/fr-fr/library/1t3y8s4s.aspx). Regardez maintenant comment la notion de null avec la base de donnée est gérée en .NET (http://msdn.microsoft.com/fr-fr/library/system.dbnull.value(v=vs.110).aspx


    Vous voyez, vous êtes contraint de gérer l'entier d'un côté, et le principe de null de l'autre ; il n'y a pas d'astuces. Soit vous configurez la colonne de votre table est interdisant les null avec un syntaxe du genre (ici  le null est interdit, la valeur par défaut est zéro)

    ALTER TABLE ma_table
      MODIFY ma_colonne int NOT NULL DEFAULT 0;

    Soit vous gérer dans votre code un troisième état. Vous pouvez faire comme en .NET (le type nullable est un generic, c'est à dire l'équivalent d'un template C++), ou bien joué avec une variable supplémentaire du genre is_initialized, etc, etc.

    Bien cordialement,

    Fabrice JEAN-FRANCOIS


    jeudi 12 juin 2014 08:43
  • Merci Fabrice pour cette réponse argumentée.

    Jean-Noël, je pense que vous avez mal interprété l'utilisation d'une API.

    Pouvez-vous nous donnez le bout de code qui vous pose problème ?


    Paul Bacelar, Ex - MVP VC++

    jeudi 12 juin 2014 18:08
    Modérateur
  • Merci

    J'ai donc codé

    static hidDB hidPrevSegment;
    erc CMDBManager::CreateSegmentAndAllItsSubelement(CAnalysedSegment * pAnalysedSegment)
    {
    //DATA
    //	hidPrevSegment		Identifier of the previous segment of the segment to create
    //	hidNewSegmentID		Identifier of the segment to create
    //	hidNewLayout			Identifier of the layout of the segment to create
    //	hidNewClues				Identifier of the clues of the segment to create
    	System::DBNull^ dbnull;
        hidDB hidNewSegmentID = 0;
        hidDB hidNewLayout = 0;
        hidDB hidNewClues = 0;
        std::wstringstream wssRequest;
        std::wstringstream wssPreviousRequest;
        unsigned long dwNbResultFound = 0;
        std::list<CAnalysedWord *>::iterator itWord;
        std::list<CAnalysedChunk *>::iterator itChunk;
        std::list<CElementSemantique *>::iterator itProposition;
        std::wstring wsText;
        CAnalysedWord * pWord;
        CAnalysedChunk * pChunk;
        CElementSemantique * pProposition;
    	enStatusDocument enDocumentType = STATUS_DOC_SOURCE;
    	
    //ATAD
    //DO
    //	ErrorCode := 0
       hidDB ErrorCode = 0;
       // il faut d'abord vérifier que ce segment n'est pas déjà dans la base de donnée
       // on va publier le segment pour tracabilité
       wsText = L"";
       itProposition = pAnalysedSegment->pLinguisticSegment->ListProposition.begin();
       while( itProposition != pAnalysedSegment->pLinguisticSegment->ListProposition.end())
       {
          pProposition = *itProposition;
          itChunk = pProposition->ListChunk.begin();
          while( itChunk != pProposition->ListChunk.end())
          {
             pChunk = *itChunk;
             itWord = pChunk->ListWord.begin();
             while( itWord != pChunk->ListWord.end())
             {
                pWord = *itWord++;
                wsText += pWord->wsWord;
                wsText += L" ";
             }
             itChunk++;
          }
          itProposition++;
       }
    //	[Create the Clues of the segment to create] =
    //	DO
    //		ErrorCode:=[call the method "CreateSegmentClues(pSegmentCluesDescription of pAnalysedSegment, hidNewClues)"]
    //	[Create the Layout of the segment to create] =
    //	DO
    //		ErrorCode:=[call the method "CreateSegmentLayout(pSegmentLayout of pAnalysedSegment, hidNewLayout)"]
       // Layout
       // ErrorCode |= CreateSegmentLayout(pAnalysedSegment->pSegmentLayout,hidNewLayout);
    //	[Search the previous segment of the segment to create] =
    //	DO
    //		IF (this is the first segment (ulDocPosition = 1)) THEN
    //			hidPrevSegment := NULL
    //		ELSE
    //			[Select "nuIdSeg" from T_SEGMENT where "iInitPos" = "ulDocPosition - 1" and  "siIdLang" = Language]
    //			[Update "hidPrevSegment" with the result of the request]
    //
    //		FI
       if( pAnalysedSegment->ulDocPosition > 10000)
    	   pAnalysedSegment->ulDocPosition = 1;
       
          wssPreviousRequest << hidPrevSegment;
          wssRequest.str(L"");
          wssRequest <<   SELECT <<
                                SEG_INIT_POS << CO << SEG_SIZE_IN_CHAR<< CO << SEG_ID_SEG <<
                            FROM <<
                                SEG_TABLE <<
                            WHERE <<
                                SEG_INIT_POS << EQ << (pAnalysedSegment->ulDocPosition) << AND <<
                                SEG_TYPE_DOC << EQ << enDocumentType << AND <<
                                SEG_ID_DOC << EQ << iIdDoc << AND <<
                                SEG_ID_LANG << EQ << pAnalysedSegment->Language;
          dwNbResultFound = 0;
          try
    	  {
    		CInterbaseManagerM::ExecuteSelectRequest(wssRequest.str(), &dwNbResultFound);
    		while( CInterbaseManagerM::myReader->Read())
    		{
    			dwNbResultFound++;
    			hidPrevSegment = CInterbaseManagerM::GetInteger( 2);
    		}
    	  }
    	  catch(...)
    	  {
    		  hidNewSegmentID++;
    	  }
    	  CInterbaseManagerM::CloseReader();
          CInterbaseManagerM::CommitTransaction();
       
    //	OD
    //
    //	[Create the new segment] =
    //	DO
    //		[Get the new identifier "hidNewSegmentID"of "nuIdSeg"]
       
       //		[Insert into the table T_SEGMENT with "nuIdSeg"="hidNewSegmentID", "cAlignStatus"=SEG_AL_ST_NOALIGNED, "iInitPos"="ulDocPosition",
    //		"sSizeInChar"="shSegmentCharLength", "sSizeInWords"="shSegmentWordLength","nuIdPrev"="hidPrevSegment",
    //		"nuIdLayout"="hidNewLayout","nuIdClues"="hidNewClues","siIdLang"="Language"]
       if( dwNbResultFound != 1)
       {
    		try
    		{
    			hidNewSegmentID = CInterbaseManagerM::GetIdentifier( SEG_TABLE, SEG_INIT_POS, SEG_ID_SEG);
    		}
    		catch(...)
    		{
    			hidNewSegmentID++;
    		}
    		if( hidPrevSegment == 0)
    			hidPrevSegment = gcnew DBNull( dbnull);
    		wssRequest.str(L"");
    		wssRequest <<   INSERT <<
                              SEG_TABLE << BLANK <<
                              PB  << SEG_ALIGN_STATUS << CO << SEG_INIT_POS << CO <<
                              SEG_SIZE_IN_CHAR << CO << SEG_SIZE_IN_WORDS << CO << SEG_ID_PREV << CO <<
                              SEG_ID_LAYOUT << CO << SEG_ID_DOC << CO << SEG_TYPE_DOC << CO << SEG_ID_LANG << PE <<
                          VALUES <<
                              PB << SEG_AL_ST_NOALIGNED << CO << pAnalysedSegment->ulDocPosition << CO <<
                              pAnalysedSegment->shSegmentCharLength << CO << pAnalysedSegment->shSegmentWordLength << CO << wssPreviousRequest.str() << CO <<
                              hidNewLayout << CO << iIdDoc << CO << enDocumentType << CO << pAnalysedSegment->Language << PE;
    		try
    		{
    			CInterbaseManagerM::ExecuteRequest(wssRequest.str(), &dwNbResultFound);
    			CInterbaseManagerM::CommitTransaction();
    		}
    		catch(...)
    		{
    			hidNewSegmentID++;
    		}
       }
       CInterbaseManagerM::CloseInsertion( SEG_TABLE);
    //		[Update "ullSegmentID" of pAnalysedSegment with "hidNewSegmentID"]
       pAnalysedSegment->ullSegmentID = hidNewSegmentID;
    //
       itProposition = pAnalysedSegment->pLinguisticSegment->ListProposition.begin();
       while( itProposition != pAnalysedSegment->pLinguisticSegment->ListProposition.end())
       {
          pProposition = *itProposition;
          itChunk = pProposition->ListChunk.begin();
          while( itChunk != pProposition->ListChunk.end())
          {
             pChunk = *itChunk;
             //	[Create the Lemmas of the segment to create] =
             //	DO
             //		ErrorCode:=[call the method "CreateSegmentLemmas(Language,ListWord of pLinguisticSegment of pAnalysedSegment)"]
             ErrorCode |= CreateSegmentLemmas(pAnalysedSegment->Language, pChunk->ListWord);
             //	OD
             //
             //	[Create the Words of the segment to create] =
             //	DO
             //		ErrorCode:=[call the method "CreateSegmentWords(Language,hidNewSegmentID, ListWord of pLinguisticSegment of pAnalysedSegment)"]
             ErrorCode |= CreateSegmentWords(pAnalysedSegment->Language,hidNewSegmentID,pChunk->ListWord);
             itChunk++;
          }
          //	[Create the Chunks of the segment to create] =
          //	DO
          //		ErrorCode:=[call the method "CreateSegmentChunks(Language,hidNewSegmentID, ListChunk of pLinguisticSegment of pAnalysedSegment)"]
          ErrorCode |= CreateSegmentChunks(pAnalysedSegment->Language,hidNewSegmentID,pProposition->ListChunk);
          //	OD
          //
          itProposition++;
       }
    //	OD
    //	[Create the Propositions of the segment to create] =
    //	DO
    //		ErrorCode:=[call the method "CreateSegmentNGrams(Language,hidNewSegmentID, ListProposition of pLinguisticSegment of pAnalysedSegment)"]
        ErrorCode |= CreateSegmentProposition(pAnalysedSegment->Language,hidNewSegmentID,pAnalysedSegment->pLinguisticSegment->ListProposition);
    //	OD
        hidPrevSegment = hidNewSegmentID;
    //  IF (an error occured) THEN
    //    [Return "ErrorCode" with the error occured]
    //  FI
    //	[Return ErrorCode]
       return( ErrorCode);
    //OD
    }
    Mais ça ne passe pas à la compilation


    Jean Noël Martin


    • Marqué comme réponse JeanNoel53 vendredi 13 juin 2014 07:24
    • Non marqué comme réponse Paul BacelarModerator vendredi 13 juin 2014 09:16
    • Marqué comme réponse JeanNoel53 vendredi 13 juin 2014 10:43
    • Non marqué comme réponse JeanNoel53 vendredi 13 juin 2014 10:43
    • Modifié JeanNoel53 vendredi 13 juin 2014 10:44
    vendredi 13 juin 2014 07:23
  • Mais c'est où dans tout ce code ?

    Votre code est très perfectible.

    Vous vous compliquez la vie, utilisez des requêtes paramétrées, cela gère correctement les DBNull et les problèmes d'SQLinjection.

    http://msdn.microsoft.com/en-us/library/yy6y35y8(v=vs.110).aspx


    Paul Bacelar, Ex - MVP VC++

    lundi 16 juin 2014 08:55
    Modérateur
  • Je comprend le sens de votre apport, mais j'ai besoin d'information sur les requêtes paramétrées

    Jean Noël Martin

    lundi 16 juin 2014 18:27
  • Suivez le lien dans mon précédant post.

    Paul Bacelar, Ex - MVP VC++

    lundi 16 juin 2014 23:21
    Modérateur
  • Je suis sur le lien et je ne voie qu'un lointain rapport avec mon pb

    Jean Noël Martin

    mercredi 18 juin 2014 19:00
  • Il est lointain car vous devez faire beaucoup de chemin.

    Vous ne pourrez pas gérer correctement tous les cas possibles lors de la génération des requêtes juste en les bricolant avec des opérations sur des flux de chaine de caractères :

    Remplacez ce machin :

    <MACHIN>

    wssRequest <<   SELECT <<
                                SEG_INIT_POS
    << CO << SEG_SIZE_IN_CHAR<< CO << SEG_ID_SEG <<
                            FROM
    <<
                                SEG_TABLE
    <<
                            WHERE
    <<
                                SEG_INIT_POS
    << EQ << (pAnalysedSegment->ulDocPosition) << AND <<
                                SEG_TYPE_DOC
    << EQ << enDocumentType << AND <<
                                SEG_ID_DOC
    << EQ << iIdDoc << AND <<
                                SEG_ID_LANG
    << EQ << pAnalysedSegment->Language;

    </MACHIN>

    par

    SqlCommand ^ cmdDatabase = gcnew SqlCommand(L"SELECT SEG_INIT_POS, SEG_SIZE_IN_CHAR, SEG_ID_SEG FROM SEG_TABLE WHERE SEG_INIT_POS = @SegInitPos AND SEG_TYPE_DOC = @TypeDoc AND SEG_ID_DOC = @idDoc AND SEG_ID_LANG = @IdLang;", conDatabase);
    
    cmdDatabase->Parameters->Add(L"@SegInitPos", SqlDbType::Int);
    cmdDatabase->Parameters["@SegInitPos"]->Value = pAnalysedSegment->ulDocPosition;
    
    cmdDatabase->Parameters->Add(L"@TypeDoc", SqlDbType::Int);
    cmdDatabase->Parameters["@TypeDoc"]->Value = enDocumentType;

    Vous n'avez pas à gérer Null ou pas, l'escaping des chaines de caractères etc...

    Paul Bacelar, Ex - MVP VC++

    jeudi 19 juin 2014 00:28
    Modérateur
  • Ça vient; Je crois que ca va résoudre de  nombreux problème Mais pour finir:

    Je dois déclarer conDatabase. De quel type s'agit il?

    D'autre part j'ai un typage de la base de donnée qui ne passe pas le type sqlCommand    ne convient pas pour ExecuteRequest:

    J'ai donc modifié le code de cette primitive et je retombe sur la déclaration de ConDatabase.

    Je me demande si ce n'est pas myDatatbase qu'il faut mettre?

    mon code est devenu

            int TypeDoc = enDocumentType;
    	SqlCommand ^ cmdDatabase = gcnew SqlCommand(L"SELECT SEG_INIT_POS, SEG_SIZE_IN_CHAR, SEG_ID_SEG FROM SEG_TABLE WHERE SEG_INIT_POS = @SegInitPos AND SEG_TYPE_DOC = @TypeDoc AND SEG_ID_DOC = @idDoc AND SEG_ID_LANG = @IdLang;", conDatabase);
            cmdDatabase->Parameters->Add(L"@SegInitPos", SqlDbType::Int);
            cmdDatabase->Parameters["@SegInitPos"]->Value = pAnalysedSegment->ulDocPosition;
            cmdDatabase->Parameters->Add(L"@TypeDoc", SqlDbType::Int);
            cmdDatabase->Parameters["@TypeDoc"]->Value = TypeDoc;
    	try
    	{
    			CInterbaseManagerM::ExecuteRequest( cmdDatabase, &dwNbResultFound);
    			CInterbaseManagerM::CommitTransaction();
    	}
    	catch(...)
    	{
    			hidNewSegmentID++;
    	}


    Jean Noël Martin





    jeudi 19 juin 2014 03:19
  • Comme indiqué dans la documentation de SqlCommand :

    http://msdn.microsoft.com/fr-fr/library/system.data.sqlclient.sqlcommand(v=vs.110).aspx

    Il n'est pas nécessaire d'indiquer sur quel connexion exécuter cette commande, au moment de sa création.

    Mais au moment de son exécution, il faut qu'une SqlConnection lui soit associé:

    http://msdn.microsoft.com/fr-fr/library/system.data.sqlclient.sqlconnection(v=vs.110).aspx

    C'est vous qui voyez quand faire cette association.

    Attention, ces classes sont spécifique à SQL Server, si vous utilisez une autre base, il faut utiliser les classes équivalente pour l'autre classe, ou utiliser les version SGBD agnostique http://msdn.microsoft.com/fr-fr/library/System.Data.Common(v=vs.110).aspx


    Paul Bacelar, Ex - MVP VC++

    jeudi 19 juin 2014 15:27
    Modérateur
  • J’implémente tout cela et je reviens donner le résultat.

    Jean Noël Martin

    • Marqué comme réponse JeanNoel53 vendredi 20 juin 2014 12:29
    jeudi 19 juin 2014 18:27