Forum Programmation.c++ Trouver la fin d'une ligne après un charactère

Posté par  .
Étiquettes : aucune
2
1
août
2010
bonjour,

savez-vous comment analyser une chaîne en C++ pour déterminer si elle contient un début de ligne avant un charactère, et une fin de ligne après un autre ?

Si je teste avec par exemple :

strcmp(s,"mot")==0

puis plus loin :
strcmp(s,"fin_de_la_fin")==0

ça fonctionne pour détecter ces 2 mots, mais si je veux tester par exemple avec "mot" qui finit une ligne, ça ne fonctionne pas pareil :

strcmp(s,"mot\n")==0
  • # Bizarre

    Posté par  (site web personnel) . Évalué à 2.

    Avez-vous vérifié avec un éditeur hexadécimal que les chaînes de caractères écrites en faisant
    fprintf(fw,"mot\n");
    et en imprimant le tableau de caractères "s" sont bien identiques ?

    « IRAFURORBREVISESTANIMUMREGEQUINISIPARETIMPERAT » — Odes — Horace

  • # Énoncé peu clair

    Posté par  . Évalué à 1.

    D'où vient s ? saisie au clavier via scanf ? Met plus de code.
    • [^] # Re: Énoncé peu clair

      Posté par  . Évalué à 2.

      le texte dans s est le contenu d'un fichier textuel analysé dans scite par exemple, voir réponse plus bas. (Soit en cours d'écriture, soit chargé depuis le disque)

      Only wimps use tape backup: real men just upload their important stuff on megaupload, and let the rest of the world ~~mirror~~ link to it

  • # normal

    Posté par  . Évalué à 2.

    '\n' et '\0', ce n'est pas la même chose
    il faut soit stripper les '\n' à la récupération des données, soit en tenir compte dans les tests.
    J'aurais tendance à préférer la première solution, mais elle pourrait être inadaptée au contexte.
    Pour la seconde approche, un truc comme ça ?:
    strncmp(s, "mot\n", strlen(s));

    maintenant, cf http://linuxfr.org/comments/1149037.html#1149037 , j'ai p-e pas compris la question :)
    • [^] # Re: normal

      Posté par  . Évalué à 2.

      merci pour vos réponses, en fait je n'y connais pas grand chose en programmation de ce type, mais je cherche à adapter un "lexer" pour Scintilla.

      La coloration existe déjà, par contre pour pouvoir permettre au code de se replier en fonction de certains critères, je n'y arrive pas.

      Pour la coloration, ça avait été fait à partir du code du lexer de Markdown, et ça donnait ça : http://scintilla.hg.sourceforge.net/hgweb/scintilla/scintill(...)

      J'ai essayé de suivre un peu le modèle utilisé pour TeX pour le repliage de code, mais là où les marques pour TeX sont nettes (par exemple avec \begin et \end), dans txt2tags c'est plus compliqué, parce que les parties à replier (les entêtes) sont de type :

      == header 1 ==

      texte

      == header 2 ==

      texte

      === sous header ===

      etc

      et donc il n'est pas aisé de savoir où ça commence et où ça s'arrête. J'avais donc pensé faire commencer ça à la fin d'une ligne avec ==\n et l'arrêter en début de ligne avec \n== par exemple, en me basant sur le code de :

      http://scintilla.hg.sourceforge.net/hgweb/scintilla/scintill(...)

      static int classifyFoldPointTeXPaired(const char* s) {
      int lev=0;
      if (!(isdigit(s[0]) || (s[0] == '.'))){
      if (strcmp(s, "begin")==0||strcmp(s,"FoldStart")==0||
      strcmp(s,"abstract")==0||strcmp(s,"unprotect")==0||
      strcmp(s,"title")==0||strncmp(s,"start",5)==0||strncmp(s,"Start",5)==0||
      strcmp(s,"documentclass")==0||strncmp(s,"if",2)==0
      )
      lev=1;
      if (strcmp(s, "end")==0||strcmp(s,"FoldStop")==0||
      strcmp(s,"maketitle")==0||strcmp(s,"protect")==0||
      strncmp(s,"stop",4)==0||strncmp(s,"Stop",4)==0||
      strcmp(s,"fi")==0
      )
      lev=-1;
      }
      return lev;
      }


      Mais si ça fonctionne bien avec n'importe quel symbole ou partie de texte entrée, avec un \n ça bloque l'analyse.

      Only wimps use tape backup: real men just upload their important stuff on megaupload, and let the rest of the world ~~mirror~~ link to it

      • [^] # Re: normal

        Posté par  . Évalué à 3.

        Vérifie que tu as bien des \n dans s car si ils sont enlevés par une lecture ligne par ligne, c'est la position de la chaîne recherchée dans le buffer qu'il faut prendre en compte.
        • [^] # Re: normal

          Posté par  . Évalué à 2.

          c'est sans doute retiré mais je ne sais pas comment vérifier cela. Je posterais sans doute sur la liste de diffusion de scintilla.

          Only wimps use tape backup: real men just upload their important stuff on megaupload, and let the rest of the world ~~mirror~~ link to it

          • [^] # Re: normal

            Posté par  . Évalué à 2.

            Ce sont les fonctions ParseTeXCommand et isWordChar qui ne renvoient des mots (seulement ascii). En fait ce lexer n'est pas adapté à une syntaxe type wiki et c'est toute la logique qu'il faut revoir à partir de FoldTexDoc.
  • # Une possibilité

    Posté par  . Évalué à 1.

    Salut,

    Tu parles de C++ mais tu n'utilises pas std::string ? Voici ce que je peux te proposer :


    void main()
    {

    std::istringstream flux(s);

    while (flux)
    {
    std::string ligne;
    std::getline(flux, ligne);
    if (commencePar(ligne, "motDuDebut")
    {
    // ici la ligne commence par motDuDebut
    if (finitPar(ligne, "motDeLaFin")
    {
    // ici la ligne fini par motDeLaFin et commence par motDuDebut
    }
    }
    }
    }

    bool finitPar(const std::wstring& chaine, const std::wstring& recherche)
    {
    return chaine.substr(chaine.size() - recherche.size() - 1) == recherche;
    }

    bool commencePar(const std::wstring& chaine, const std::wstring& recherche)
    {
    return chaine.substr(0, recherche.size()) == recherche;
    }


    Je n'ai pas vérifié qu'il fonctionnait, mais c'est l'idée.

    Après malheureusement je répond peut-être à côté de la plaque, mais je trouve toujours que ton énoncé n'est pas clair du tout et que tu ne mets pas assez de code.
    • [^] # Re: Une possibilité

      Posté par  . Évalué à 2.

      merci de ta proposition, malheureusement il s'avère que le code actuel (voir http://linuxfr.org/comments/1149075.html#1149075 ) fonctionne si le mot de début et mot de fin sont différents, mais là ce qui délimite c'est le marquage type wiki "==" (ou simplement "=" ou "===") et donc le seul moyen de différenciation c'est de voir s'il y a un retour à la ligne ou pas.

      Only wimps use tape backup: real men just upload their important stuff on megaupload, and let the rest of the world ~~mirror~~ link to it

      • [^] # Re: Une possibilité

        Posté par  . Évalué à 1.

        Dans ma proposition les lignes sont lues une par une (dans la boucle while). Donc si commencePar(ligne, "=") vaut vrai, cela signifie que tu as une ligne qui commence par "=", ce qui implique donc que ta chaine contient un caractère saut de ligne puis immédiatement après un caractère "=". Même chose pour la fonction finitPar.

        Donc :


        std::istringstream flux(s);

        while (flux)
        {
        std::string ligne;
        std::getline(flux, ligne);
        if (commencePar(ligne, "=") && finitPar(ligne, "="))
        {
        // ici la ligne lue commence par "=" et finit par "="
        // comme c'est une ligne, elle est précédé par un saut de ligne (sauf la première)
        // et finit par un saut de ligne (sauf la dernière)
        }
        }


        Désolé pour l'indentation, elle disparait lors de l'envoi.
  • # Avec un fichier venant de windows

    Posté par  . Évalué à 3.

    Tu peux aussi avoir des fins de ligne "\r\n". Je ne suis plus sûr, mais c'est le cas si tu ouvres ton fichier en mode binaire, ou si ton fichier contient des "\r\n" et que tu l'ouvres depuis un système unix/linux.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.