как использовать указатели для хранения нескольких строк с помощью malloc - PullRequest
0 голосов
/ 04 января 2019

Я пытался создать программу для динамического выделения памяти для хранения нескольких строк с использованием указателей, но, похоже, она не работает.

#include <stdio.h>
#include<conio.h>

void main()
{
    FILE *fp;
    int num;

    printf("enter no of students");
    scanf("%d",&num);
    char *names = (char*) malloc(num * 100 * sizeof(char));

    printf("enter the names");
    fp = fopen("file.txt","w");

    for (int i = 0; i < num; i++)
    {
        fgets(*(names + i * 100), 100, stdin);
        fprintf(fp, "%s\n", (names + i * 100));
    }

    fclose(fp);

    fp = fopen("file.txt", "r");
    printf("names stored in *ptr");
}

Ответы [ 4 ]

0 голосов
/ 04 января 2019

Самый простой подход - объявить names как "указатель на массив из 100 символов" и использовать только один malloc. После этого вы можете просто получить доступ к индивидуальному имени, используя names[i].

Как это:

char (*names)[100] = malloc(num * sizeof *names);

printf("enter the names\n");
fp = fopen("file.txt","w");

for (int i = 0; i < num; i++)
{
    fgets(names[i], 100, stdin);
    fprintf(fp, "%s", names[i]);
}

fclose(fp);

Несколько дополнительных комментариев:

1) sizeof(char) всегда 1

2) Обратите внимание, что scanf("%d",&num); оставит новую строку во входном буфере. Это приводит к тому, что ваше имя будет пустым. Вам нужно удалить эту новую строку перед сканированием имен

3) Также обратите внимание, что fgets будет содержать символ новой строки (по крайней мере, когда ввод меньше 99 символов).

4) Кажется, вам не нужно хранить все имена в массиве, когда вы немедленно записываете их в файл. Так что вы можете просто сделать:

printf("enter the names\n");
fp = fopen("file.txt","w");

for (int i = 0; i < num; i++)
{
    char name[100];
    fgets(name, 100, stdin);
    fprintf(fp, "%s", name);
}

fclose(fp);
0 голосов
/ 04 января 2019

Я согласен с ответом выше, но если вы хотите сохранить ту же структуру, вы идете

    #include<stdio.h>
    #include<conio.h>
    void main()
    {
    FILE *fp;
    int num;

    printf("enter no of students ");
    scanf("%d",&num);
    char *names=malloc(num*100);


    printf("enter the names\n");
    fp=fopen("file.txt","w");
                fseek(stdin,0,SEEK_END);

    for(int i=0;i<num;i++)
    {

    fgets((names + i * 100), 100, stdin);
    fprintf(fp, "%s", (names + i * 100));
        fseek(stdin,0,SEEK_END);
    }
    fclose(fp);

    fp=fopen("file.txt","r");
    printf("names stored in *ptr");
    fclose(fp);
    }
0 голосов
/ 04 января 2019

У вас есть несколько проблем. Во-первых, scanf не очень хорошо работает с fgets - он оставит новую строку во входном потоке, что означает, что когда вы вызовете fgets, он просто прочитает это. Самый простой способ исправить это - использовать fgets для чтения всей строки при запросе количества студентов и sscanf для получения действительного числа, например:

char temp[100];
fgets(temp,100,stdin);
sscanf(temp,"%d",&num);

Во-вторых, вы создаете только одну действительно большую длинную строку, а не несколько строк. Итак, чтобы создать num строк, вы сначала хотите выделить «массив» строк, подобный этому

names=malloc(sizeof(char *)*num);

, а затем использовать цикл для выделения места для строк

for(int i=0; i<num; i++)
{
     names[i]=malloc(100);
} 

Вы также увидите, что не нужно приводить возвращаемое значение из malloc, но вам нужно включить правильный файл, а именно "stdlib.h". И технически вам не нужно sizeof(char), поскольку это всегда будет 1.

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

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

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

Также технически main должно вернуть int.

Окончательная версия кода может выглядеть так:

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

int main()
{
    FILE *fp;
    int num;
    char temp[100];

    printf("enter no of students");
    fgets(temp,100,stdin);
    sscanf(temp,"%d",&num);
    char **names=malloc(num*sizeof(char*));


    printf("enter the names");
    fp=fopen("file.txt","w");
    if(fp==NULL)
    {
        printf("Failed to open\n");
        return 1;
    }
    for(int i=0;i<num;i++)
    {
        names[i]=malloc(100);
        fgets(names[i],100,stdin);
        fprintf(fp,"%s\n",names[i]);
    }
    fclose(fp);

    for(int i=0;i<num;i++)
    {
        free(names[i]);
    }
    free(names);

    printf("names stored in *ptr");
}
0 голосов
/ 04 января 2019

Вам нужно иметь таблицу указателей на символ.

char **strtable = NULL
size_t nstrings = 0; 

int addstring(const char *str)
{
    int result = -1;
    char **tmp = realloc(strtable, (nstrings + 1)* sizeof(*strtable));

    if(tmp)
    {
        tmp[nstrings] = malloc(strlen(str) + 1);
        if(tmp[nstrings])
        {
            result = 0;
            strtable = tmp;
            strcpy(tmp[nstrings++], str);
        }
    }
    return result;
}

С его помощью вы можете добавлять введенные (читаемые) строки и легко выполнять итерации.

...