Kakashi Flor
Kakashi Flor

Reputation: 1

Finding a string in a file using the lseek command in C

I have a file storing data of students in the following order:

id (space) name (space) address

Below is the content of the file:

10 john manchester

11 sam springfield

12 samuel glasgow

Each data is stored in a newline.

I want to search the student with id 10 and display his/her details using the lseek command, however I'm not to complete the task. Any help is appreciated.

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

void main() {

char line[50] = "";

char id[2] = "";

ssize_t fd = open("file.dat", O_RDONLY);

while(read(fd,line,sizeof(line))>0){

if (id[0] == '1' && id[1] == '0'){
    printf("%s\n",line);
}
lseek(fd, 1 ,SEEK_CUR);
}
close(fd);

Upvotes: 0

Views: 970

Answers (2)

Luis Colorado
Luis Colorado

Reputation: 12668

Your file has a first line that has 18 characters, a second line with the same number of characters, and a third one with one less (17) number of characters.

In case you have a four line in which the name for example makes the number of characters different, they should be appended to the file without any other structure.

Lines are delimited by \n characters, that can appear at any point, so second line starts as soon as just behind the first appearance of the \n char.

For this reason, you don't know the precise position where each line begins, and so you cannot know the exact position where each line begins, as the position of each line is (n + 1) bytes forward from twhere the previous line started, where n is the number of characters you put in the previous line, plus one (for the new line character).

You need an index, which is a file that allows you to get, on a fixed length record, to store the starting positions of each line in the data file. In this way, to read line i, you access the index at position (record_index_size * i), and get the position of the starting point of line i. Then you go to the data file, and position your file pointer to the value obtained from the las calculation, and read that with, for example fgets(3).

To build the index, you need to call ftell() right before each call to fgets(), because the call to fgets() will move the pointer, and so the position obtained will not be correct. Try to write the position in a fixed length format, e.g. binary form, with:

    write(ix_fd, position, sizeof position);

so the position of line i, can be calculated by reading from index at position i * sizeof position.

Upvotes: 0

Use the right tools for the task. Hammer for nails, Screwdriver for screws.

lseek is not the right tool here, since lseek is for repositioning the file offset (which you do not have yet, you are looking for a specific position, when found, then you don't have a need for repositioning the file offset, since you are already there).

Ask yourself,

What is your task:

  • search for a specific id
  • print the line if match

What do you have:

  • a dataset (textfile) with a fixed format (id <space> name <space> address <newline>)

Your dataset is separated by a newline, and the id is the first field of that row. The keywords here are 'newline' and 'first field'.

The right procedure here would be:

  • read a whole line (fgets)
  • compare the first field (start of line) with the desired id (strcmp)

Example:

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

int main() {
    //return value of main
    int ret = EXIT_FAILURE;

    //open filestream in read mode
    FILE *f = fopen("file.dat", "r");

    //string buffer
    #define MAX_LEN 50
    const char line[MAX_LEN];
    char field[MAX_LEN];

    //the id to search for
    const char *id = "10";

    //for each line
    while (fgets(line, MAX_LEN, f)) {
        //extract the first field ('%s' matches a sequence of non-white-space characters)
        sscanf(line, "%s", field);
        //compare the field with the desired id
        if (strcmp(field, id) == 0) {
            //if found print line
            printf("%s", str);
            //set result to success
            ret = EXIT_SUCCESS;
            //and exit
            break;
        }
    }

    //cleanup
    fclose(f);

    //return the result
    return ret;
}

Upvotes: 1

Related Questions