2015-03-18 4 views
0

Il y a deux textes, le texte a est le contenu et le texte b est la liste des mots ligne par ligne. Le programme consiste à obtenir la position des mots du texte b dans le contenu.strstr() fonction obtenir la position

Ceci est mon programme:

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

#define WORDMAXLENGTH 30 
#define MAXLENGTH 200 

int main(){ 
    typedef struct{ 
     char stack[MAXLENGTH][WORDMAXLENGTH]; 
     int top; 
    }stack; 

    stack query; 
    query.top = 0; 
    int i = 0, j = 0,q = 0; 
    char myArr[MAXLENGTH]; 
    char *PosStr = NULL; 
    FILE *inFile = fopen("query.txt","r"); 
    FILE *inFile2 = fopen("hello.txt","r"); 

    while(fgets(query.stack[query.top],WORDMAXLENGTH,inFile) != NULL){ 
     query.top++; 
    } 

    fgets(myArr,MAXLENGTH,inFile2); 

    for(i = 0; i < query.top; i++){ 
     PosStr = strstr(myArr,query.stack[i]);//get the position of s2 (Q1) 
     printf("%d\n", PosStr - myArr + 1); 
    } 

    fclose(inFile); 
    fclose(inFile2); 
    return 0; 
} 

Q1. Cette équation est-elle correcte? Si c'est faux, comment puis-je obtenir le poste? Si c'est juste, pourquoi je ne peux pas obtenir la position correctement? En outre, certains du résultat de POSSTR est 0.

+0

La taille de myArr ne doit pas être MAXLENGTH * WORDMAXLENGTH? – mathiasfk

Répondre

2

Je suppose que le programme est destiné à vérifier chaque liste de mots dans le premier fichier, pour l'occurrence dans la ligne de texte unique du deuxième fichier, et avec quelques réglages, cela fonctionne.

J'ai ajouté une vérification d'erreur et j'ai supprimé le newline à la fin des entrées de fichier. J'ai vérifié le résultat de strstr() avant d'imprimer les valeurs basées sur NULL. J'ai également ajouté un autre #define pour distinguer la taille de la pile de la longueur de la chaîne de test, et, je vérifie que la pile ne déborde pas.

MISE À JOUR révise le code pour vérifier les mots entiers - insensible à la casse.

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

#define WORDMAXLENGTH 30 
#define MAXENTRY 200 
#define MAXLENGTH 200 

typedef struct{ 
    char stack[MAXENTRY][WORDMAXLENGTH]; 
    int top; 
} stack; 

int main(){ 
    FILE *inFile; 
    FILE *inFile2; 
    int i, w; 
    char myArr[MAXLENGTH]; 
    char *sptr; 
    stack query; 
    query.top = 0; 
    inFile = fopen("query.txt","r"); 
    inFile2 = fopen("hello.txt","r"); 
    if (inFile == NULL || inFile2 == NULL) { 
     printf("Cannot open both files\n"); 
     return 1; 
    } 
    while(fgets(query.stack[query.top], WORDMAXLENGTH, inFile) != NULL){ 
     i = strcspn(query.stack[query.top], "\r\n"); 
     query.stack[query.top][i] = 0;  // remove trailing newline etc 
     if (++query.top >= MAXENTRY)  // check stack full 
      break; 
    } 

    fgets(myArr,MAXLENGTH,inFile2); 
    //myArr [ strcspn(myArr, "\r\n") ] = 0; // remove trailing newline etc 
    w = 1;         // word count 
    sptr = strtok(myArr, " \t\r\n");  // removes trailing stuff anyway 
    while (sptr) {       // each word in test string 
     for(i=0; i<query.top; i++) {  // each word in library list 
      if (stricmp(sptr, query.stack[i]) == 0) // without case 
       printf("%-4d %s\n", w, query.stack[i]); 
     } 
     w++; 
     sptr = strtok(NULL, " \t\r\n"); 
    } 

    fclose(inFile); 
    fclose(inFile2); 
    return 0; 
} 

fichier query.txt:

cat 
dog 
fox 
rabbit 

fichier hello.txt:

A quick brown fox jumps over the lazy dog 

sortie du programme:

4 fox 
9 dog 
+0

Y a-t-il un moyen plus rapide de savoir de quel mot il s'agit? par exemple, chien 9, renard 4 – whalesf

+0

Votre programme n'est pas allé jusqu'à extraire des mots entiers de la chaîne 'hello.txt', et je ne suis pas allé plus loin que pour améliorer ce que vous avez fait. Je vous suggère d'examiner 'strtok()' qui peut être utilisé dans une boucle pour extraire des mots de la chaîne de test, que vous pouvez ensuite comparer avec la liste de mots. –

0

Le seul problème est que fgets() met le '\n' dans le tampon, rendant ainsi strstr() essayer de faire correspondre ce caractère aussi, il y a plusieurs techniques pour supprimer ce caractère, un simple on est

strtok(myArr, "\n"); 

juste après l'fgets() cela fonctionne parce que strtok() remplacera le '\n' par un '\0'., ou

size_t length = strlen(myArr); 
myArr[length - 1] = '\0'; 
+1

Je recommande fortement de ne pas utiliser la méthode 'strtok' car cette fonction n'est pas adaptée aux threads et possède un état interne caché. Cela n'a peut-être pas d'importance pour le moment mais commencer à l'utiliser va créer de mauvaises habitudes qui vous hanteront plus tard. –

0

Je ne suis pas entièrement sûr de comprendre la question, mais je devine que "query.txt" (qui est lu dans l'objet stack) est constitué de lignes de mots (pas plus de 30 caractères par ligne), quelque chose comme quelques mots quelques mots plus mots sur une ligne tandis que « hello.txt » contient une seule ligne, le mot que vous recherchez: mot Et vous voulez que le programme pour produire la sortie: pour l'entrée ci-dessus.

Comme mentionné dans les commentaires, la fonction fgets() inclura la fin du '\ n' dans le tampon qu'elle lit. En outre, la fonction strstr() prend des arguments char * strstr (const char * haystack, const char * needle); Autrement dit, le premier argument est la grande chaîne (la botte de foin) dans laquelle vous recherchez une petite chaîne (l'aiguille). Il renvoie un pointeur dans la botte de foin pour savoir où trouver l'aiguille. Par conséquent, si je comprends bien votre question, le programme devrait devenir:

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

#define WORDMAXLENGTH 30 
#define MAXLENGTH 200 
int 
main() 
{ 
    typedef struct { 
     char stack[MAXLENGTH][WORDMAXLENGTH]; 
     int top; 
    } stack; 
    stack query; 

    query.top = 0; 
    int i = 0, j = 0, q = 0; 

    char myArr[MAXLENGTH]; 
    char *PosStr = NULL; 
    FILE *inFile = fopen("query.txt", "r"); 
    FILE *inFile2 = fopen("hello.txt", "r"); 

    while (fgets(query.stack[query.top], WORDMAXLENGTH, inFile) != NULL) { 
     query.top++; 
    } 

    fgets(myArr, MAXLENGTH, inFile2); 
     myArr[strlen(myArr)-1] = 0; 

    for (i = 0; i < query.top; i++) { 
     PosStr = strstr(query.stack[i], myArr); //get the position of s2 (Q1) 

     printf("%d\n", PosStr -query.stack[i] + 1); 
    } 

    fclose(inFile); 
    fclose(inFile2); 
    return 0; 
} 

En particulier, vous recherchez une botte de foin dans une aiguille, et l'aiguille était pas vraiment ce que vous recherchez!

0
Note: comments beginning with '// --' are reasons for following code changes 

#include<stdio.h> 
#include<stdlib.h> // exit(), EXIT_FAILURE 
#include<string.h> 

// --wrap #define number in parens 
// --vertical alignment make the code easier to read 
// --vertical spacing makes the code easier to read 
#define WORDMAXLENGTH (30) 
#define MAXLENGTH  (200) 

// --place data type definitions outside of any function 
// --in modern C, for struct definitions just declare the struct 
// --and don't clutter the code with typedef's for struct definitions 
struct stack 
{ 
    char stack[MAXLENGTH][WORDMAXLENGTH]; 
    int top; 
}; 

// --place large data struct in file global memory, not on stack 
// contains search keys and number of search keys 
static struct stack query; 

// --using Georgian formatting for braces makes the code harder to read 
// --indent code blocks within braces for readabillity 
int main() 
{ 
    query.top = 0; 
    // --while legal C, multiple variable declarations on same line 
    // --leads to maintenance problems and reduces readability 
    int i = 0; 
    // -- eliminate unused variables 
    //int j = 0; 
    //int q = 0; 
    char myArr[MAXLENGTH]; // line to search 
    char *PosStr = NULL; // ptr to where search key found 

    // --always check the returned value from fopen to assure operation successful 
    // --always place the literal on the left in comparisons 
    // -- so compiler can catch errors like using '=' rather than '==' 
    FILE *inFile = fopen("query.txt","r"); 
    if(NULL == inFile) 
    { // then fopen failed 
     perror("fopen for query.txt for read failed"); 
     exit(EXIT_FAILURE); 
    } 

    // implied else, fopen successful 

    FILE *inFile2 = fopen("hello.txt","r"); 
    if(NULL == inFile2) 
    { // then, fopen failed 
     perror("fopen for hello.txt for read failed"); 
     fclose(inFile); // cleanup 
     exit(EXIT_FAILURE); 
    } 

    // implied else, fopen successful 

    // --the following while loop can 
    // -overflow the available space in the struct 
    // --leading to undefined behaviour and can/will lead to a seg fault event 
    // --comment the code so reverse engineering is not needed 
    // note: each search key in the struct field: stack[] will be terminated with '\n' 
    //  so eliminate them 
    // read in complete file. line-by-line to struct 
    // while tracking number of lines 
    while(fgets(query.stack[query.top],WORDMAXLENGTH,inFile)) 
    { 
     query.top++; 
     strtok(myArr, "\n"); // replace newline with NUL char 
    } // end while 

    // --always check returned value from fgets 
    // --to assure the operation was successful 
    // read line to search 
    if(NULL == fgets(myArr,MAXLENGTH,inFile2)) 
    { // then fgets failed 
     perror("fgets for hello.txt file failed"); 
     exit(EXIT_FAILURE); 
    } 

    // implied else, fgets successful 

    for(i = 0; i < query.top; i++) 
    { 
     // --strstr will return NULL if search string not found 
     // --always check returned value from strstr (!=NULL) to assure successful operation 
     PosStr = strstr(myArr,query.stack[i]);//get the position of s2 (Q1) 

     if(PosStr) 
     { // then at least one instance of current search key found in line 
      // --difference between two pointer is a 'long int', not an 'int' 
      // display offset into line 
      printf("%ld\n", PosStr - myArr + 1); 
     } // end if 
    } // end for 

    fclose(inFile); 
    fclose(inFile2); 
    return 0; 
} // end function: main