简体   繁体   中英

Reading in multiple lines of keywords as character arrays from file? In C

Hi I am trying to read in lines of text from an input file. The file can contain multiple keywords. Each keyword is seperated by an end of line. I can assume the keywords wont be longer than 30 characters. So far I am able to readon only one keyword and then my loop ends. How do I read multiple keywords until I reach the end of file. I want to store each keyword into different character arrays. This is what I have so far.

char readKeywords()
{
    FILE *finn;
    char array2[30];
    int i = 0;
    finn = fopen("cp3Keywords.txt", "r");
    while (fscanf(finn, "%c", &array2[i]) != '\n')
    {
        i++;
    }

}

OK, you've got several problems here.

  1. The fscanf return value is the number of items read, which in this case will always be 1.

  2. The loop seems intended to end when you read the newline, not when you reach end of file.

How about something like this:

int getNextKeyword(FILE *fp, char *result) {
    int c;
    while (EOF != (c = fgetc(fp))) {
        if (c == '\n') break;
        *result++ = c;
    }
    *result = 0;
    return c;
}

This consumes characters up to the next newline or EOF. It accumulates the result in the input buffer provided. When you hit the newline or EOF, you write a 0 in the buffer, thus resulting in a standard null-terminated string. It returns the last character written. Then you write some more code that calls this function in a loop until it returns EOF.

Please notice how the variable c is type int, not type char. That's because EOF (the end of file value returned from fgetc) is not representable as a character. So if you write char c; c = fgets(fp); if (c == EOF) ... it will never be true. This is a common C programming mistake.

So the calling code might look like this:

FILE *fp = fopen("cp3Keywords.txt", "r");
char array2[30];
while (EOF != readKeyword(fp, array2)) {
    // Do what you want to do with the keyword
}

You can try something like this:

while (fgets(array2, 30, finn)!= 0)
{
    puts(array2); //to print on screen, However you can copy it in separate array as per requirement.
}

You could do something like this:

int readLine( FILE *stream, char *line )
{
    int i = 0;
    while( fscanf( stream, "%c", line + i ) != EOF )
    {
        if( line[i++] == '\n' )
        {
            line[i-1] = '\0';
            return 1;
        }
    }

    return 0;
}

int main( )
{
    const int KEYWORDS_COUNT = 100;
    char *keywords[KEYWORDS_COUNT];
    FILE *finn;
    int i = 0;

    finn = fopen( "plik.txt", "r" );
    do
    {
        keywords[i] = (char*)malloc( sizeof(char) * 31 );
    } while( readLine( finn, keywords[i++] ) );

    //free memory
    for( ; i > 0; i-- )
        free( keywords[i-1] );

    fclose( finn );

}

If you don't know how many keywords there will be you can always realloc and copy keywords to new array

Below you'll find a working solution. Reading keywords is easy once you know about getline() function. The tricky part is storing the keywords. Since you don't know how many there will be, you need to use a dynamically allocated list, which then you need to iterate over, clear, etc.

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

struct list_node{
    struct list_node *next;
    char *value;
};

struct list_node * appendToList(struct list_node *head, const char* keyword){
    //create new node and save value
    struct list_node *new_node, *node;
    new_node=calloc(sizeof(struct list_node),1); 
    if(!new_node){
        fprintf(stderr,"calloc() failed\n");
        return NULL;
    }
    new_node->value=strdup(keyword);

    //append new node to the tail of the list
    if(head){//head already exists, so append
        node=head;
        while(node->next)node=node->next;
        node->next=new_node;
    }else{ //appending first element
        head=new_node;
    }

    return head;
}
const char * getKeywordAtIndex(struct list_node *head, unsigned int index){
    const char *rv=NULL;
    if(head){ //basic sanity check
        while(index-->0){
            if(head->next)head=head->next;//walk the list
            else return NULL; //index too big
        }
        rv=head->value;
    }
    return rv;
}
void clearList(struct list_node *head){
    struct list_node *node;
    while(head){
        free(head->value);
        node=head->next;
        free(head);
        head=node;
    }
}
int main(){

    FILE *fp=fopen("keywords.txt","r");
    if(!fp){
        perror("Opening file failed");
        return 1;
    }

    char *lineptr=NULL;
    size_t buffer_len=0;
    ssize_t string_len;
    struct list_node *head=NULL;
    while((string_len=getline(&lineptr,&buffer_len,fp))!=-1){
        printf("line:%s\n",lineptr);
        if(lineptr[string_len-1]=='\n')lineptr[string_len-1]='\0';
        head=appendToList(head,lineptr);
    }
    free(lineptr);
    fclose(fp);
    int idx=0;
    const char *keyword;
    while((keyword=getKeywordAtIndex(head,idx++))!=NULL){
        printf("from list: %s\n",keyword);
    }
    clearList(head);
    return 0;
}

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