1
#define LINES 4
#define LENGHT 30

typedef struct
{
  char *name;
  char *phoneNumber;
  char *location;
  char *traveltype;
} Client;

int main(int argc, char *argv[])
{
  char *filename = argv[1];
  char clientData[LINES][LENGHT];
  readClientData(filename, clientData);

  /* How to do this client struct */
  Client *client = createClient(clientData[0], clientData[1], clientData[2], clientData[3]);
  return 0;
}

void readClientData(char *filename, char clientData[LINES][LENGHT])
{
  FILE *file = fopen(filename, "r");
  if (file == NULL)
  {
    perror("Error while opening file!");
    exit(1);
  }

  char line[LENGHT];
  int i = 0;
  while (fgets(line, LENGHT, file) != NULL)
    clientData[i] = line; /* How to do this */ 
    i++;
  fclose(file);
}

Coming from a pythonista world I'm a bit confused how things are working here. It is clear that I can't just add lines to the list, nor can acces the lines the way I do to initialize the client struct.

Maybe I should just use a char *clientData[], but don't know how.

MattSom
  • 2,097
  • 5
  • 31
  • 53

1 Answers1

2

To copy C strings, you need to use:

char * strcpy ( char * destination, const char * source );

from the Standard C String Library, string.h.

However, notice, than unlike Python (your background), indentation does not define the body of the loop, you need to use curly brackets!

So, you need to do this:

while (fgets(line, LENGHT, file) != NULL)
{
  strcpy(clientData[i], line);
  i++;
}

Without the curly brackets, only the first immediate line of code will be considered to be the body of the loop. So, in the example above, the body of the loop - if we did not use curly brackets - would be only the call to the method for copying strings, and the increment of the counter would not be part of the loop!


You need to define, or just declare a method before using it, which you didn't do in your example.


Since you only need one client, you do not need a pointer, you can simply create one, by doing Client client;.

In order to keep it simple, use the knowledge you gathered from reading this answer so far, and do define the maximum length of the strings (that is the size of the arrays of characters every field of your struct gets to have). Remember, that C strings have to be NULL terminated, so, the maximum length of them is actually LENGTH - 1.

If you keep the fields of the struct as pointers to char, then you'd need to dynamically allocate memory, or set the pointer point to corresponding string of the clientData array (similarly to what you did for the file name). I suggest you get some experience in C first, and then try implementing these two approaches.

Now, you are ready to do:

strcpy(client.name, clientData[0]);
...
strcpy(client.traveltype, clientData[3]);

Complete working example:

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

#define LINES 4
#define LENGTH 30

typedef struct
{
  char name[LENGTH];
  char phoneNumber[LENGTH];
  char location[LENGTH];
  char traveltype[LENGTH];
} Client;

void readClientData(char *filename, char clientData[LINES][LENGTH]);
void printClient(Client client);

int main(int argc, char *argv[])
{

  char *filename = NULL;
  if(argc > 1)
    filename = argv[1];
  else
  {
    printf("Usage: %s <filename>\n", argv[0]);
  }
  char clientData[LINES][LENGTH];
  readClientData(filename, clientData);

  Client client;
  strcpy(client.name, clientData[0]);
  strcpy(client.phoneNumber, clientData[1]);
  strcpy(client.location, clientData[2]);
  strcpy(client.traveltype, clientData[3]);

  printClient(client);

  return 0;
}

void readClientData(char *filename, char clientData[LINES][LENGTH])
{
  FILE *file = fopen(filename, "r");
  if (file == NULL)
  {
    perror("Error while opening file!");
    exit(1);
  }

  char line[LENGTH];
  int i = 0;
  while (fgets(line, LENGTH, file) != NULL)
  {
    line[strcspn(line, "\n")] = 0;
    strcpy(clientData[i], line);
    i++;
  }
  fclose(file);
}

void printClient(Client client)
{
    printf("%s, %s, %s, %s\n", client.name, client.phoneNumber, client.location, client.traveltype);
}

Output:

Georgioss-MBP:Desktop gsamaras$ cat test.txt 
MegasAlexandros
3335632320
Greece
Cosmos
Georgioss-MBP:Desktop gsamaras$ gcc main.c
Georgioss-MBP:Desktop gsamaras$ ./a.out test.txt 
MegasAlexandros, 3335632320, Greece, Cosmos

PS: I used this in my example: Removing trailing newline character from fgets() input

gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • Thank you! One question: can I do this considering this is a multidimensional array? Can I acces the char strings this way? I mean, I need these 'lines' to behave like strings for the struct declared above. – MattSom Nov 28 '19 at 19:45
  • 1
    You are welcome @MattSom. `clientData[i]` is a string, the i-th string in the array to be exact. `clientData[i][j]` is the j-th character of the i-th string of the array. I updated my answer with a full working example. I think that this should be enough for now, get a good grasp of that, and then try my suggestion, and if you find problems, debug them, but if you get stuck, post a new question, and share it with me, if you like. :) Hope this helps! – gsamaras Nov 28 '19 at 20:36
  • 1
    Will do! Thank you, I'm trying to work with this information now :) – MattSom Nov 28 '19 at 20:46