Чтение различных значений из файла в C и печать в зависимости от условий - PullRequest
0 голосов
/ 16 марта 2019

Я хочу прочитать различные значения, которые хранятся в файле на C, используя одномерные массивы. в тексте есть разные типы данных и много записей. каждая запись отделяется пустым пробелом, и запись содержит name, palate Number, логическое значение type 1 или 0, cost и date. структура файла выглядит следующим образом:

Hanif Hefaz
BA123HB
0
100.50
20180101

Jacki Shroff
UP673MK
1
3000.99
20170512

. . .

Проблема в том, что я хочу прочитать каждую запись из файла и распечатать names и palate Numbers только тех, чей date больше одного года. если так, то я хочу проверить type на этот раз. если type равно 1, тогда я хочу напечатать новое значение, скажем amount вместе с name и palate Number для этой записи таким образом, что cost умножается на 1.5 а если type равно 0, то cost следует умножить на 2.5.

, чтобы описать это в краткой форме:

read file
check if the date in the record is more than 1 year from now
if yes
check type
if type = 1
amount = cost * 1.5
else
if type = 0
amount = cost * 2.5
print name, palate Number, amount

В настоящее время я могу распечатать все записи в файле. но как реализовать эти условия?

Это мой код:

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

void FileRead(FILE *pr)
{
    fseek(pr, 0,0);
    while(1)
    {
    char name[100];
    if(fgets(name,100,pr) == NULL)
    {
        break;
    }
    printf("Name: : %s", name);
    char palateNumber [20];
    fgets(palateNumber,20,pr);
    printf("spz: %s", palateNumber);
    char type [2];
    fgets(type,20,pr);
    printf("type: %s", type);
    char cost [10];
    fgets(cost,10,pr);
    printf("cena: %s", cost);
    char date [15];
    fgets(date,15,pr);
    printf("date : %s", datum);
    fgets(name, 50, pr);
    printf("%s", name);
    }

}


int main()
{

   char x;
   FILE *pr;
   pr=fopen("file.txt","r");
   if(pr==NULL)
   {
       printf("File can not be opened.");
       return 0;
   }

  while(scanf("%c", &x))
    {
        switch(x)
        {

        case 'v' :
            FileRead(pr);
        break;

        }
    }
fclose(pr);
    return 0;
}

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

time_t fill_broken_down_time (int y, int m, int d)
{                   /* initialize struct members */
    struct tm bdt = { .tm_sec=0, .tm_min=0, .tm_hour=0, .tm_mday=d,
                    .tm_mon=m>0?m-1:0, .tm_year=y-1900, .tm_isdst=-1 };

    return mktime(&bdt);    /* return mktime conversion to time_t */
}
        while (fgets (buf, MAXC, pr)) {     // read each line.

        if (sscanf (buf, "%4d%2d%2d", &y, &m, &d) != 3) {
            continue;
        }
        time_t  now = time(NULL),
        then = fill_broken_down_time (y, m, d);
        double secs = difftime (now, then);
        printf ("%g\n",secs / 86400.0);
        }

1 Ответ

0 голосов
/ 16 марта 2019

Хорошо, я получил ваш комментарий, но давайте попробуем массив struct , чтобы сделать вашу обработку данных управляемой. Это не тривиальное дополнение к вашему последнему вопросу. Попытка согласовать 5 отдельных массивов (3 из которых были бы двумерными символьными массивами) создает больше проблем, чем стоит. struct - это правильный способ координировать различные типы информации как одну единицу. Кроме того, если у вас нет постоянной необходимости использовать bool, просто используйте int. Компилятор может обрабатывать собственный тип int так же эффективно.

Давайте начнем с вашей структуры. struct - это не более чем удобная оболочка, позволяющая собирать разные типы и обрабатывать их как один объект. В вашем случае ваши строки символов name, plate, date, ваши int type и ваши double value (ваши amount) могут быть членами struct. Вы можете использовать typedef для структуры, чтобы сделать ее использование более удобным, поэтому вместо написания struct nameofstruct везде вы можете просто использовать typedeffed nameofstruct, как если бы вы использовали обычный тип, такой как int. Например:

#define MAXS   16u  /* max number of structs */
#define MAXNM  32u  /* max characters in name and other arrays in struct */
#define MAXC 1024u  /* max characters in read buffer */
#define SECPY 31536000u /* seconds per-year */

typedef struct mydata {
    char name[MAXNM],
        plate[MAXNM],
        date[MAXNM];
    int type;
    double value;
} mydata_t;

Создайте struct mydata с typedef из mydata_t, который является ссылкой (псевдонимом) на struct mydata (вы можете опустить mydata и просто ввести определение анонимной структуры).

Теперь вы можете создать массив struct mydata или просто mydata_t, и каждый элемент массива является структурой, которая может содержать каждое из этих значений.

Теперь давайте начнем с вашей проблемы. Как упоминалось выше, просто объявите массив mydata_t вместо 5 отдельных массивов, например,

int main (int argc, char **argv) {
    ...
    int n = 0, ndx = 0; /* NOTE when dealing with array, start at ZERO */
    ...
    mydata_t data[MAXS] = {{ .name = "" }};

Теперь у вас есть массив 16 struct для работы (отрегулируйте свою константу, определяя размер массива по мере необходимости), и у вас есть 2 счетчика n, чтобы отслеживать, какой элемент в вашей структуре вы сейчас читаете, и ndx индекс структуры в массиве, который вы заполняете.

Используя их, вы можете прочитать каждую строку, как в своем последнем вопросе, и использовать n, чтобы определить, что делать со строкой (вы можете использовать isspace(), чтобы проверить, является ли первый символ белой строкой (включая '\n'). ), чтобы пропустить пустые строки. Затем просто передайте n на switch(n), чтобы выполнить соответствующее действие для этой строки (или использовать набор if ... else if ... else if ...) Например:

   while (fgets (buf, MAXC, fp)) {     /* read each line in file */
        if (isspace(*buf))  /* skip blank lines (or start with space) */
            continue;
        buf[strcspn (buf, "\r\n")] = 0; /* trim '\n' from end of buf */
        /* if line isn't a date line, just output line as non-date line */
        switch (n) {
            case 0: /* fill the name in struct */
            case 1: /* fill the plate in struct */
            case 2: /* set the type in struct */
            ...

( примечание: buf[strcspn (buf, "\r\n")] = 0; - это просто удобный способ обрезки '\n' (или \r\n) от конца буфера до его копирования в name, plate, date и т. Д. )

В каждом из ваших случаев вы просто ВАЛИДИРУЕТЕ, что строка, прочитанная с помощью fgets, поместится в строковый член вашей структуры, прежде чем скопировать его, или вы преобразуете строку в нужное вам числовое значение, например:

            case 0: 
                if (strlen (buf) < MAXNM)
                    strcpy (data[ndx].name, buf);
                else {
                    fputs ("error: name exceeds storage.\n", stderr);
                    exit (EXIT_FAILURE);
                }
                n++;   /* advance n counter to act on next member */
                break;

или

            case 2:
                if (sscanf (buf, "%d", &data[ndx].type) != 1) {
                    fputs ("error: type not an integer.\n", stderr);
                    exit (EXIT_FAILURE);
                }
                n++;
                break;

(Вы используете оператор '.' (точка) для доступа к каждому члену структуры при работе с самой структурой, или вы используете оператор '->' (стрелка), если у вас есть указатель на struct. Когда у вас есть массив stuct, индекс массива ([..]) действует как разыменование. Точно так же, как массив чего-либо еще)

Так как вы не сохраняете year, month, day, вам просто нужна функция, которая проверяет время с этого момента, чтобы вы могли проверить, прошло ли оно больше года. Таким образом, вы просто передаете свою дату в функцию и получаете время в секундах назад как double, например,

 double check_time_from_now (const char *str)
{
    int y, m, d;

    if (sscanf (str, "%4d%2d%2d", &y, &m, &d) != 3) {
        fprintf (stderr, "error non-date string: '%s'.\n", str);
        exit (EXIT_FAILURE);
    }

    time_t  now = time(NULL),
            then = fill_broken_down_time (y, m, d);
    double secs = difftime (now, then); /* get seconds between dates */

    return secs;
}

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

void prn_data_t_array (mydata_t *data, int n)
{
    for (int i = 0; i < n; i++)
        printf ("%-12s %-8s  %d  %9.2f %s\n", data[i].name, data[i].plate,
                data[i].type, data[i].value, data[i].date);
}

С этим мы можем взглянуть на остаток вашего switch(n), который показывает, как обрабатывать каждый случай:

    while (fgets (buf, MAXC, fp)) {     /* read each line in file */
        if (isspace(*buf))  /* skip blank lines (or start with space) */
            continue;
        buf[strcspn (buf, "\r\n")] = 0; /* trim '\n' from end of buf */
        /* if line isn't a date line, just output line as non-date line */
        switch (n) {
            case 0: 
                if (strlen (buf) < MAXNM)
                    strcpy (data[ndx].name, buf);
                else {
                    fputs ("error: name exceeds storage.\n", stderr);
                    exit (EXIT_FAILURE);
                }
                n++;
                break;
            case 1:
                if (strlen (buf) < MAXNM)
                    strcpy (data[ndx].plate, buf);
                else {
                    fputs ("error: plate exceeds storage.\n", stderr);
                    exit (EXIT_FAILURE);
                }
                n++;
                break;
            case 2:
                if (sscanf (buf, "%d", &data[ndx].type) != 1) {
                    fputs ("error: type not an integer.\n", stderr);
                    exit (EXIT_FAILURE);
                }
                n++;
                break;
            case 3:
                if (sscanf (buf, "%lf", &data[ndx].value) != 1) {
                    fputs ("error: value not a double.\n", stderr);
                    exit (EXIT_FAILURE);
                }
                n++;
                break;
            case 4: 
                if (strlen (buf) < MAXNM)
                    strcpy (data[ndx].date, buf);
                else {
                    fputs ("error: date exceeds storage.\n", stderr);
                    exit (EXIT_FAILURE);
                }
                if (check_time_from_now (data[ndx].date) > SECPY) {
                    if (data[ndx].type)
                        data[ndx].value *= 1.5;
                    else
                        data[ndx].value *= 2.5;
                }
                n = 0;
                ndx++;
                if (ndx == MAXS)
                    goto arrayfull;
                break;
            default:
                fputs ("error: you shouldn't get here!\n", stderr);
                break;
        }
    }

( примечание: присмотритесь к case 4: и тому, как счетчик строк n сбрасывается в ноль и как увеличивается индекс вашего массива ndx, чтобы вы затем заполняли следующую структуру в своем массиве Также note вы защищаете границы массива, проверяя if (ndx == MAXS), чтобы убедиться, что вы не пишете больше структур, чем в массиве.)

Если сложить все вместе, вы получите:

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

#define MAXS   16u  /* max number of structs */
#define MAXNM  32u  /* max characters in name and other arrays in struct */
#define MAXC 1024u  /* max characters in read buffer */
#define SECPY 31536000u /* seconds per-year */

typedef struct {
    char name[MAXNM],
        plate[MAXNM],
        date[MAXNM];
    int type;
    double value;
} mydata_t;

time_t fill_broken_down_time (int y, int m, int d)
{                   /* initialize struct members */
    struct tm bdt = { .tm_sec=0, .tm_min=0, .tm_hour=0, .tm_mday=d, 
                    .tm_mon=m>0?m-1:0, .tm_year=y-1900, .tm_isdst=-1 };

    return mktime(&bdt);    /* return mktime conversion to time_t */
}

double check_time_from_now (const char *str)
{
    int y, m, d;

    if (sscanf (str, "%4d%2d%2d", &y, &m, &d) != 3) {
        fprintf (stderr, "error non-date string: '%s'.\n", str);
        exit (EXIT_FAILURE);
    }

    time_t  now = time(NULL),
            then = fill_broken_down_time (y, m, d);
    double secs = difftime (now, then); /* get seconds between dates */

    return secs;
}

void prn_data_t_array (mydata_t *data, int n)
{
    for (int i = 0; i < n; i++)
        printf ("%-12s %-8s  %d  %9.2f %s\n", data[i].name, data[i].plate,
                data[i].type, data[i].value, data[i].date);
}

int main (int argc, char **argv) {
    /* use filename provided as 1st argument (stdin by default) */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
    int n = 0, ndx = 0; /* NOTE when dealing with array, start at ZERO */
    char buf[MAXC];     /* buffer to hold each line read from file */
    mydata_t data[MAXS] = {{ .name = "" }};

    if (!fp) {  /* validate file open for reading */
        perror ("file open failed");
        return 1;
    }

    while (fgets (buf, MAXC, fp)) {     /* read each line in file */
        if (isspace(*buf))  /* skip blank lines (or start with space) */
            continue;
        buf[strcspn (buf, "\r\n")] = 0; /* trim '\n' from end of buf */
        /* if line isn't a date line, just output line as non-date line */
        switch (n) {
            case 0: 
                if (strlen (buf) < MAXNM)
                    strcpy (data[ndx].name, buf);
                else {
                    fputs ("error: name exceeds storage.\n", stderr);
                    exit (EXIT_FAILURE);
                }
                n++;
                break;
            case 1:
                if (strlen (buf) < MAXNM)
                    strcpy (data[ndx].plate, buf);
                else {
                    fputs ("error: plate exceeds storage.\n", stderr);
                    exit (EXIT_FAILURE);
                }
                n++;
                break;
            case 2:
                if (sscanf (buf, "%d", &data[ndx].type) != 1) {
                    fputs ("error: type not an integer.\n", stderr);
                    exit (EXIT_FAILURE);
                }
                n++;
                break;
            case 3:
                if (sscanf (buf, "%lf", &data[ndx].value) != 1) {
                    fputs ("error: value not a double.\n", stderr);
                    exit (EXIT_FAILURE);
                }
                n++;
                break;
            case 4: 
                if (strlen (buf) < MAXNM)
                    strcpy (data[ndx].date, buf);
                else {
                    fputs ("error: date exceeds storage.\n", stderr);
                    exit (EXIT_FAILURE);
                }
                if (check_time_from_now (data[ndx].date) > SECPY) {
                    if (data[ndx].type)
                        data[ndx].value *= 1.5;
                    else
                        data[ndx].value *= 2.5;
                }
                n = 0;
                ndx++;
                if (ndx == MAXS)
                    goto arrayfull;
                break;
            default:
                fputs ("error: you shouldn't get here!\n", stderr);
                break;
        }
    }
    arrayfull:;
    if (fp != stdin) fclose (fp);   /* close file if not stdin */

    puts ("\ncomputed information\n");
    prn_data_t_array (data, ndx);   /* print the computed values */

    return 0;
}

Теперь используя ваш файл данных:

Пример входного файла

$ cat dat/namelbltypevaldate.txt
Hanif Hefaz
BA123HB
0
100.50
20180101

Jacki Shroff
UP673MK
1
3000.99
20170512

Пример использования / Вывод

Код выдаст:

$ ./bin/time_from_now3 dat/namelbltypevaldate.txt

computed information

Hanif Hefaz  BA123HB   0     251.25 20180101
Jacki Shroff UP673MK   1    4501.48 20170512

Если вы проверите, соответствующий коэффициент был применен к каждому.

Я действительно не хотел бы делать это с 5 отдельными массивами.Структура является подходящим инструментом для работы.Вы можете использовать 5 массивов, точно так же, как я использовал вышеупомянутый массив struct - у вас просто есть гораздо более длинный список переменных и намного больше имен, которые нужно отслеживать в вашем коде.Просмотрите это и дайте мне знать, если у вас есть еще вопросы.

Динамически выделяемый массив структур

Функционально программе не важно, где находится хранилище для ваших данных.является.Однако выделение с помощью автоматического хранения имеет недостаток, заключающийся в невозможности динамического увеличения при продолжении добавления записей.Альтернатива для динамического распределения ваших данных с использованием malloc, calloc, realloc.Это добавляет небольшую дополнительную сложность, поскольку теперь вам нужно отслеживать доступное выделенное хранилище, используемое хранилище и перераспределять, когда используемое хранилище равно вашему доступному хранилищу.

Вы не хотите realloc каждая строка - это неэффективно.Вместо этого вы будете выделять некоторое разумное начальное количество структур, заполнять их, пока не достигнете предела, а затем перераспределить.Сколько вы перераспределяете, зависит от вас, но общие схемы перераспределения заключаются в удвоении текущего выделенного размера (или вы можете добавить другое кратное значение, например 3/2 и т. Д., В зависимости от того, насколько быстро вы хотите увеличить свое распределение).В этом примере используется старый добрый метод double.

Сначала изменения (для печати только строк, длина которых превышает 1 год) просто включают перемещение вашего результата в:

                if (check_time_from_now (data[ndx].date) > SECPY) {

Добавление функциидля вывода записи ndx это то, что вы можете сделать, чтобы сохранить тело вашего кода в чистоте, например,

void prn_data_t_rec (mydata_t *data, int n)
{
    printf ("%-12s %-8s  %d  %9.2f %s\n", data[n].name, data[n].plate,
            data[n].type, data[n].value, data[n].date);
}

, что делает вызов из тела вашего кода:

                if (check_time_from_now (data[ndx].date) > SECPY) {
                    if (data[ndx].type)
                        data[ndx].value *= 1.5;
                    else
                        data[ndx].value *= 2.5;
                    prn_data_t_rec (data, ndx);  /* output > 1 year */
                }

Теперьк динамическому распределению.Вместо объявления:

mydata_t data[MAXS] = {{ .name = "" }};

Вы просто измените объявление и начальное выделение на:

#define MAXS   16u  /* initial number of structs */
...
    int maxs = MAXS;    /* variable to track allocated number of struct */
    mydata_t *data = calloc (maxs, sizeof *data); /* allocate storage */

( note: calloc было выбрано вместо mallocпотому что я хочу инициализировать ноль всей памяти и избежать необходимости явного инициализатора, чтобы установить каждый элемент type или value на ноль в противном случае. Затраты на calloc для выполнения этого незначительны)

Теперь * Подтвердите КАЖДОЕ распределение

    if (!data) {    /* validate every allocation */
        perror ("calloc-data");
        return 1;
    }

То же самое относится к каждому перераспределению с оговоркой.Вы Всегда realloc с временным указателем .Если вы перераспределите с помощью самого указателя, e..g ptr = realloc (ptr, newsize); и realloc не вернут NULL - вы перезапишете свой первоначальный адрес с NULL, создав утечку памяти и потеряв весь доступ к вашим существующим данным!

Все остальное в коде идентично, пока вы не доберетесь до realloc в case 4: из switch().Там, когда (ndx == maxs) вы должны realloc дополнительное хранилище, например,

            case 4: 
                if (strlen (buf) < MAXNM)
                    strcpy (data[ndx].date, buf);
                else {
                    fputs ("error: date excceeds storage.\n", stderr);
                    exit (EXIT_FAILURE);
                }
                if (check_time_from_now (data[ndx].date) > SECPY) {
                    if (data[ndx].type)
                        data[ndx].value *= 1.5;
                    else
                        data[ndx].value *= 2.5;
                    prn_data_t_rec (data, ndx);
                }
                n = 0;
                ndx++;
                if (ndx == maxs) {  /* check if realloc required */
                    /* realloc w/temp pointer to 2X current size */
                    void *tmp = realloc (data, 2 * maxs * sizeof *data);
                    if (!tmp) { /* validate every allocation */
                        perror ("realloc-data");
                        goto outofmem;  /* original data still good */
                    }
                    data = tmp; /* set data to newly reallocated block */
                    /* zero the new memory allocated (optional) */
                    memset (data + maxs, 0, maxs * sizeof *data);
                    maxs *= 2;  /* update the currently allocated max */
                }
                break;

( примечание: продолжение использования goto - здесь необходимо сохранить ваш оригинал data в случае сбоя realloc. Даже в случае сбоя ВСЕ исходное data по-прежнему исправно - и поскольку вы использовали временный указатель для проверки перераспределения, вы не потеряли к нему доступ.Так что просто выпрыгните из переключателя и цикла while, и вы сможете продолжать использовать его и free, когда он больше не нужен.

Собрав весь пример, вы получите:

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

#define MAXS   16u  /* initial number of structs */
#define MAXNM  32u  /* max characters in name and other arrays in struct */
#define MAXC 1024u  /* max characters in read buffer */
#define SECPY 31536000u /* seconds per-year */

typedef struct {
    char name[MAXNM],
        plate[MAXNM],
        date[MAXNM];
    int type;
    double value;
} mydata_t;

time_t fill_broken_down_time (int y, int m, int d)
{                   /* initialize struct members */
    struct tm bdt = { .tm_sec=0, .tm_min=0, .tm_hour=0, .tm_mday=d, 
                    .tm_mon=m>0?m-1:0, .tm_year=y-1900, .tm_isdst=-1 };

    return mktime(&bdt);    /* return mktime conversion to time_t */
}

double check_time_from_now (const char *str)
{
    int y, m, d;

    if (sscanf (str, "%4d%2d%2d", &y, &m, &d) != 3) {
        fprintf (stderr, "error non-date string: '%s'.\n", str);
        exit (EXIT_FAILURE);
    }

    time_t  now = time(NULL),
            then = fill_broken_down_time (y, m, d);
    double secs = difftime (now, then); /* get seconds between dates */

    return secs;
}

void prn_data_t_array (mydata_t *data, int n)
{
    for (int i = 0; i < n; i++)
        printf ("%-12s %-8s  %d  %9.2f %s\n", data[i].name, data[i].plate,
                data[i].type, data[i].value, data[i].date);
}

void prn_data_t_rec (mydata_t *data, int n)
{
    printf ("%-12s %-8s  %d  %9.2f %s\n", data[n].name, data[n].plate,
            data[n].type, data[n].value, data[n].date);
}

int main (int argc, char **argv) {
    /* use filename provided as 1st argument (stdin by default) */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
    int n = 0, ndx = 0, /* NOTE when dealing with array, start at ZERO */
        maxs = MAXS;    /* variable to track allocated number of struct */
    char buf[MAXC];     /* buffer to hold each line read from file */
    mydata_t *data = calloc (maxs, sizeof *data); /* allocate storage */

    if (!data) {    /* validate every allocation */
        perror ("calloc-data");
        return 1;
    }

    if (!fp) {  /* validate file open for reading */
        perror ("file open failed");
        return 1;
    }

    puts ("\ncomputed information for records > 1 year from now\n");

    while (fgets (buf, MAXC, fp)) {     /* read each line in file */
        if (isspace(*buf))  /* skip blank lines (or start with space) */
            continue;
        buf[strcspn (buf, "\r\n")] = 0; /* trim '\n' from end of buf */
        /* if line isn't a date line, just output line as non-date line */
        switch (n) {
            case 0: 
                if (strlen (buf) < MAXNM)
                    strcpy (data[ndx].name, buf);
                else {
                    fputs ("error: name excceeds storage.\n", stderr);
                    exit (EXIT_FAILURE);
                }
                n++;
                break;
            case 1:
                if (strlen (buf) < MAXNM)
                    strcpy (data[ndx].plate, buf);
                else {
                    fputs ("error: plate excceeds storage.\n", stderr);
                    exit (EXIT_FAILURE);
                }
                n++;
                break;
            case 2:
                if (sscanf (buf, "%d", &data[ndx].type) != 1) {
                    fputs ("error: type not an integer.\n", stderr);
                    exit (EXIT_FAILURE);
                }
                n++;
                break;
            case 3:
                if (sscanf (buf, "%lf", &data[ndx].value) != 1) {
                    fputs ("error: value not a double.\n", stderr);
                    exit (EXIT_FAILURE);
                }
                n++;
                break;
            case 4: 
                if (strlen (buf) < MAXNM)
                    strcpy (data[ndx].date, buf);
                else {
                    fputs ("error: date excceeds storage.\n", stderr);
                    exit (EXIT_FAILURE);
                }
                if (check_time_from_now (data[ndx].date) > SECPY) {
                    if (data[ndx].type)
                        data[ndx].value *= 1.5;
                    else
                        data[ndx].value *= 2.5;
                    prn_data_t_rec (data, ndx);
                }
                n = 0;
                ndx++;
                if (ndx == maxs) {  /* check if realloc required */
                    /* realloc w/temp pointer to 2X current size */
                    void *tmp = realloc (data, 2 * maxs * sizeof *data);
                    if (!tmp) { /* validate every allocation */
                        perror ("realloc-data");
                        goto outofmem;  /* original data still good */
                    }
                    data = tmp; /* set data to newly reallocated block */
                    /* zero the new memory allocated (optional) */
                    memset (data + maxs, 0, maxs * sizeof *data);
                    maxs *= 2;  /* update the currently allocated max */
                }
                break;
            default:
                fputs ("error: you shouldn't get here!\n", stderr);
                break;
        }
    }
    outofmem:;
    if (fp != stdin) fclose (fp);   /* close file if not stdin */

    puts ("\nall stored information\n");
    prn_data_t_array (data, ndx);   /* print the computed values */

    free (data);    /* don't forget to free what you allocate */

    return 0;
}

( примечание: печатать > 1 year во время цикла и выводить итоговые записи в конце - корректировать по мере необходимости)

Пример Использование / Вывод

Использование того же файла данных:

$ ./bin/time_from_now4 dat/namelbltypevaldate.txt

computed information for records > 1 year from now

Hanif Hefaz  BA123HB   0     251.25 20180101
Jacki Shroff UP673MK   1    4501.48 20170512

all stored information

Hanif Hefaz  BA123HB   0     251.25 20180101
Jacki Shroff UP673MK   1    4501.48 20170512

Использование памяти / проверка ошибок

В любом написанном вами коде, который динамически выделяет памятьу вас есть 2 обязанностей в отношении любого выделенного блока памяти: (1) всегда нажмитеуказатель на начальный адрес для блока памяти, поэтому (2) он может быть освобожден , когда он больше не нужен.

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

Для Linux valgrind - нормальный выбор. Для каждой платформы есть похожие проверки памяти. Все они просты в использовании, просто запустите вашу программу через него.

$ ./bin/time_from_now4 dat/namelbltypevaldate.txt
==4331== Memcheck, a memory error detector
==4331== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==4331== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==4331== Command: ./bin/time_from_now4 dat/namelbltypevaldate.txt
==4331==

computed information for records > 1 year from now

Hanif Hefaz  BA123HB   0     251.25 20180101
Jacki Shroff UP673MK   1    4501.48 20170512

all stored information

Hanif Hefaz  BA123HB   0     251.25 20180101
Jacki Shroff UP673MK   1    4501.48 20170512
==4331==
==4331== HEAP SUMMARY:
==4331==     in use at exit: 0 bytes in 0 blocks
==4331==   total heap usage: 12 allocs, 12 frees, 5,333 bytes allocated
==4331==
==4331== All heap blocks were freed -- no leaks are possible
==4331==
==4331== For counts of detected and suppressed errors, rerun with: -v
==4331== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

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

Дайте мне знать, если у вас есть дополнительные вопросы (что, вероятно, потребует нового вопроса на этом этапе)

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