LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 06-12-2013, 01:20 PM   #1
LUB997
Member
 
Registered: Jul 2003
Distribution: openSUSE Linux, Apple Darwin UNIX
Posts: 66

Rep: Reputation: 15
C - How to properly pass a struct containing char arrays from one function to another


I am working on a c program to read in a file containing data on thousands of people into an array of PERSON structs, and then output that data however I may need it to. I am trying to read in the data from the file and save it into an array of PERSON structs in the function
Code:
char* input_data_from_file( char filename[], char file_format[], int individuals, int categories )
. I am then trying to transfer this array of PERSON structs back to an array PERSON structs in main(), so that I can later pass that array of PERSON structs to other functions to perform various operations on it and output that data whatever way I may need to. I have never returned an array of structs before, though, and assigned it to another array of structs in main(). This is my first time attempting to do something like that, and I'm not sure how to go about it properly. The function
Code:
char* input_data_from_file( char filename[], char file_format[], int individuals, int categories )
is currently returning char* instead of an array of structs, simply for testing purposes to see if I can get anything from one struct within the function to another struct of the same type back in main(); Any suggestions appreciated on how to go about this in a well organized way. I am using C99, and have done a little with C before, but not very much. I am writing this code on a Mac using gcc in the Darwin UNIX terminal, however, once the code is finished, it will be compiled on an x86_64 Linux machine to generate .html pages for an Apache web server. I know it would probably be easier to use an object oriented language, such as C# with Mono or perhaps C++ or Java for such a task as this, but I want to challenge myself with C. Any other random suggestions on improving my C99 code would also be welcome and appreciated. If I had enough room to write a more lengthy title, it would have more properly said "How to properly pass an array of structs containing char arrays from one function to another?" Here is the code I have so far:

Code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>


bool string_contains_substring( char the_string[], char the_substring[] );
char* determine_file_format( char filename[] );
int number_of_individuals( char filename[], char file_format[] );
int number_of_categories();
char* input_data_from_file( char filename[], char file_format[], int individuals, int categories );

typedef struct {
    int day;
    int month;
    int year;
    bool circa;
} DATE;

typedef struct {
    int individual_id;
    int birth_family_id;
    int head_family_id;
    char name[50];
    DATE birth_date;
    char birth_location[85];
    DATE death_date;
    char death_location[85];
} PERSON;

int main( int argc, char *argv[] )
{
    char filename[256];
    char file_format[50];
    int individuals = 0;
    int categories = 0;
    
    strncpy(filename, "input_file.ged", strlen("input_file.ged"));
    strcpy(file_format, determine_file_format(filename));
    individuals = number_of_individuals(filename, file_format);
    categories = number_of_categories();
    
    printf("%s\n", input_data_from_file(filename, file_format, individuals, categories));
    
    return 0;
}

bool string_contains_substring( char the_string[], char the_substring[] )
{
	int pos_search = 0;
	int pos_text = 0;
	int len_search = strlen(the_substring);
	int len_text = strlen(the_string);
    
	for (pos_text = 0; pos_text < len_text; ++pos_text)
    {
        if(the_string[pos_text] == the_substring[pos_search])
        {
            ++pos_search;
            if(pos_search == len_search)
            {
                // match
                return true;
            }
        }
        
        else
        {
            pos_text -=pos_search;
            pos_search = 0;
        }
    }
    // no match
    return false;
}

char* determine_file_format( char filename[] )
{
    FILE *fp;
    
    if (fp = fopen(filename, "r")) {
        char line[250];
        
        while(fgets(line, sizeof(line), fp))
        {
            if (string_contains_substring(line, "1 DEST GED55") == true) {
                fclose(fp);
                return "gedcom_5_5";
            }
        }
        
        fclose(fp);
    }
    
    else {
        return NULL;
    }
    
    return NULL;
}

int number_of_individuals( char filename[], char file_format[] )
{
    FILE *fp;
    
    if (strcmp(file_format, "gedcom_5_5") == 0) {
        if (fp = fopen(filename, "r")) {
            char line[250];
            
            int individuals = 0;
            
            while(fgets(line, sizeof(line), fp))
            {
                char *pch;
                pch = strtok (line,"\n\r");
                while (pch != NULL)
                {
                    if (string_contains_substring(pch, "0 @I")) {
                        individuals++;
                    }
                    
                    pch = strtok (NULL, "\n\r");
                }
            }
            
            return individuals;
            
            fclose(fp);
        }
        
        else {
            return 0;
        }
    }
    
    else {
        return 0;
    }
    
    return 0;
}

int number_of_categories()
{
    return 10;
}

char* input_data_from_file( char filename[], char file_format[], int individuals, int categories )
{
    PERSON buffer_person;
    PERSON *return_person = calloc(1, 1);
    
    FILE *fp;
    
    if (strcmp(file_format, "gedcom_5_5") == 0) {
        if (fp = fopen(filename, "r")) {
            char line[250];
            
            while(fgets(line, sizeof(line), fp))
            {
                char *pch;
                pch = strtok (line,"\n\r");
                while (pch != NULL)
                {
                    strncpy(buffer_person.name, "John Smith", strlen("John Smith"));
                    strncpy(return_person->name, buffer_person.name, strlen(buffer_person.name));
                    
                    pch = strtok (NULL, "\n\r");
                }
            }
            
            fclose(fp);
            
            return return_person->name;
        }
        
        else {
            printf("%s: Unable to open file\n", filename);
            return NULL;
        }
    }
    
    else {
        printf("%s: Unknown file format\n", filename);
    }
    
    return NULL;
}

Last edited by LUB997; 06-12-2013 at 01:28 PM.
 
Old 06-12-2013, 01:32 PM   #2
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
I am not sure I understand your question.

You probably are looking for the following language idiom:

Code:
void f(SOME_TYPE *output_struct_ptr, <the_rest_of_args>)
  {
  ...
  (*output_struct_ptr).field_1 = value_1;
  ...
  (*output_struct_ptr).field_N = value_N;
  }

...

int main(...)
  {
  ...
  SOME_TYPE output_struct;
  ...
  f(&output_struct, <the_rest_of_args>);
  ...
  }
 
Old 06-12-2013, 01:43 PM   #3
LUB997
Member
 
Registered: Jul 2003
Distribution: openSUSE Linux, Apple Darwin UNIX
Posts: 66

Original Poster
Rep: Reputation: 15
Sergei,

The example that you have shown is actually very much like what I wish to accomplish. It looks from your example, like you are understanding me correctly. I think your example has already given me enough of an answer to work with.

A further question I have, though, is am I allowed by the C language to modify the variable that I pass to void f() as a pointer within the void f() function? For example, I would like void f() to read in data on thousands of people from my data file, and then add their data into SOME_TYPE *output_struct_ptr (which might be a pointer to an array of PERSON structs). Will C allow me to do this, and if so, what would be the proper syntax for passing an array of PERSON into the void f(*) function where you have used SOME_TYPE *output_struct_ptr as your example?

Thanks!

Last edited by LUB997; 06-12-2013 at 01:55 PM. Reason: Typo
 
Old 06-12-2013, 02:25 PM   #4
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by LUB997 View Post
Sergei,

The example that you have shown is actually very much like what I wish to accomplish. It looks from your example, like you are understanding me correctly. I think your example has already given me enough of an answer to work with.

A further question I have, though, is am I allowed by the C language to modify the variable that I pass to void f() as a pointer within the void f() function? For example, I would like void f() to read in data on thousands of people from my data file, and then add their data into SOME_TYPE *output_struct_ptr (which might be a pointer to an array of PERSON structs). Will C allow me to do this, and if so, what would be the proper syntax for passing an array of PERSON into the void f(*) function where you have used SOME_TYPE *output_struct_ptr as your example?

Thanks!
The 'void' return type means that the function itself doesn't return anything, but you can do whatever you like with data pointed to by pointers.


By the way, the extended idiom is:

Code:
ERROR_CODE_TYPE f(SOME_TYPE *output_struct_ptr, <the_rest_of_args>)
  {
  ...
  ERROR_CODE_TYPE result;
  ...
  (*output_struct_ptr).field_1 = value_1;
  ...
  (*output_struct_ptr).field_N = value_N;
  ...
  result = SUCCESS_OR_FAILURE;
  ...
  return result;
  }
 
Old 06-12-2013, 02:29 PM   #5
LUB997
Member
 
Registered: Jul 2003
Distribution: openSUSE Linux, Apple Darwin UNIX
Posts: 66

Original Poster
Rep: Reputation: 15
Sergei, I found a way that appears to work, based off of the example that you gave. I had to change one thing, but other than that, it is very close to what your example does. The only thing I changed from your example is that I have to pass the actual array of PERSON structs itself as a parameter to the function, rather than passing a pointer to the array of person structs as a parameter. The reason for this is that if I pass it as a pointer, and then try to modify the contents of the PERSON structs within the array, I get a compiler warning that I am trying to modify something that is not a struct or a union. That is true, because if it is a pointer to an array of structs, then it is not a struct; it is a pointer. Passing it as itself rather than as a pointer to itself is the only thing I changed, though. Your example of a passing the original variable as a parameter to a void function, and modifying its contents that way, seems to be working a lot better than what I was doing, which was attempting to modify a local variable within the function and return it to assign it's contents to the original variable in main(). Thanks for your help! Here is how I changed the code, based upon your example, and it seems to work properly now:

Code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>


typedef struct {
    int day;
    int month;
    int year;
    bool circa;
} DATE;

typedef struct {
    int individual_id;
    int birth_family_id;
    int head_family_id;
    char name[50];
    DATE birth_date;
    char birth_location[85];
    DATE death_date;
    char death_location[85];
    DATE baptism_date;
    char baptism_location[85];
    DATE burial_date;
    char burial_location[85];
} PERSON;

bool string_contains_substring( char the_string[], char the_substring[] );
char* determine_file_format( char filename[] );
int number_of_individuals( char filename[], char file_format[] );
void input_data_from_file( char filename[], char file_format[], PERSON the_database[] );

int main( int argc, char *argv[] )
{
    char filename[256];
    char file_format[50];
    int individuals = 0;
    int categories = 0;
    
    strncpy(filename, "input_file.ged", strlen("input_file.ged"));
    strcpy(file_format, determine_file_format(filename));
    individuals = number_of_individuals(filename, file_format);
    
    PERSON database[individuals];
    
    input_data_from_file(filename, file_format, database);
    
    printf("%s\n", database[0].name);
    
    return 0;
}

bool string_contains_substring( char the_string[], char the_substring[] )
{
	int pos_search = 0;
	int pos_text = 0;
	int len_search = strlen(the_substring);
	int len_text = strlen(the_string);
    
	for (pos_text = 0; pos_text < len_text; ++pos_text)
    {
        if(the_string[pos_text] == the_substring[pos_search])
        {
            ++pos_search;
            if(pos_search == len_search)
            {
                // match
                return true;
            }
        }
        
        else
        {
            pos_text -=pos_search;
            pos_search = 0;
        }
    }
    // no match
    return false;
}

char* determine_file_format( char filename[] )
{
    FILE *fp;
    
    if (fp = fopen(filename, "r")) {
        char line[250];
        
        while(fgets(line, sizeof(line), fp))
        {
            if (string_contains_substring(line, "1 DEST GED55") == true) {
                fclose(fp);
                return "gedcom_5_5";
            }
        }
        
        fclose(fp);
    }
    
    else {
        return NULL;
    }
    
    return NULL;
}

int number_of_individuals( char filename[], char file_format[] )
{
    FILE *fp;
    
    if (strcmp(file_format, "gedcom_5_5") == 0) {
        if (fp = fopen(filename, "r")) {
            char line[250];
            
            int individuals = 0;
            
            while(fgets(line, sizeof(line), fp))
            {
                char *pch;
                pch = strtok (line,"\n\r");
                while (pch != NULL)
                {
                    if (string_contains_substring(pch, "0 @I")) {
                        individuals++;
                    }
                    
                    pch = strtok (NULL, "\n\r");
                }
            }
            
            return individuals;
            
            fclose(fp);
        }
        
        else {
            return 0;
        }
    }
    
    else {
        return 0;
    }
    
    return 0;
}

void input_data_from_file( char filename[], char file_format[], PERSON the_database[] )
{
    FILE *fp;
    
    if (strcmp(file_format, "gedcom_5_5") == 0) {
        if (fp = fopen(filename, "r")) {
            char line[250];
            
            while(fgets(line, sizeof(line), fp))
            {
                char *pch;
                pch = strtok (line,"\n\r");
                while (pch != NULL)
                {
                    strncpy(the_database[0].name, "John Smith", strlen("John Smith"));
                    
                    pch = strtok (NULL, "\n\r");
                }
            }
            
            fclose(fp);
        }
        
        else {
            printf("%s: Unable to open file\n", filename);
        }
    }
    
    else {
        printf("%s: Unknown file format\n", filename);
    }
}

Last edited by LUB997; 06-12-2013 at 02:47 PM. Reason: Typo
 
Old 06-12-2013, 02:49 PM   #6
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by LUB997 View Post
Sergei, I found a way that appears to work, based off of the example that you gave. I had to change one thing, but other than that, it is very close to what your example does. The only thing I changed from your example is that I have to pass the actual array of PERSON structs itself as a parameter to the function, rather than passing a pointer to the array of person structs as a parameter. The reason for this is that if I pass it as a pointer, and then try to modify the contents of the PERSON structs within the array, I get a compiler warning that I am trying to modify something that is not a struct or a union. That is true, because if it is a pointer to an array of structs, then it is not a struct; it is a pointer. Passing it as itself rather than as a pointer to itself is the only thing I changed, though. Your example of a passing the original variable as a parameter to a void function, and modifying its contents that way, seems to be working a lot better than what I was doing, which was attempting to modify a local variable within the function and return it to assign it's contents to the original variable in main(). Thanks for your help! Here is how I changed the code, based upon your example, and it seems to work properly now:

Code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>


typedef struct {
    int day;
    int month;
    int year;
    bool circa;
} DATE;

typedef struct {
    int storysoga_id;
    int birth_family_id;
    int head_family_id;
    char name[50];
    DATE birth_date;
    char birth_location[85];
    DATE death_date;
    char death_location[85];
    DATE baptism_date;
    char baptism_location[85];
    DATE burial_date;
    char burial_location[85];
} PERSON;

bool string_contains_substring( char the_string[], char the_substring[] );
char* determine_file_format( char filename[] );
int number_of_individuals( char filename[], char file_format[] );
void input_data_from_file( char filename[], char file_format[], PERSON the_database[] );

int main( int argc, char *argv[] )
{
    char filename[256];
    char file_format[50];
    int individuals = 0;
    int categories = 0;
    
    strncpy(filename, "input_file.ged", strlen("input_file.ged"));
    strcpy(file_format, determine_file_format(filename));
    individuals = number_of_individuals(filename, file_format);
    
    PERSON database[individuals];
    
    input_data_from_file(filename, file_format, database);
    
    printf("%s\n", database[0].name);
    
    return 0;
}

bool string_contains_substring( char the_string[], char the_substring[] )
{
	int pos_search = 0;
	int pos_text = 0;
	int len_search = strlen(the_substring);
	int len_text = strlen(the_string);
    
	for (pos_text = 0; pos_text < len_text; ++pos_text)
    {
        if(the_string[pos_text] == the_substring[pos_search])
        {
            ++pos_search;
            if(pos_search == len_search)
            {
                // match
                return true;
            }
        }
        
        else
        {
            pos_text -=pos_search;
            pos_search = 0;
        }
    }
    // no match
    return false;
}

char* determine_file_format( char filename[] )
{
    FILE *fp;
    
    if (fp = fopen(filename, "r")) {
        char line[250];
        
        while(fgets(line, sizeof(line), fp))
        {
            if (string_contains_substring(line, "1 DEST GED55") == true) {
                fclose(fp);
                return "gedcom_5_5";
            }
        }
        
        fclose(fp);
    }
    
    else {
        return NULL;
    }
    
    return NULL;
}

int number_of_individuals( char filename[], char file_format[] )
{
    FILE *fp;
    
    if (strcmp(file_format, "gedcom_5_5") == 0) {
        if (fp = fopen(filename, "r")) {
            char line[250];
            
            int individuals = 0;
            
            while(fgets(line, sizeof(line), fp))
            {
                char *pch;
                pch = strtok (line,"\n\r");
                while (pch != NULL)
                {
                    if (string_contains_substring(pch, "0 @I")) {
                        individuals++;
                    }
                    
                    pch = strtok (NULL, "\n\r");
                }
            }
            
            return individuals;
            
            fclose(fp);
        }
        
        else {
            return 0;
        }
    }
    
    else {
        return 0;
    }
    
    return 0;
}

void input_data_from_file( char filename[], char file_format[], PERSON the_database[] )
{
    FILE *fp;
    
    if (strcmp(file_format, "gedcom_5_5") == 0) {
        if (fp = fopen(filename, "r")) {
            char line[250];
            
            while(fgets(line, sizeof(line), fp))
            {
                char *pch;
                pch = strtok (line,"\n\r");
                while (pch != NULL)
                {
                    strncpy(the_database[0].name, "John Smith", strlen("John Smith"));
                    
                    pch = strtok (NULL, "\n\r");
                }
            }
            
            fclose(fp);
        }
        
        else {
            printf("%s: Unable to open file\n", filename);
        }
    }
    
    else {
        printf("%s: Unknown file format\n", filename);
    }
}
You can have pointer to array, but you need to define types properly:

Code:
sergei@amdam2:~/junk/pointer_to_array> cat -n f.c
     1  typedef struct
     2    {
     3    int i;
     4    double d;
     5    } s;
     6
     7  typedef s array_type[2];
     8
     9
    10  void f(array_type *a_ptr)
    11    {
    12    (*a_ptr)[0].i = 1;
    13    }
sergei@amdam2:~/junk/pointer_to_array> ~/AFSWD/install/gcc-4.5.4/binsh/gcc -Wall -Wextra -c f.c
sergei@amdam2:~/junk/pointer_to_array>
 
Old 06-12-2013, 02:55 PM   #7
LUB997
Member
 
Registered: Jul 2003
Distribution: openSUSE Linux, Apple Darwin UNIX
Posts: 66

Original Poster
Rep: Reputation: 15
Yes, I see what you are saying. Is it better to pass it as a pointer?
 
Old 06-12-2013, 03:02 PM   #8
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by LUB997 View Post
Yes, I see what you are saying. Is it better to pass it as a pointer?
In some cases passing pointer to array allows the compiler to check index bounds statically - I remember I once got a warning because of out of bound index error in my code.

I am saying that pointer to an array lets the compiler know how many elements are in the array while regular pointer does not imply this knowledge.

This knowledge is compile time only.

Last edited by Sergei Steshenko; 06-12-2013 at 08:58 PM.
 
Old 06-12-2013, 03:51 PM   #9
LUB997
Member
 
Registered: Jul 2003
Distribution: openSUSE Linux, Apple Darwin UNIX
Posts: 66

Original Poster
Rep: Reputation: 15
Code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>


typedef struct {
    int day;
    int month;
    int year;
    bool circa;
} DATE;

typedef struct {
    int individual_id;
    int birth_family_id;
    int head_family_id;
    char name[50];
    DATE birth_date;
    char birth_location[85];
    DATE death_date;
    char death_location[85];
    DATE baptism_date;
    char baptism_location[85];
    DATE burial_date;
    char burial_location[85];
} PERSON;

typedef PERSON PERSON_DATABASE[4000];

bool string_contains_substring( char the_string[], char the_substring[] );
char* determine_file_format( char filename[] );
int number_of_individuals( char filename[], char file_format[] );
/*void input_data_from_file( char filename[], char file_format[], PERSON_DATABASE *the_database );*/

int main( int argc, char *argv[] )
{
    char filename[256];
    char file_format[50];
    int individuals = 0;
    int categories = 0;
    
    strncpy(filename, "input_file.ged", strlen("input_file.ged"));
    strcpy(file_format, determine_file_format(filename));
    individuals = number_of_individuals(filename, file_format);
    
    typedef PERSON PERSON_DATABASE[individuals];
    void input_data_from_file( char filename[], char file_format[], PERSON_DATABASE *the_database );
    
    PERSON_DATABASE database;
    
    input_data_from_file(filename, file_format, &database);
    
    printf("%s\n", database[0].name);
    
    return 0;
}

bool string_contains_substring( char the_string[], char the_substring[] )
{
	int pos_search = 0;
	int pos_text = 0;
	int len_search = strlen(the_substring);
	int len_text = strlen(the_string);
    
	for (pos_text = 0; pos_text < len_text; ++pos_text)
    {
        if(the_string[pos_text] == the_substring[pos_search])
        {
            ++pos_search;
            if(pos_search == len_search)
            {
                // match
                return true;
            }
        }
        
        else
        {
            pos_text -=pos_search;
            pos_search = 0;
        }
    }
    // no match
    return false;
}

char* determine_file_format( char filename[] )
{
    FILE *fp;
    
    if (fp = fopen(filename, "r")) {
        char line[250];
        
        while(fgets(line, sizeof(line), fp))
        {
            if (string_contains_substring(line, "1 DEST GED55") == true) {
                fclose(fp);
                return "gedcom_5_5";
            }
        }
        
        fclose(fp);
    }
    
    else {
        return NULL;
    }
    
    return NULL;
}

int number_of_individuals( char filename[], char file_format[] )
{
    FILE *fp;
    
    if (strcmp(file_format, "gedcom_5_5") == 0) {
        if (fp = fopen(filename, "r")) {
            char line[250];
            
            int individuals = 0;
            
            while(fgets(line, sizeof(line), fp))
            {
                char *pch;
                pch = strtok (line,"\n\r");
                while (pch != NULL)
                {
                    if (string_contains_substring(pch, "0 @I")) {
                        individuals++;
                    }
                    
                    pch = strtok (NULL, "\n\r");
                }
            }
            
            return individuals;
            
            fclose(fp);
        }
        
        else {
            return 0;
        }
    }
    
    else {
        return 0;
    }
    
    return 0;
}

void input_data_from_file( char filename[], char file_format[], PERSON_DATABASE *the_database )
{
    FILE *fp;
    
    if (strcmp(file_format, "gedcom_5_5") == 0) {
        if (fp = fopen(filename, "r")) {
            char line[250];
            
            while(fgets(line, sizeof(line), fp))
            {
                char *pch;
                pch = strtok (line,"\n\r");
                while (pch != NULL)
                {
                    strncpy((*the_database)[0].name, "John Smith", strlen("John Smith"));
                    
                    pch = strtok (NULL, "\n\r");
                }
            }
            
            fclose(fp);
        }
        
        else {
            printf("%s: Unable to open file\n", filename);
        }
    }
    
    else {
        printf("%s: Unknown file format\n", filename);
    }
}
 
Old 06-12-2013, 09:04 PM   #10
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by LUB997 View Post
Code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>


typedef struct {
    int day;
    int month;
    int year;
    bool circa;
} DATE;

typedef struct {
    int individual_id;
    int birth_family_id;
    int head_family_id;
    char name[50];
    DATE birth_date;
    char birth_location[85];
    DATE death_date;
    char death_location[85];
    DATE baptism_date;
    char baptism_location[85];
    DATE burial_date;
    char burial_location[85];
} PERSON;

typedef PERSON PERSON_DATABASE[4000];

bool string_contains_substring( char the_string[], char the_substring[] );
char* determine_file_format( char filename[] );
int number_of_individuals( char filename[], char file_format[] );
/*void input_data_from_file( char filename[], char file_format[], PERSON_DATABASE *the_database );*/

int main( int argc, char *argv[] )
{
    char filename[256];
    char file_format[50];
    int individuals = 0;
    int categories = 0;
    
    strncpy(filename, "input_file.ged", strlen("input_file.ged"));
    strcpy(file_format, determine_file_format(filename));
    individuals = number_of_individuals(filename, file_format);
    
    typedef PERSON PERSON_DATABASE[individuals];
    void input_data_from_file( char filename[], char file_format[], PERSON_DATABASE *the_database );
    
    PERSON_DATABASE database;
    
    input_data_from_file(filename, file_format, &database);
    
    printf("%s\n", database[0].name);
    
    return 0;
}

bool string_contains_substring( char the_string[], char the_substring[] )
{
	int pos_search = 0;
	int pos_text = 0;
	int len_search = strlen(the_substring);
	int len_text = strlen(the_string);
    
	for (pos_text = 0; pos_text < len_text; ++pos_text)
    {
        if(the_string[pos_text] == the_substring[pos_search])
        {
            ++pos_search;
            if(pos_search == len_search)
            {
                // match
                return true;
            }
        }
        
        else
        {
            pos_text -=pos_search;
            pos_search = 0;
        }
    }
    // no match
    return false;
}

char* determine_file_format( char filename[] )
{
    FILE *fp;
    
    if (fp = fopen(filename, "r")) {
        char line[250];
        
        while(fgets(line, sizeof(line), fp))
        {
            if (string_contains_substring(line, "1 DEST GED55") == true) {
                fclose(fp);
                return "gedcom_5_5";
            }
        }
        
        fclose(fp);
    }
    
    else {
        return NULL;
    }
    
    return NULL;
}

int number_of_individuals( char filename[], char file_format[] )
{
    FILE *fp;
    
    if (strcmp(file_format, "gedcom_5_5") == 0) {
        if (fp = fopen(filename, "r")) {
            char line[250];
            
            int individuals = 0;
            
            while(fgets(line, sizeof(line), fp))
            {
                char *pch;
                pch = strtok (line,"\n\r");
                while (pch != NULL)
                {
                    if (string_contains_substring(pch, "0 @I")) {
                        individuals++;
                    }
                    
                    pch = strtok (NULL, "\n\r");
                }
            }
            
            return individuals;
            
            fclose(fp);
        }
        
        else {
            return 0;
        }
    }
    
    else {
        return 0;
    }
    
    return 0;
}

void input_data_from_file( char filename[], char file_format[], PERSON_DATABASE *the_database )
{
    FILE *fp;
    
    if (strcmp(file_format, "gedcom_5_5") == 0) {
        if (fp = fopen(filename, "r")) {
            char line[250];
            
            while(fgets(line, sizeof(line), fp))
            {
                char *pch;
                pch = strtok (line,"\n\r");
                while (pch != NULL)
                {
                    strncpy((*the_database)[0].name, "John Smith", strlen("John Smith"));
                    
                    pch = strtok (NULL, "\n\r");
                }
            }
            
            fclose(fp);
        }
        
        else {
            printf("%s: Unable to open file\n", filename);
        }
    }
    
    else {
        printf("%s: Unknown file format\n", filename);
    }
}
Shouldn't the lines in red be outside (before) 'main' ?

In real programs I have separate files for typedefs and yet other separate files for function prototypes - the a latter #include the former.
 
Old 06-13-2013, 02:23 AM   #11
LUB997
Member
 
Registered: Jul 2003
Distribution: openSUSE Linux, Apple Darwin UNIX
Posts: 66

Original Poster
Rep: Reputation: 15
Yes, the lines in red do need to be outside of main(). I had them in main() temporarily, while I was experimenting with things to try to figure out a way to set the size of typedef PERSON PERSON_DATABASE based upon how many people are in the file that is read in. If you notice, I had the line typedef PERSON PERSON_DATABASE[4000] outside of main(), while I was experimenting with things, and that was actually the line of code that was making the program work, because the lines in red inside of main() were doing nothing. I had a very difficult time figuring out a way to set the size of PERSON PERSON_DATABASE variably, based upon how many people are read in from the data file. I ended up eventually finding a way that seems to work quite well though:

Code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

typedef struct {
    int day;
    int month;
    int year;
    bool circa;
} DATE;

typedef struct {
    int individual_id;
    int birth_family_id;
    int head_family_id;
    char name[50];
    DATE birth_date;
    char birth_location[85];
    DATE death_date;
    char death_location[85];
    DATE baptism_date;
    char baptism_location[85];
    DATE burial_date;
    char burial_location[85];
    char text_from_file[85];
} PERSON;

typedef PERSON *PERSON_DATABASE;

bool string_contains_substring( char the_string[], char the_substring[] );
char* determine_file_format( char filename[] );
int number_of_individuals( char filename[], char file_format[] );
void input_data_from_file( char filename[], char file_format[], PERSON_DATABASE *the_database );

int main( int argc, char *argv[] )
{
    char filename[256];
    char file_format[50];
    int individuals = 0;
    
    strncpy(filename, "input_file.ged", strlen("input_file.ged"));
    strcpy(file_format, determine_file_format(filename));
    
    individuals = number_of_individuals(filename, file_format);
    
    PERSON_DATABASE database = calloc(individuals, sizeof(PERSON));
    
    input_data_from_file(filename, file_format, &database);
    
    printf("%s\n", database[1].name);
    printf("%d\n", individuals);
    
    return 0;
}

bool string_contains_substring( char the_string[], char the_substring[] )
{
	int pos_search = 0;
	int pos_text = 0;
	int len_search = strlen(the_substring);
	int len_text = strlen(the_string);
    
	for (pos_text = 0; pos_text < len_text; ++pos_text)
    {
        if(the_string[pos_text] == the_substring[pos_search])
        {
            ++pos_search;
            if(pos_search == len_search)
            {
                // match
                return true;
            }
        }
        
        else
        {
            pos_text -=pos_search;
            pos_search = 0;
        }
    }
    // no match
    return false;
}

char* determine_file_format( char filename[] )
{
    FILE *fp;
    
    if (fp = fopen(filename, "r")) {
        char line[250];
        
        while(fgets(line, sizeof(line), fp))
        {
            if (string_contains_substring(line, "1 DEST GED55") == true) {
                fclose(fp);
                return "gedcom_5_5";
            }
        }
        
        fclose(fp);
    }
    
    else {
        return NULL;
    }
    
    return NULL;
}

int number_of_individuals( char filename[], char file_format[] )
{
    FILE *fp;
    
    if (strcmp(file_format, "gedcom_5_5") == 0) {
        if (fp = fopen(filename, "r")) {
            char line[250];
            
            int individuals = 0;
            
            while(fgets(line, sizeof(line), fp))
            {
                char *pch;
                pch = strtok (line,"\n\r");
                while (pch != NULL)
                {
                    if (string_contains_substring(pch, "0 @I")) {
                        individuals++;
                    }
                    
                    pch = strtok (NULL, "\n\r");
                }
            }
            
            return individuals;
            
            fclose(fp);
        }
        
        else {
            return 0;
        }
    }
    
    else {
        return 0;
    }
    
    return 0;
}

void input_data_from_file( char filename[], char file_format[], PERSON_DATABASE *the_database )
{
    FILE *fp;
    
    if (strcmp(file_format, "gedcom_5_5") == 0) {
        if (fp = fopen(filename, "r")) {
            char line[250];
            
            while(fgets(line, sizeof(line), fp))
            {
                char *pch;
                pch = strtok (line,"\n\r");
                while (pch != NULL)
                {
                    // Do input work here
                    strncpy((*the_database)[1].name, "John Smith", strlen("John Smith"));
                    
                    pch = strtok (NULL, "\n\r");
                }
            }
            
            fclose(fp);
        }
        
        else {
            printf("%s: Unable to open file\n", filename);
        }
    }
    
    else {
        printf("%s: Unknown file format\n", filename);
    }
}
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] [c] malloc with struct->char **variablelengtharray Mol_Bolom Programming 9 05-02-2013 08:36 AM
How can I pass a char* array as a function paramter in c++? chinho Programming 3 01-28-2011 12:40 PM
[C] Pass pointer of struct to function by refrence PJani Programming 3 11-19-2008 12:49 AM
how to pass pointer of struct to function? jinxcat Programming 2 09-01-2005 09:29 AM
switch statement converting struct char to struct int oceaneyes2 Programming 2 12-10-2003 04:30 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 02:28 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration