strstr() 函数获取位置

strstr() function get the position

有两个文本,文本a是内容,文本b是逐行列出单词。该程序是获取文本b中单词在内容中的位置。

这是我的程序:

#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。这个等式对吗?如果错了,我怎样才能得到这个位置?如果是对的,为什么我不能正确得到位置?另外,PosStr的部分结果是0.

唯一的问题是 fgets()'\n' 放入缓冲区,从而使 strstr() 也尝试匹配该字符,有多种技术可以删除该字符,一个简单的一个是

strtok(myArr, "\n");

fgets() 之后有效,因为 strtok() 会将 '\n' 替换为 '[=18=]',或

size_t length = strlen(myArr);
myArr[length - 1] = '[=11=]';

我不完全确定我理解这个问题,但我猜测 "query.txt"(它被读入堆栈对象)由多行单词组成(每行不超过 30 个字符) , 就像是 一些单词 再说几句 一行字 而 "hello.txt" 包含一行,即您要搜索的词: 单词 您希望程序产生输出: 6个 11 1个 1个 对于上述输入。

如评论中所述,fgets() 函数将在其读取的缓冲区中包含终止符“\n”。 此外, strstr() 函数接受参数 char *strstr(const char *haystack, const char *needle); 也就是说,第一个参数是大绳子(大海捞针),您要在其中搜索小绳子(针)。它 returns 指向大海捞针的指针。因此,如果我理解你的问题,程序应该变成:

#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;
}

特别是,您正在寻找针中的大海捞针,而针实际上并不是您要找的东西!

我假设该程序旨在检查第一个文件中的每个单词列表,以检查是否出现在第二个文件的单个文本行中,并进行一些调整,它可以工作。

我添加了一些错误检查并从文件输入中删除了尾随 newline。在打印基于 NULL 的值之前,我检查了 strstr() 的结果。我还添加了另一个#define来区分堆栈的大小和测试字符串的长度,并且,我检查堆栈没有溢出。

UPDATE 修改代码以检查整个单词 - 不区分大小写。

#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;
}

文件query.txt:

cat
dog
fox
rabbit

文件hello.txt:

A quick brown fox jumps over the lazy dog

程序输出:

4    fox
9    dog
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