strstr()函数获取位置

时间:2015-03-18 13:20:49

标签: c file position strstr

有两个文本,文本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。

4 个答案:

答案 0 :(得分:2)

我认为该程序旨在检查第一个文件中的每个单词列表,以便在第二个文件的单个文本行中出现,并且通过一些调整,它可以正常工作。

我添加了一些错误检查,并从文件输入中删除了尾随的newline。在根据strstr()打印值之前,我检查了NULL的结果。我还添加了另一个#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

答案 1 :(得分:0)

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

strtok(myArr, "\n");

fgets()工作之后,因为strtok()会将'\n'替换为'\0'。或

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

答案 2 :(得分:0)

我不完全确定我理解这个问题,但我猜测“query.txt”(它被读入堆栈对象)由单词行组成(每行不超过30个字符),喜欢     一些单词     更多的话     在一条线上的文字 而“hello.txt”包含一行,您要搜索的单词:     字 你希望程序产生输出:     6     11     1     1 对于上述输入。

正如评论中所提到的,fgets()函数将在它读取的缓冲区中包含终止'\ n'。 此外,strstr()函数接受参数     char * strstr(const char * haystack,const char * needle); 也就是说,第一个参数是你要搜索一个小字符串(针)的大字符串(haystack)。它返回一个指向大海捞针的指针,找到针的位置。因此,如果我理解你的问题,程序应该成为:

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

特别是,你正在寻找针头中的干草堆,针头实际上并不是你想要的!

答案 3 :(得分: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