web-dev-qa-db-fra.com

Comment extraire une sous-chaîne d'une chaîne en C?

J'ai essayé d'utiliser strncmp mais cela ne fonctionne que si je lui donne un nombre d'octets spécifique que je veux extraire.

char line[256] = This "is" an example. //I want to extract "is"
char line[256] = This is "also" an example. // I want to extract "also"
char line[256] = This is the final "example".  // I want to extract "example"
char substring[256]

Comment pourrais-je extraire tous les éléments entre le ""? et le mettre dans la sous-chaîne variable?

6
juice

Remarque: J'ai modifié cette réponse après avoir réalisé que le code, tel qu'écrit, poserait un problème, car strtok n'aime pas utiliser les variables const char*. C'était plus un artefact de la façon dont j'ai écrit l'exemple qu'un problème avec le principe sous-jacent - mais apparemment, il méritait un double vote négatif. Alors je l'ai réparé.

Les travaux suivants (testés sous Mac OS 10.7 avec gcc):

#include <stdio.h>
#include <string.h>

int main(void) {
const char* lineConst = "This \"is\" an example"; // the "input string"
char line[256];  // where we will put a copy of the input
char *subString; // the "result"

strcpy(line, lineConst);

subString = strtok(line,"\""); // find the first double quote
subString=strtok(NULL,"\"");   // find the second double quote

printf("the thing in between quotes is '%s'\n", subString);
}

Voici comment cela fonctionne: strtok recherche des "délimiteurs" (deuxième argument) - dans ce cas, le premier ". En interne, il sait "jusqu'où il est allé", et si vous l'appelez à nouveau avec NULL comme premier argument (au lieu d'un char*), il recommencera à partir de là. Ainsi, lors du deuxième appel, il renvoie "exactement la chaîne entre le premier et le deuxième guillemet double". C'est ce que tu voulais.

Avertissement: strtok remplace généralement les délimiteurs par '\0' car il "mange" l'entrée. Vous devez donc compter sur la modification de votre chaîne d’entrée par cette approche. Si cela n’est pas acceptable, vous devez d’abord faire une copie locale. En gros, je le fais dans ce qui précède lorsque je copie la constante de chaîne dans une variable. Ce serait plus propre de le faire avec un appel à line=malloc(strlen(lineConst)+1); et ensuite à free(line); - mais si vous avez l'intention d'envelopper cela dans une fonction, vous devez considérer que la valeur de retour doit rester valide après le retour de la fonction ... Parce que strtok renvoie un pointeur au bon endroit dans la chaîne, il ne fait pas une copie du jeton. Passer un pointeur sur l'espace où vous voulez que le résultat se termine et créer cet espace à l'intérieur de la fonction (avec la taille correcte), puis y copier le résultat serait la bonne chose à faire. Tout cela est assez subtil. Faites-moi savoir si ce n'est pas clair!

7
Floris

Voici un long chemin à faire: Supposer que la chaîne à extraire sera entre guillemets (Correction du contrôle d'erreur suggéré par kieth dans les commentaires ci-dessous)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(){

    char input[100];
    char extract[100];
    int i=0,j=0,k=0,endFlag=0;

    printf("Input string: ");
    fgets(input,sizeof(input),stdin);
    input[strlen(input)-1] = '\0';

    for(i=0;i<strlen(input);i++){
        if(input[i] == '"'){

                j =i+1;
                while(input[j]!='"'){
                     if(input[j] == '\0'){
                         endFlag++;
                         break;
                     }
                     extract[k] = input[j];
                     k++;
                     j++;
                }
        }
    }
    extract[k] = '\0';

    if(endFlag==1){
        printf("1.Your code only had one quotation mark.\n");
        printf("2.So the code extracted everything after that quotation mark\n");
        printf("3.To make sure buffer overflow doesn't happen in this case:\n");
        printf("4.Modify the extract buffer size to be the same as input buffer size\n");

        printf("\nextracted string: %s\n",extract);
    }else{ 
       printf("Extract = %s\n",extract);
    }

    return 0;
}

Sortie (1):

$ ./test
Input string: extract "this" from this string
Extract = this

Sortie (2):

$ ./test
Input string: Another example to extract "this gibberish" from this string
Extract = this gibberish

Sortie (3) :( Vérification d'erreur suggérée par Kieth)

$ ./test

Input string: are you "happy now Kieth ?
1.Your code only had one quotation mark.
2.So the code extracted everything after that quotation mark
3.To make sure buffer overflow doesn't happen in this case:
4.Modify the extract buffer size to be the same as input buffer size

extracted string: happy now Kieth ?

---------------------------------------------------- -------------------------------------------------- ------------------------------

Bien que cela ne soit pas demandé - Le code suivant extrait plusieurs mots de la chaîne d'entrée tant qu'ils sont entre guillemets:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(){

    char input[100];
    char extract[50];
    int i=0,j=0,k=0,endFlag=0;

    printf("Input string: ");
    fgets(input,sizeof(input),stdin);
    input[strlen(input)-1] = '\0';

    for(i=0;i<strlen(input);i++){
        if(input[i] == '"'){
            if(endFlag==0){
                j =i+1;
                while(input[j]!='"'){
                     extract[k] = input[j];
                     k++;
                     j++;
                }
                endFlag = 1;
            }else{
               endFlag =0;
            }

            //break;
        }
    }

    extract[k] = '\0';

    printf("Extract = %s\n",extract);

    return 0;
}

Sortie:

$ ./test
Input string: extract "multiple" words "from" this "string"
Extract = multiplefromstring
0
sukhvir

Avez-vous essayé de regarder la fonction strchr? Vous devriez pouvoir appeler cette fonction deux fois pour obtenir des pointeurs sur les première et deuxième instances du caractère " et utiliser une combinaison de memcpy et de l'arithmétique de pointeur pour obtenir ce que vous voulez.

0
godel9
#include <string.h>
...        
substring[0] = '\0';
const char *start = strchr(line, '"') + 1;
strncat(substring, start, strcspn(start, "\""));

Limites et vérification des erreurs omises. Évitez strtok car cela aurait des effets secondaires.

0
fizzer

si vous voulez le faire sans support de bibliothèque ...

void extract_between_quotes(char* s, char* dest)
{
   int in_quotes = 0;
   *dest = 0;
   while(*s != 0)
   {
      if(in_quotes)
      {
         if(*s == '"') return;
         dest[0]=*s;
         dest[1]=0;
         dest++;
      }
      else if(*s == '"') in_quotes=1;
      s++;
   }
}

alors appelez-le

extract_between_quotes(line, substring);

0
Keith Nicholas