1

I want to create a function which has a text file as input with a line number and returns the string which represents the line in the number given as argument, in C langage. I've written this function (getLineFromFile) but I think it changes the content of my file, because I tried to use it in one other function but it seems to act weird(in the function (compiled)). these are the codes of my fuction getLineFromFile and the function "compiled", in compiled, when I run it gives me weird caracteres which doesnt represent my line. Can you help me I dont see where is the problem with the function getLineFromFile, I think the function getNumberOfLines has also problems, I want her to return 0 when the file is empty. thank you

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

char* getLineFromFile(FILE *fp, int lineNumber)// si on depasse le nb de lignes, elle renvoie la derniere
{
    char *str;
    int i;
    str = malloc(sizeof(char) * 80);// disons que ca ne depasse pas 80
    for (i = 1 ; i <= lineNumber; i++)
        fgets(str, 80, fp);


    str[strlen(str) - 1] = '\0';

    return str;
}
/// count the number of non empty lines in a file
int count_number_of_lines(FILE *fp) {
    int count = 0;
    char line[256];

    while (fgets(line, sizeof(line), fp) != NULL) {
        if (strlen(line) > 0) {
            count++;
        }
    }

    return count;
}

int compiled(FILE* fp){
   char *line =malloc(sizeof(char)*80);
   int nb_lines=count_number_of_lines(fp);
   printf("number of lines : %d \n", nb_lines);
   for (int j=1;j<=nb_lines;j++){
     line=getLineFromFile(fp,j);
     printf("%s \n",line);
   }
   return 0;
}



int main()
{
    FILE *fichier=fopen("CodeSource.txt","r");
    char *str=malloc(sizeof(char)*80);
    int nb_lines=count_number_of_lines(fichier);
    for (int j=1;j<=nb_lines;j++){
        str=getLineFromFile(fichier,j);
        printf("%s \n",str);
    }
free(str);
    return 0;
}
Kiko
  • 13
  • 3
  • 2
    Aside: You don't need cast the result of ```malloc```. C automatically promotes the ```void *``` to the correct type. – Harith Dec 13 '22 at 16:53
  • The function `getLineFromFile` will only work if all lines are less than `80` characters long (including the newline character). Are you sure that this is the case? – Andreas Wenzel Dec 13 '22 at 16:56
  • the lines of my file are less than 80, I added the content of the main – Kiko Dec 13 '22 at 17:05
  • You're also leaking data in the line `str=getLineFromFile(fichier,j);`. `str` is created by `malloc` but you never call `free`. – Daniel Walker Dec 13 '22 at 17:15

2 Answers2

1

After you call count_number_of_lines, you've read the entire file. So, when you call getLineFromFile, there's nothing left to read because you're at the end of the file. What you need to do is seek to the beginning of the file on every call of getLineFromFile:

char* getLineFromFile(FILE *fp, int lineNumber)
{
    fseek(fp, 0, SEEK_SET);
    ...
}

On a side note, you're counting lines inconsistently between the two functions. In count_number_of_lines, you don't count empty lines. However, in getLineFromFile, you do count them. Even then, strlen will actually be positive even for empty lines because of the newline character(s). So, you're accidentally getting the same line count.

Daniel Walker
  • 6,380
  • 5
  • 22
  • 45
  • and how can I fixe it? I want it to return only the number of non empty lines. – Kiko Dec 13 '22 at 17:30
  • You can check if the first character is anything other than a newline (`'\n'` or `'\r'`) or a null terminator (`'\0'`). – Daniel Walker Dec 13 '22 at 17:32
  • @Kiko: I suggest that you change the line `if (strlen(line) > 0) {` to `if ( strcmp( line, "\n" ) != 0 ) {`. – Andreas Wenzel Dec 13 '22 at 17:34
  • @AndreasWenzel, there could also be a carriage return character. – Daniel Walker Dec 13 '22 at 17:34
  • 1
    @DanielWalker: The file was opened in text mode, not binary mode, so that should generally not be an issue, unless you are for example reading a text file with Windows line endings on a POSIX system. – Andreas Wenzel Dec 13 '22 at 17:36
  • Huh! Today I learned! – Daniel Walker Dec 13 '22 at 17:36
  • 1
    Regarding your (deleted) comment on how `fgets` will treat the last line of the file: That depends on whether the file has a POSIX file ending or not. See [this link](https://stackoverflow.com/questions/729692/why-should-text-files-end-with-a-newline) and [this one](https://unix.stackexchange.com/questions/18743/whats-the-point-in-adding-a-new-line-to-the-end-of-a-file) on whether the last line of the file should contain a newline character. – Andreas Wenzel Dec 13 '22 at 17:46
1

In the function main, you are first calling count_number_of_lines and then getLineFromFile.

The function count_number_of_lines will read the file until it reaches the end of the file. Therefore, when you call getLineFromFile, you will already be at the end of the file. For this reason, getLineFromFile will be unable to find any further data in the file.

In order to get the function getLineFromFile to work, you will have to rewind to the beginning of the file, for example by adding the line

rewind( fp );

to the beginning of the function.

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39