Реализация grep в c с использованием системных вызовов

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include <sys/types.h> 
#include <sys/stat.h>
#include <unistd.h>
#include<string.h>
#include <fcntl.h>

void match_pattern(char *argv[])
{
    int fd,r,j=0;
    char temp,line[100];
    if((fd=open(argv[2],O_RDONLY)) != -1)
    {
        while((r=read(fd,&temp,sizeof(char)))!= 0)
        {
            if(temp!='\n')
            {
                line[j]=temp;
                j++;
            }
            else
            {
                if(strstr(line,argv[1])!=NULL)
                    printf("%s\n",line);
                memset(line,0,sizeof(line));
                j=0;
            }

        }
    }   
}

main(int argc,char *argv[])
{
    struct stat stt;
    if(argc==3)
    {
        if(stat(argv[2],&stt)==0)
            match_pattern(argv);
        else 
        {
            perror("stat()");
            exit(1);
        }
    }
}

Содержимое файла:

arunds ghh
sdf
hi
hello dude
am arun

Мой вывод:

./mygrep arun file
arunds ghh
am arun

Я получаю правильный вывод

Содержимое файла:

arun arundfdf arun
arunds ghh
sdf

Мой вывод:

./mygrep arun file
arun arundfdf arun �5
arunds ghh

Я понятия не имею, почему печатаются некоторые нежелательные символы.


person Community    schedule 05.02.2013    source источник
comment
Если вас интересует производительность, прочитайте в буфер, а затем получите из буфера посимвольно. Накладные расходы на read() действительно довольно велики. В общем, переопределите stdio getchar.   -  person hyde    schedule 05.02.2013


Ответы (2)


Вы никогда не завершаете буфер line нулем, поэтому он переполнится после окончания. Выполните вызов memset также после того, как вы объявили переменную line.

person Bart Friederichs    schedule 05.02.2013
comment
Большое спасибо!! Я добавил строку [j]='\0' выше if(strstr(line,argv[1])!=NULL) - person ; 05.02.2013

Вам нужно завершить нулем line, но почему вы читаете его по одному символу за раз? вы можете читать целые строки с помощью fgets(), что приведет к нулевому завершению буфера для вас:

while (fgets(line, sizeof(line), file)) {
   if (strstr(line, argv[1])) {
    ...
   }
}

Также это гарантирует, что вы не переполните 100-байтовый буфер, который вы выделяете.

person iabdalkader    schedule 05.02.2013
comment
@BartFriederichs, да, это еще одна проблема. - person iabdalkader; 05.02.2013
comment
на самом деле мне нужно использовать только системные вызовы - person ; 05.02.2013
comment
@user1958241 user1958241 это не системные вызовы, это функции из стандартной библиотеки C, даже read() - это функция :) в любом случае, по крайней мере, убедитесь, что вы не читаете более 99 байтов - person iabdalkader; 05.02.2013
comment
Насколько я знаю, fgets() — это функция, и она находится в стандарте C, но read() — это системный вызов unix. - person ; 05.02.2013
comment
@user1958241 user1958241 read() - это просто оболочка, которая вызывает ядро ​​​​и передает прочитанный номер системного вызова и аргументы, я уверен, что ваше задание не требует использования реальных системных вызовов. см. это, если вы хотите понять разницу. stackoverflow.com/questions/2668747/ - person iabdalkader; 05.02.2013