0

The program below describes: read everything in library.txt then put it in a level 2 char pointer, choose ramdomly a word from the pointer then use strlen to print a number of characters in that word. The problem is every number of characters are increase by 2 units. Examples:

helloworld (10 letters) -> 12 letters

abcdef (6 letters) -> 8 letters

uiop (4 letters) -> 6 letters

SUB-QUESTION: can anyone show me the way to return a char pointer from a function? I tried to do like this " char *read (FILE *library) " but on the Internet, they told me not to do that, so i did like the function below =)). please help.

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

int read (FILE *library){

    // count number of word in library.txt
    int n=0;
    char *s=(char *)malloc(256*sizeof(char));
    library=fopen("C:\\Users\\pc\\Desktop\\library.txt","rb");
    while (fgets(s, 256, library)!=NULL)
    {
        n++;
    }
    free(s);

    rewind(library);

    // put all words in library.txt to the level 2 pointer
    char **word=(char**)malloc(n*sizeof(char *));
    for (int i = 0; i < n; i++)
    {
        *(word+i)=(char *)malloc(256*sizeof(char));
        fgets(*(word+i), 256, library);
    }
    fclose(library);

    // choose a rondom word then return it to function
    int j=0;
    srand((int) time(0));
    j=rand()%n;
    return (int)*(word+j);
}

int main(){

    FILE *library;

    int length_word=0;
    length_word=strlen(read(library));
    printf("%s%d",read(library),length_word);

    return 0;
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Becker
  • 147
  • 7
  • 1
    Since you return a random element from the array you allocate, there's a small chance that you could return different elements from each of your calls. But since you call `srand` each time before getting the random number, the likelihood of that happening are small. – Some programmer dude Oct 19 '19 at 11:41
  • 1
    Other points of note: Why do you pass `library` as an argument to the function? You have plenty of resource leaks (you call `malloc` quite a few times in each call, but you never `free` the memory). And in C you [should not cast the result of `malloc`](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). Lastly, for any pointer or array `p` and index `i`, the expression `*(p + i)` is exactly equal to `p[i]`. The latter is usually easier to understand. – Some programmer dude Oct 19 '19 at 11:44
  • 1
    And a last very important point: You return a pointer, but cast it to `int`. On a system where `int` is 32 bits (just about all systems the last few decades) and where pointers are *not* 32 bits (typically any 64-bit system) then that would lead to really big problems and *undefined behavior*. – Some programmer dude Oct 19 '19 at 11:45
  • 1
    Hint: [Removing trailing newline character from fgets() input](https://stackoverflow.com/a/28462221/33499) – wimh Oct 19 '19 at 11:45
  • There's no problem returning a pointer from a function. The problem comes in if the returned pointer contains the address of a variable/array that ceases to existas the function returns, since anything the caller does with that pointer gives undefined behaviour. – Peter Oct 19 '19 at 11:48
  • I use 2 pointers and 1 of them has been free " free(s); " and the second is **word. it exists during the time function works, I think it must be " free " after the function even when I don't " free " it. – Becker Oct 19 '19 at 11:53

1 Answers1

0

For starters the function declaration

int read (FILE *library)

does not make sense because within the function the parameter is overwritten, that is its value is not used.

And instead of the pointer of the type char * the function returns an object of the type int.

Also it is unclear why you are opening the file in the binary mode instead of the text mode.

library=fopen("C:\\Users\\pc\\Desktop\\library.txt","rb");
                                                    ^^^^

Secondly, this return statement

return (int)*(word+j);

does not make sense and results in a memory leak because all allocated memory except the memory pointed to by the the pointer *( word+j ) is not freed.

So before exiting from the function you have to free the allocated memory.

For example

char *p = *( word + j );
for ( int i = 0; i < n; i++ )
{
    if ( i != j ) free( *( word + i ) );
}

free( word );

return p;

Correspondingly the function shall have the return type char *.

In main you two times call the function. And again does not free the memory pointed to by the returned pointer.

length_word=strlen(read(library)); printf("%s%d",read(library),length_word)

Also pay attention to the the function fgets can append the new line character '\n' to the input string. You need to remove it.

It can be done the following way

for (int i = 0; i < n; i++)
{
    *(word+i)=(char *)malloc(256*sizeof(char));
    fgets(*(word+i), 256, library);
    word[i][ strcspn( word[i], "\n" ) ] = '\0';
}

if you are using an old compiler that does not convert carriage return escape character and the new line escape character to the one new line escape character then you can write

    word[i][ strcspn( word[i], "\r\n" ) ] = '\0';

Thus the function should be declared like

char * read( void );

within the function you should declare

FILE *library;

in the function main you should write

char *word = read();

and then

size_t length_word = strlen( word );
printf("%s%zu", word,length_word) ;
free( word );
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • What about an answer to the actual question (there's a trailing CRLF) – ikegami Oct 19 '19 at 12:00
  • @ikegami When a record is read the compiler shall convert crlf to the new line character. And i Showed how to remove it. It is possible that an old compiler is used. – Vlad from Moscow Oct 19 '19 at 12:10
  • Oops, missed that you mentioned the newline, but the fact that you didn't answer the question remains. It probably *is* a CRLF, and reason is they're probably using a Windows file in a unix system (which includes Cygwin and MSYS) – ikegami Oct 19 '19 at 12:15
  • the code in the link has been fixed but it still doesn't work [link](https://ideone.com/ZJ8ycB). please help – Becker Oct 19 '19 at 12:46
  • @Becker Are you sure that the file was opened successfully? Check within the function whether library is equal to NULL after opening the file. – Vlad from Moscow Oct 19 '19 at 12:50
  • @VladfromMoscow the file was opened successfully, I have checked it – Becker Oct 19 '19 at 12:52
  • @Becker And why is the file opened in the binary mode instead of the text mode?! – Vlad from Moscow Oct 19 '19 at 12:56
  • I still can open it normally@VladfromMoscow. but it can be 1 of my fault. tks for your help – Becker Oct 19 '19 at 13:02