0

My code is read a string in line from file and print it and its length on screen. But the length is incorrect (bigger than 1).

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

int main() {

    FILE * file;
    file= fopen("data.txt","r");
    char* singleLine;
    singleLine = (char *) malloc(150* sizeof(char *));

    if(file){
        while(!feof(file)){
            fgets(singleLine,150, file);
            puts(singleLine);
            printf("length: %ld\n",strlen(singleLine));
        }
    }
    fclose(file);

    return 0;
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 2
    could you add the content of the file to your question as well. Also post the output if possible. – Ghos3t Jun 22 '18 at 08:34
  • Side note: `fclose(file);` should be within the `if` clause. And it's `sizeof(char)` instead of `sizeof(char *)`. – Jabberwocky Jun 22 '18 at 08:37
  • 5
    [Why is “while ( !feof (file) )” always wrong?](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) – Paul Jun 22 '18 at 08:37
  • 2
    `strlen()` returns a `size_t`, so you should use the `%zu` format specifier. – Ilja Everilä Jun 22 '18 at 08:45
  • 2
    `singleLine = (char *) malloc(150* sizeof(char *))` you are allocating 150 *pointers* here. – joop Jun 22 '18 at 08:47
  • data.txt look like cat dog human etc... – Đặng Trung Jun 22 '18 at 08:54
  • @ĐặngTrung please [edit] your question and show the data.txt file _there_. In comments it doesn't make much sense as you cannot put newlines in comments – Jabberwocky Jun 22 '18 at 10:15
  • Do you mean "bigger than 1" or "bigger _by_ 1"? If it is bigger by 1, then the extra byte is the newline that `fgets()` keeps. If you mean bigger than 1, then if there's more than a newline on the line, you'll get a length that's bigger than 1. – Jonathan Leffler Jun 22 '18 at 15:50

2 Answers2

0

fgets(char *s, int size, FILE *stream) reads in at most size-1 characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A '\0' is stored after the last character in the buffer.

If the length of a line is less than 149 bytes, and it is not the end of file, then the newline will be read to the buf. Thus the return value of strlen will include the newline.

Plus: If your just need 150 characters buffer, instead of malloc(150* sizeof(char *)), malloc(sizeof(char) * 150) might be more reasonable.

There is no need to cast the result of malloc. For detail please go this question Do I cast the result of malloc?

Paul
  • 1,630
  • 1
  • 16
  • 23
0

You can get rid of the newline character that results in the extra length in the following manner:

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

int main()
{
    char* singleLine;

    FILE * file = fopen("data.txt","r");

    singleLine = (char *) malloc(150* sizeof(char));

    if(file)
    {
        char *p = NULL;

        while(fgets(singleLine, 150, file) != NULL) //giving the length here directly as 150 is important, because using sizeof() or strlen() only reads the 1st 3 characters(which is the size of char * on my platform) of the string.
        {
            p = strstr(singleLine,"\n");

            if(p)
            {
                *p = '\0';
            }
            printf("%s\n", singleLine);

            printf("length: %ld\n",strlen(singleLine));
        }
        if (feof(file))
        {
            fclose(file);   
        }
        else
        {
            printf("some other error occured");
        }
    }
    else
    {
        printf("inside else\n");
    }

    return 0;
}
Ghos3t
  • 174
  • 1
  • 14
  • Since `p` points to the newline, you can use `if (p != NULL) *p = '\0';` without needing to use `strlen()`. And [`while (!feof(file))` is always wrong](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong). – Jonathan Leffler Jun 22 '18 at 15:51
  • `while (fgets(singleLine, 150, file) != 0)` (replaces loop condition and line after it). You should normally test the result of the actual I/O operation — `fgets()`, `getchar()`, `scanf()`, whatever. Also, it is often effective to use `singleLine[strcspn(singleLine, "\n")] = '\0';` to eliminate the newline. – Jonathan Leffler Jun 25 '18 at 04:10