Raghad
Raghad

Reputation: 53

Reading files using system calls and printing lines

This program reads a text file "hello.txt" and looks for the occurrence of the string w in it and prints the number of the line and the whole line. It also prints how many times the string w has occurred in the file. The program compiles with no errors, here is the code:

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

int main() {

    int fd;
    char c;
    char str[152];
    int i = 0, j = 0;
    int bytesread;
    int flag = 1;
    int found = 0;
    int line = 1;
    int foundflag = 1;

    char w[] = {'h', 'e', 'l', 'l', 'o'};
    int len = strlen(w);

    if ((fd = open("hello.txt", O_RDONLY, 0)) != -1) { //if 1

        bytesread = read(fd, &c, 1);
        str[j] = c;
        j++;

        if (bytesread != -1) { //if 2

            while (bytesread != 0) { //while

                if (c == '\n')
                    line++;

                if (c == w[i]) { //if 3
                    i++;
                    flag = 0;
                } else if (flag == 0 || i == len) //end of f3
                { // else 3
                    i = 0;
                    flag = 1;
                }// end of else 3
                else if (flag == 1) {
                    while (read(fd, &c, 1)) {
                        str[j] = c;
                        j++;
                        if (c == ' ')
                            break;
                        if (c == '\n') {
                            line++;
                            break;
                        }
                    }
                }

                bytesread = read(fd, &c, 1);
                str[j] = c;
                j++;

                if ((c == ' ' || c == '\n') && flag == 0 && i == len) {
                    found++;
                    foundflag = 0;
                    printf("w was found in line %d.\n", line);
                }

                if ((c == '\n')&&(foundflag == 0)) {

                    for (j = 0; str[j] != '\n'; j += 5) {
                        printf("%c", str[j]);

                        if (str[j + 1] != '\n')
                            printf("%c", str[j + 1]);
                        else {
                            j++;
                            break;
                        }

                        if (str[j + 2] != '\n')
                            printf("%c", str[j + 2]);
                        else {
                            j += 2;
                            break;
                        }

                        if (str[j + 3] != '\n')
                            printf("%c", str[j + 3]);
                        else {
                            j += 3;
                            break;
                        }

                        if (str[j + 4] != '\n')
                            printf("%c", str[j + 4]);
                        else {
                            j += 4;
                            break;
                        }
                    }

                    for (; str[j] != '\n'; j++)
                        printf("%c", str[j]);

                    printf("\n");
                    j = 0;

                } else if (c == '\n')
                    foundflag = 1;

            } //end of while
            printf("w has occured %d times.\n", found);

        } else //end of if 2
            printf("couldn't read file.\n");

    } else //end of if 1
        printf("Couldn't open file for read.\n");

    close(fd);
} //end of main

This is the output in the terminal:

w was found in line 1.
hello
w was found in line 2.
w was found in line 6.
hello world
hellooooo
w has occured 3 times.

and here is the content of "hello.txt":

hello
hello world
hallo
I'm here
we're here
hello
hellooooo

the number of lines printed in the output are 1,2 & 6, but this is what the output should look like:

w was found in line 1.
hello
w was found in line 2.
hello world
w was found in line 6.
hello
w has occured 3 times.

Upvotes: 0

Views: 14125

Answers (1)

Enzo Ferber
Enzo Ferber

Reputation: 3094

  1. I suggest you read some C material. You code suggests you don't know much about the language yet.
  2. I won't change your code, since that'd be hard.
  3. I'll post the relevant parts of my code and explain the bits.

So, the code bits:

const char fname[] = "hello.txt";
const char w[] = "hello";

(...)    

while (read(fd, &buffer[i], 1) == 1) {
    /* end of line */
    if (buffer[i] == '\n' || buffer[i] == 0x0) {
        buffer[i] = 0;
        if (!strncmp(buffer, w, strlen(w))) {
            printf("w was found in line %d\n", line);
            puts(buffer);
            n++;
        }
        line++;
        i = 0;
        continue;
    }
    i++;
}

Explanation

  1. while (read(fd, &buffer[i], 1) == 1): This will read one character from your fd (which was returned by an earlier open call) and store that at buffer[i]. The relevant thing to note here is that before this you should have declared int i = 0 and make sure buffer is either a defined array or a malloced memory region. This while will go on until the amount of bytes read is different than 1 (which was what we asked for).

  2. if (buffer[i] == '\n' || buffer[i] == 0x0): This if detects an end of line. Pretty straight-forward.

  3. buffer[i] = 0; and if (!strncmp(buffer, w, strlen(w))): buffer[i] = 0 will set the last character of the current buffer to zero. What this does is it gets rid of the last \n we read, so we can print it nicely with puts. The bit I suggested in the comments is the use of strncmp. This function is just like strcmp, but it will only compare at most a defined number of bytes. So, with this function, you can effectively determine if a string starts with the substring you're looking for. If this string is found, we print the line in which it is, print the buffer itself and increment n, which is our counter on how many times w was found. You should have declared int n = 0; in the beginning of the code...

  4. line++; i = 0; continue; :This is inside the end-of-line detection if. So, what this does is it increments our line counter, sets i to zero - this is important, because at a new line we're gonna read a new buffer, and that buffer index must start at 0. And continue forces a loop repetition without executing the rest of the code.

  5. Finally, the rest of the while scope is defined as i++. As our while loop executes at every character, the buffer index must get incremented after every character read.


The file I tested with is the one you provided. The output I got was:

w was found in line 1
hello
w was found in line 2
hello world
w was found in line 6
hello
w was found 3 times

Upvotes: 4

Related Questions