0

my C class is having us read from a file with an unknown number of entries but a known format, which goes like this:

firstname, lastname

address line 1

address line 2

zip code

So we're dynamically allocating an array of pointers to structs, and I made a function getData which will use gets to read line by line and store everything appropriately. My biggest problem is how to make it so that it stops collecting data when the file has nothing left to read. I have crudely come up with while((strcpy(ptr[i].name, buffer))!=EOF) which I'm sure makes no sense but it seemed to somewhat work, especially because it correctly prints out almost every entry. Here is the code:

    #define _CRT_SECURE_NO_WARNINGS

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

struct AddressBook {
    char *name[10];
    char *address[50];
    int zip;
};

typedef struct AddressBook adds;

void getData(adds *ptr);

int main() {
    //adds *ptrArr[50];
    int size = 50;
    adds *ptrs = (adds*)calloc(size, sizeof(adds*)); //array of 50 ptrs allocated dynamically

    if (ptrs == NULL) {
        printf("Bad memory allocation...exiting.");
        exit(0);
    }
    else
        printf("Allocation successful...\n");
    getData(ptrs);

    system("pause");
    return 0;
}

void getData(adds *ptr) {
    printf("Gathering data...\n");
    char buffer[50];
    int i = 0;
    gets(buffer);
    while((strcpy(ptr[i].name, buffer))!=EOF) {
        if (i > 0) {
            gets(buffer);
            strcpy(ptr[i].name, buffer);
        }
        /*gets(buffer);
        strcpy(ptr[i].name, buffer);*/
        gets(buffer);
        strcpy(ptr[i].address, buffer);     
        gets(buffer);
        strcat(ptr[i].address, " ");
        strcat(ptr[i].address, buffer);
        gets(buffer);
        ptr[i].zip = atoi(buffer);
        printf("Printing data for line %d...\n", i);
        printf("name is: %s\naddress is: %s\nzip is: %d\n", ptr[i].name, ptr[i].address, ptr[i].zip);
        printf("\n");
        i++;
    }
}

Two problems are happening: 1. When I print, it will print up to 50 entries, which is just the amount of space I asked for but the actual number of entries is far less.

2.It prints our every entry correctly except for line 2. (or subscript 1) here is the input if you're curious: https://pastebin.com/Ph5wzFeF

here is the output for the first 3 entries:

Printing data for line 0...
name is: A1, A2
address is: 20294 Lorenzana Dr Woodland Hills, CA
zip is: 91364

Printing data for line 1...
name is: B1, name is: B1, name is: B1, name is: B1, name is: B1, name is: B1, nam
address is: 1, name is: B1, name is: B1, name is: B1, nam
address is: 1, name is: B1, name is: B1, name is: B1, nam
address is: 1, name is: B1, name is: B1, name is: B1, nam
address is: 1, name is: B1, name is: B1,
zip is: 94023

Printing data for line 2...
name is: C1, C2
address is: 5142 Dumont Pl Azusa, CA
zip is: 91112

Debugging has been a pain because I can't use i/o redirection and the visual studio debugger at the same time. If anyone has any suggestions as to how I can debug I would appreciate it! But otherwise I would like some feedback on what i've got.

Taelle Echon
  • 31
  • 1
  • 6
  • 1
    For starters, your name and address arrays should be `char` not `char*`, and your `calloc` call should take `sizeof(adds)`, not `sizeof(adds*)`. You should not cast the return value of `calloc` and you should range-check `i` to ensure you don't overflow your buffer. Use `fgets` instead of `gets` because the latter is extremely unsafe. – paddy Nov 19 '18 at 01:14
  • I have no idea why i made them char * , thanks for pointing that out. I figured i should ask for size of(adds*) because i'm allocating an array of pointers, not an array of structs. should I still be asking for adds even knowing this? I will implement a range check, and I figured I couldn't use fgets because he wants us to only use file input/output redirection, we haven't learned how to work with files within the source code itself. It would be much easier if it were that way though! – Taelle Echon Nov 19 '18 at 01:20
  • Use `fgets`. Check the result of `fgets`. – jxh Nov 19 '18 at 01:20
  • Given accesses like `ptr[i].address`, it's clear you're _not_ using it as an array of pointers. Otherwise you would be allocating each entry and using `ptr[i]->address`. Not to mention that a dynamically-allocated array of pointers would be of type `adds**`. Regarding `fgets`, you simply use `stdin` as the file stream. – paddy Nov 19 '18 at 01:23
  • Ahhh okay thank you, i'll try fgets and use stdin, and do you mean I should be dynamically allocating the structs as well? like within my while loop set ptr[i] to a new struct? I have tried it and couldnt get the syntax to agree with me. Let me know if I;m misunderstanding you. – Taelle Echon Nov 19 '18 at 01:27
  • regarding your edit paddy: you're saying `adds **ptrs = (adds*)calloc(size, sizeof(adds*));` will set ptr to be a pointer to an array of pointers? – Taelle Echon Nov 19 '18 at 01:29
  • Don't cast `calloc()`. – melpomene Nov 19 '18 at 01:33
  • Note that [`gets()` is too dangerous to be used — ever!](https://stackoverflow.com/questions/1694036/why-is-the-gets-function-dangerous-why-should-it-not-be-used) – Jonathan Leffler Nov 19 '18 at 03:59

0 Answers0