nbdy
nbdy

Reputation: 65

Dynamically allocated unknown length string reading from file (it has to be protected from reading numbers from the file) in C

My problem is such that I need to read string from file. File example:

Example 1 sentence

Example sentence number xd 595 xd 49 lol

but I have to read only the string part, not numbers. I guess I have to use fscanf() with %s for it but let me know what you guys think about it. The part where my problem begins is how to read the string (it is unknown length) using malloc(), realloc()? I tried it by myself, but I failed (my solution is at bottom of my post). Then I need to show the result on the screen.

P.S. I have to use malloc()/calloc(), realloc() <-- it has to be dynamically allocated string :) (char *)

Code I've tried:

    int wordSize = 2;
    char *word = (char *)malloc(wordSize*sizeof(char));
    char ch;

    FILE* InputWords = NULL;
    InputWords = fopen(ListOfWords,"r"); /* variable ListOfWords contains name of the file */

    if (InputWords == NULL)
    {
      printf("Error while opening the file.\n");
      return 0;
    }

    int index = 0;
    while((ch = fgetc(InputWords)) != -1)
    {
      if(ch == ' ')
      {
        printf("%s\n", word);
        wordSize = 2;
        index = 0;
        free(word);
        char* word = (char *)malloc(wordSize*sizeof(char));
      }
      else
      {
        wordSize++;
        word = (char *)realloc(word, wordSize*sizeof(char));
        strcpy(word,ch);
        index++;
      }
    }
  fclose(InputWords);

Upvotes: 2

Views: 183

Answers (1)

Hitokiri
Hitokiri

Reputation: 3699

For your code, you have something have to improve:

  1. fgetc return the int type not char. So change char ch to int ch;
  2. As the comment of @pmg use EOF (may be any negative value) instead of -1`
  3. strcpy(word,ch); you try to copy character (ch) to character pointer (word).
  4. Do not cast malloc or realloc function: Do I cast the result of malloc?.

For solving your question, i propose you use the strtok function to split string by space character, then test each word is number or not. If the word is not a number, you can use strcat to concatenate the word to the old sentence.

The complete code:

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

int is_number(char *str) {
    if (strlen(str) == 0)
       return -1;
    for(int i =0; (i < strlen(str)) && (str[i] != '\n') ; i++) {
        if(!isdigit(str[i]))
            return -1;
    }
    return 1;
}

int main()
{
    FILE *fp = fopen("input.txt", "r");
    char line[256];

    if(!fp) return -1;
    char **sentence;
    int i = 0;
    sentence = malloc(sizeof(char *));
    if(!sentence) return -1;
    while(fgets(line, 256, fp)) {
        char * token = strtok(line, " ");
        size_t len = 0;
        sentence = realloc(sentence, sizeof(char *) * (i+1));
        if(!sentence) return -1;
        while(token != NULL) {
            if (is_number(token) != 1) {

                sentence[i] = realloc(sentence[i], len + 2 + strlen(token)); // +2 because 1 for null character and 1 for space character
                if (!sentence[i]) {
                    printf("cannot realloc\n");
                    return -1;
                }
                strcat(strcat(sentence[i], " "), token);
                len = strlen(sentence[i]);
            }
            token = strtok(NULL, " ");
        }
        if(len > 0)
           i++;
    }

    for(int j = 0; j < i; j++) {
        printf("line[%d]: %s", j, sentence[j]);
    }

    for(int j = 0; j < i; j++) {
        free(sentence[j]);
    }
    free(sentence);
    fclose(fp);
    return 0;
}

The input and output:

$cat input.txt
Example 1 sentence
Example sentence number xd 595 xd 49 lol

./test

line[0]:  Example sentence                                                                                                                                  
line[1]:  Example sentence number xd xd lol

Upvotes: 1

Related Questions