Suppose I have a text file such as:
Adam: Tall Handsome Kind Athlete
He enjoys playing basketball
Sabrina: Short Pretty Funny Adorable Gymnast
She loves gymnastics
Sinclair: Blonde
He is blonde
Assume the file has several more people, each with a Name and then 0 or more characteristics about them and then a new line with a tab following a sentence underneath. For example,
Adam: would be the name
Tall Handsome Kind Athlete would be 4 individual characteristics
He enjoys playing basketball would be the sentence.
I want to store this information in a structure like so:
typedef struct People {
char *name;
char **characteristics;
char *sentence;
} People;
typedef struct List {
People **list;
int total_ppl;
} List;
int main (void) {
List *ppl_list = malloc(sizeof(List));
ppl_list->list = malloc(sizeof(People));
int i = 0;
FILE *pf = fopen("input.txt", "r");
if (pf == NULL) {
printf("Unable to open the file");
} else {
/* I'm not sure how to go about reading the information from here. I was thinking about using
fscanf but I don't know how to separate and store the Name, each Characteristic, and
the sentence separately. I know I will need to realloc ppl_list as more people are read from the
file. If I should change my structs to organize it better, please let me know.
*/
}
}
This answer is maybe not complete but it will help you, at least, with the processing of the lines in the text file.
Assuming a file.txt
as the input file, and with the following format
Adam: Tall Handsome Kind Athlete
He enjoys playing basketball
Sabrina: Short Pretty Funny Adorable Gymnast
She loves gymnastics
Sinclair: Blonde
He is blonde
We can process this file as follows
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
/*process_info_line: process the line with the name and attributes*/
int process_info_line(char *line)
{
char *next = NULL;
char *part = strtok_r(line, ":", &next);
if (part)
printf("NAME: %s\n", part);
else
return 0;
while (part != NULL) {
part = strtok_r(NULL, " ", &next);
if (part)
printf("ATTRIBUTE: %s\n", part);
}
return 0;
}
/*process_sentence: process the line with the sentence*/
char *process_sentence(char *line)
{
line = line + 4;
return line;
}
/*is_sentence: checks if the line is a sentence, given your definition
* with a tab(or 4 spaces) at the begining*/
int is_sentence(char *line)
{
if (strlen(line) == 0)
return 0;
char *ptr = line;
int space_count = 0;
while (ptr != NULL) {
if (strncasecmp(ptr, " ", 1) != 0) {
break;
}
space_count++;
ptr++;
}
if (space_count == 4)
return 1;
return 0;
}
/*scan_file: read each of the lines of the file and use
* the previous functions to process it.*/
int scan_file(char *filename)
{
char *line_buf = NULL;
size_t line_buf_size = 0;
ssize_t line_size;
int line_count = 0;
FILE *fp = fopen(filename, "r");
if (!fp) {
fprintf(stderr, "Error opening file '%s'\n", filename);
return 1;
}
/*Get the first line of the file*/
line_size = getline(&line_buf, &line_buf_size, fp);
while (line_size >= 0)
{
line_count++;
line_buf[line_size-1] = '\0'; /*removing '\n' */
if (is_sentence(line_buf)) {
printf("SENTENCE: %s\n", process_sentence(line_buf));
} else {
process_info_line(line_buf);
}
line_size = getline(&line_buf, &line_buf_size,fp);
}
// don't forget to free the line_buf used by getline
free(line_buf);
line_buf = NULL;
fclose(fp);
return 0;
}
int main(void)
{
scan_file("file.txt");
return 0;
}
This will generate the following output
NAME: Adam
ATTRIBUTE: Tall
ATTRIBUTE: Handsome
ATTRIBUTE: Kind
ATTRIBUTE: Athlete
SENTENCE: He enjoys playing basketball
NAME: Sabrina
ATTRIBUTE: Short
ATTRIBUTE: Pretty
ATTRIBUTE: Funny
ATTRIBUTE: Adorable
ATTRIBUTE: Gymnast
SENTENCE: She loves gymnastics
NAME: Sinclair
ATTRIBUTE: Blonde
SENTENCE: He is blonde