Мне не удалось использовать stren с указателем - PullRequest
0 голосов
/ 19 октября 2019

Программа ниже описывает: прочитайте все в файле library.txt, затем поместите его в указатель символа уровня 2, выберите случайное слово из указателя, затем используйте strlen для печати количества символов в этом слове. Проблема в том, что каждое количество символов увеличивается на 2 единицы. Примеры:

helloworld (10 букв) -> 12 букв

abcdef (6 букв) -> 8 букв

uiop (4 буквы) -> 6 букв

ВОПРОС: кто-нибудь может показать мне способ вернуть указатель на символ из функции? Я пытался сделать это "char * read (FILE * library)", но в Интернете мне сказали, чтобы я этого не делал, поэтому мне понравилась функция ниже =)). пожалуйста, помогите.

#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;
}

1 Ответ

0 голосов
/ 19 октября 2019

Для начала объявление функции

int read (FILE *library)

не имеет смысла, так как внутри функции параметр перезаписывается, то есть его значение не используется.

И вместо указателятипа char * функция возвращает объект типа int.

Также неясно, почему вы открываете файл в двоичном режиме вместо текстового режима.

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

Во-вторых, этот оператор возврата

return (int)*(word+j);

не имеет смысла и приводит к утечке памяти, поскольку вся выделенная память, кроме памяти, на которую указывает указатель * (слово + j), не освобождается.

Поэтому перед выходом из функции необходимо освободить выделенную память.

Например,

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

free( word );

return p;

Соответственно, функция должна иметь тип возврата char *.

В основном вы два раза вызываете функцию. И снова не освобождает память, на которую указывает возвращенный указатель.

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

Также обратите внимание на то, что функция fgets может добавлять символ новой строки '\ n' во входную строку. Вам нужно удалить его.

Это можно сделать следующим образом

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';
}

, если вы используете старый компилятор, который не преобразует escape-символ возврата каретки и escape-символ новой строки водна новая строка, после которой вы можете написать

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

Таким образом, функция должна быть объявлена ​​как

char * read( void );

внутри функции, которую вы должны объявить

FILE *library;

в функции main вы должны написать

char *word = read();

, а затем

size_t length_word = strlen( word );
printf("%s%zu", word,length_word) ;
free( word );
...