简体   繁体   中英

How would I go about reading and separating this text file's information into arrays?

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.
*/

 }
}

There is a function called strtok(): https://www.tutorialspoint.com/c_standard_library/c_function_strtok.htm

Though I've never used it, the one time I had to do this I implemented a function that would separate a string into an array of pointers to pointers of chars and dynamically allocated memory for the whole block, it would look for commas and generate a new string each time it found one, my code wouldn't work in your case because it was written to specifically ignore withe spaces, though if you're not ignoring them but using them as delimitators the code gets a lot simpler.

Edit: as for getting the info out of the file I would create a buffer of an absurd size like say 32768 Bytes and use fgets(buffer, 32768, pf), though you may wanna add a check to see if even 32K chars weren't enough for the read and to deal with that, though I imagine it wouldn't be necessary.

Also this were the prototypes of the functions i implemented once, to give you a better idea of what you'd have to code:

char        **separete_string   (char *string, char delim);
void        free_string_list    (char **list);

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM