Easiest way to read this line of text into a struct? - c

I have a text file with data in the form:
Lee AUS 2 103 2 62 TRUE
Check AUS 4 48 0 23 FALSE
Mills AUS 8 236 0 69 FALSE
I need to each line into a struct like, however I'd like to avoid using fixed length arrays (the problem with fgets as far as I can tell):
struct Data
{
char *sname;
char *country;
int *a;
int *b;
int *c;
int *d;
char *hsisno;
};
I am very new to C. Should I use fscanf, or fgets?

fscanf stands for "file scan formatted" and user data is about as unformatted as you can get.
You should never use naked "%s" format strings on data where you don't have absolute control over what can be read.
The best solution is to use fgets to read a line since this allows you to prevent buffer overflow.
Then, once you know the size of your line, that's the maximum size of each string that you will require. Use sscanf to your heart's content to get the actual fields.
One final thing. It's probably a bit wasteful having int* types for the integers, since you know they have a specific maximum size already. I'd use the non-pointer variant, something like:
struct Data {
char *sname; char *country;
int a; int b; int c; int d;
char *hsisno;
};
By way of example, here's some safe code:
#include <stdio.h>
#include <string.h>
// Here's all the stuff for a linked list of your nodes.
typedef struct sData {
char *sname; char *country; char *hsisno;
int a; int b; int c; int d;
struct sData *next;
} Data;
Data *first = NULL; Data *last = NULL;
#define MAXSZ 100
int main (void) {
char line[MAXSZ], sname[MAXSZ], country[MAXSZ], hsisno[MAXSZ];
int a, b, c, d;
FILE *fIn;
Data *node;
// Open the input file.
fIn = fopen ("file.in", "r");
if (fIn == NULL) {
printf ("Cannot open file\n");
return 1;
}
// Process every line.
while (fgets (line, sizeof(line), fIn) != NULL) {
// Check line for various problems (too short, too long).
if (line[0] == '\0') {
printf ("Line too short\n");
return 1;
}
if (line[strlen (line)-1] != '\n') {
printf ("Line starting with '%s' is too long\n", line);
return 1;
}
line[strlen (line)-1] = '\0';
// Scan the individual fields.
if (sscanf (line, "%s %s %d %d %d %d %s",
sname, country, &a, &b, &c, &d, hsisno) != 7)
{
printf ("Line '%s' didn't scan properly\n", line);
return 1;
}
// Allocate a new node to hold data.
node = malloc (sizeof (Data));
if (node == NULL) {
printf ("Ran out of memory\n");
return 1;
}
node->sname = strdup (sname);
node->country = strdup (country);
node->a = a;
node->b = b;
node->c = c;
node->d = d;
node->hsisno = strdup (hsisno);
node->next = NULL;
if (first != NULL) {
last->next = node;
last = node;
} else {
first = node;
last = node;
}
}
fclose (fIn);
// Output the list for debugging.
node = first;
while (node != NULL) {
printf ("'%s' '%s' %d %d %d %d '%s'\n",
node->sname, node->country, node->a, node->b,
node->c, node->d, node->hsisno);
node = node->next;
}
return 0;
}
which reads in your file and stores it in a linked list. It outputs:
'Lee' 'AUS' 2 103 2 62 'TRUE'
'Check' 'AUS' 4 48 0 23 'FALSE'
'Mills' 'AUS' 8 236 0 69 'FALSE'
at the end, as expected.
I've done a whole series of answers on the pitfalls of using *scanf functions on non-controlled data (enter user:14860 fgets into the search box above), some of which (here, here and here, for example) include a perennial favourite function of mine, getLine, for safer user input.

Related

Read txt file line by line in C

I want to read a txt file, line by line, and each line stores in a different variable:
here is the txt file I want to read
Jenny
Woodbridge Ave
Amber
Exeter street
Michael
Main Street
David
Plainfield ave
and I did like
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<string.h>
typedef struct info
{
char name[20];
char add[50];
}INFO;
int main(void){
const char *fileName = "test.txt";
FILE *file = fopen(fileName, "r");
INFO* list = (INFO*)malloc(20*sizeof(INFO));
readFromFile(file,list);
fclose(file);
free(list);
return 0;
}
void readFromFile(FILE *file,INFO* list){
int i = 0;
while(!feof(file)){
fscanf(file,"%s %s\n ",(list+i)->name,(list+i)->adds);
i++;
}
}
but I getting
Name: Jenny
Addr: Woodbridge
------------------------------
Name: Ave
Addr: Amber
------------------------------
Name: Exeter
Addr: street
------------------------------
Name: Michael
Addr: Main
------------------------------
Name: Street
Addr: David
------------------------------
Name: Plainfield
Addr: ave
I just edited a little bit
so I need to use fgets to read line by line instead of fscanf() right?
%s specifier reads the input stream until it finds a blank character, in your case as you have 2 words per address, it becomes umbalanced as soon as you try to read it, the second word of the address is read by the next cycle into name, it also has a problem of potencial buffer overflow.
You should use %49[^\n], this specifier reads everything until it finds the newline character, including spaces. The 49 is meant to limit the size of the read line as to avoid the mentioned buffer overflow, in you case you have space for 50 characters, the last character would be for the null terminator.
feof is also not the best way to signal the end of file in this kind of routine, more info in Why is “while ( !feof (file) )” always wrong?.
There are some other issues I address in the comments on the below working sample:
Online demo
int main()
{
//casting malloc may make you program fail, it hides the lack of #include <stdlib.h>
INFO* list = malloc(20 * sizeof *list); //using the the dereferenced variable
//is safer regarding future code refactoring
const char *fileName = "test.txt";
FILE *f = fopen(fileName, "r"); //dont forget to verify the return of fopen
int i = read(f, list);
for (int j = 0; j < i; j++) //test print
{
printf("Name: %s Address: %s\n", list[j].name, list[j].add);
}
}
int read(FILE *file, INFO *list)
{
int i = 0;
//use scanf as stop condition, [] notation is easier to read
//limiting the size in scanf specifiers avoids buffer overflow
while (fscanf(file, "%19s %49[^\n]", list[i].name, list[i].add) == 2)
{
i++;
}
//return i so that you know how many structs were read
return i;
}
Output:
Name: Jenny Address: Woodbridge Ave
Name: Amber Address: Exeter street
Name: Michael Address: Main Street
Name: David Address: Plainfield ave
so I need to use fgets to read line by line instead of fscanf() right?
fscanf(file,"%s %s\n ",.... fails as %s does not read spaces into a string as needed by "Woodbridge Ave" and fails to protect against buffer overrun.
There are many way to solve this task. fgets() is the most clear.
Consider a helper function to read a line and handle fgets() peculiarities of line input. Adjust as needed.
// return 1 on success
// return EOF on end-of-file/input error
// else return 0
int read_line(FILE *file, int sz, char *line) {
if (fgets(line, sz, file) == NULL) {
return EOF; // EOF or rare input error
}
int len = strlen(line);
if (len > 0 && line[len - 1] == '\n') {
line[--len] = '\0'; // lop off potential \n
} else if (len + 1 == sz) { // no \n read, `line` full, so look for rest of input
int ch;
int extra = 0;
while ((ch = fgetc(file)) != '\n' && ch != EOF) {
extra = 1;
}
if (extra) {
return 0; // input too long
}
}
return 1;
}
Now read the file in line pairs into a INFO
int read_INFO(FILE *file, int n, INFO *list) {
int i = 0;
while (i < n
&& read_line(file, sizeof list->name, list[i].name) == 1
&& read_line(file, sizeof list->add, list[i].add) == 1) {
i++;
}
return i;
}
Usage
int n = 20;
INFO *list = malloc(sizeof *list * n);
if (list) {
int number_read = read_INFO(file, n, list);
if (number_read > 0) {
// The happy path
}
}

fscanf from text file to struct pointer

I'm trying to read from a text file to a struct that has a pointer to another struct.
The text file has the following format:
279288151 1 John Doe
002 1 30 04 2018
23189842 0 Jane Doe
0
282676381 1 Mark Examp
001 0 28 03 2018 03 04 2018
243897574 1 Joe Soap
003 2 14 04 2018 21 04 2018
This is my .h file:
#ifndef Clientes_h
#define Clientes_h
#include <stdio.h>
#include <stdlib.h>
#include "Alugueres.h"
#define ST_TAM 50
typedef struct info_cliente Cliente;
struct info_cliente{
char nome[ST_TAM];
long nif;
int n_alugueres;
int n_hist;
pAluga aluguer;
};
typedef struct aluga Aluguer, *pAluga;
typedef struct data DataIn, *pDataIn;
typedef struct data DaraEn, *pDataEn;
struct aluga{
int id_unico;
int estado;
pDataIn dataIn;
pDataEn dataEn;
pAluga prox;
};
struct data{
int dia;
int mes;
int ano;
};
Cliente* le_fich(char *nome, int *n);
#endif /* Clientes_h */
And my read_file func is as follows:
#include "Clientes.h"
Cliente* le_fich(char *nome, int *n){
FILE *f = fopen(nome, "r");
Cliente *aux;
int conta = 0;
if(!f){
printf("Error\n");
return NULL;
}
while(getc(f) != EOF){
aux = (Cliente*)malloc(sizeof(Cliente));
fscanf(f, "%ld %d %49[^\n]", &aux[conta].nif, &aux[conta].n_alugueres, aux[conta].nome);
if(aux[conta].n_alugueres != 0){
fscanf(f, "%d %d %d %d %d", &aux[conta].aluguer->id_unico,
&aux[conta].aluguer->estado, &aux[conta].aluguer->dataIn->dia,
&aux[conta].aluguer->dataIn->mes, &aux[conta].aluguer->dataIn->ano);
}
conta++;
}
return aux;
}
It gives me a bad_access error when trying to run the fscanf after the if is successful (when accessing the pointer of the struct for my date). If anyone could help me out, would really appreciate it.
Right now you allocating memory for aux in the loop and then try to access an element using an index which will not work. Instead you need to allocate memory for all Cliente records. If you know the number of records in the file you could simply do aux = (Cliente*)malloc(size * sizeof(Cliente));. You might also check on how you can use realloc() in the actual loop.
It gives me a bad_access error when trying to run the fscanf after the if is successful
2 problems:
As #Rishikesh Raje, #Cyclonecode pointed out, the allocation is only good for aux = aux[0] as well as other missing allocations.
The usual suspect to scanning problems are that the fscanf() did not scan what was expected and code lacked checks of the return value. (Hint: when line is only "0\n", the 2nd fscanf() reads more than OP expected.)
ret = fscanf(f, "%ld %d %49[^\n]", ...);
if((ret ==3) && (aux[conta].n_alugueres != 0)){
fscanf(f, "%d %d %d %d %d", ...
// code errantly does not check the return value of `fscanf()`.
}
else {
break; // This code missing, what to do when `ret != 3`
}
A simply solution to both problems to (re)allocate as needed and check success of reading 2 lines and scanning them.
I recommend to not allocate data for the new pair of lines until the input have been validated.
Cliente *aux = NULL; // Initialize to NULL
size_t n = 0; // Keep count of record count
char buf1[150]; // Use generous buffers. Suggest 2x maximum expected need
char buf2[100];
// while 2 lines successfully read
while (fgets(buf1, sizeof buf1, f) && fgets(buf2, sizeof buf2, f)) {
// Form objects to be scanned into with default values.
struct info_cliente cli = { 0 };
struct aluga alu = { 0 };
struct data dat = { 0 };
if (sscanf(buf1, "%ld %d %49[^\n]", &cli.nif, &cli.n_alugueres, cli.nome) != 3) {
perror("Unexpected 1st line");
break;
}
if (cli.n_alugueres == 0) {
if (sscanf(buf2, "%d", &alu.id_unico) != 1 || alu.id_unico != 0)) {
perror("Unexpected 2nd line 0");
break;
}
}
else if (cli.n_alugueres == 1) {
if (sscanf(buf2, "%d %d %d %d %d", &alu.id_unico, &alu.estado, &dat.dia,
&dat.mes, &dat.ano) != 5) {
perror("Unexpected 2nd line");
break;
}
alu.dataIn = malloc(sizeof *alu.dataIn);
*alu.dataIn = dat;
cli.aluguer = malloc(sizeof *cli.aluguer);
*cli.aluguer = alu;
} else {
perror("Unexpected 2nd line n_alugueres");
break;
}
Cliente *tmp = realloc(aux, sizeof *aux * (n+1));
aux = tmp;
aux[n] = cli;
n++;
}
Cliente *tmp = realloc(aux, sizeof *aux * (n+1));
aux = tmp;
aux[n] = NULL; // NULL terminate the list
Note Error checking on malloc()/realloc() omitted for brevity on the above sample code.
You are using both getc and fscanf to access the file.
If you want to use fscanf, you should not use getc.
Use the return value of fscanf to let you know when the file has ended. fscanf will return the number of items matched. In your case if successful it should return 3.
int ret;
do{
aux = (Cliente*)malloc(sizeof(Cliente));
ret = fscanf(f, "%ld %d %49[^\n]", &aux[conta].nif, &aux[conta].n_alugueres, aux[conta].nome);
if((ret ==3) && (aux[conta].n_alugueres != 0)){
fscanf(f, "%d %d %d %d %d", &aux[conta].aluguer->id_unico,
&aux[conta].aluguer->estado, &aux[conta].aluguer->dataIn->dia,
&aux[conta].aluguer->dataIn->mes, &aux[conta].aluguer->dataIn->ano);
}
conta++;
}while (ret == 3);

Console stuck at reading file and filter number of data characters

I didn't have any error when running the codes below. But on the command console it seems to be stuck on Processing filename xxxxx as below.
May I ask how do I use if condition to filter out number of data characters of less than 50 in line 67, I try to use strlen(array[count].data) >= 1 && strlen(array[count].data) <= 50 but doesn't seem to work ?
Enter filename: testdata.txt
Processing filename testdata.txt ...
Sample Source txt file:
9001:0002:9003:0021:CLS
0001:0010:0003:0021:CLS
8001:0002:8002:0080:<HTML>
0001:4002:0002:0080:<BODY>
0004:0002:0002:0080:JHJKJBKHJBIUHBKBKHBKHHBKJBKJNKJKHHKUHKJLHBKHBKHBHBHBKHBHBHBHBBHHBHBJKJHKJHKJHKUHIUJ
Source code:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
//struct definition
struct record{
int src;
int dest;
int type;
int port;
char data[100];
};
int main()
{
struct record *array;
FILE* inFile; //file handle or pointer
FILE* outFile;
FILE* errorFile;
char filename[100];
int count = 0; //keep track of number of records in memory
int i = 0;
int test;
int n1 = 0; //keep track number of correct records
int n2 = 0; //keep track number of error records
array = (struct record *) malloc(sizeof(struct record));
//User to enter filename
printf("Enter filename: ");
scanf("%s", filename);
printf("Processing filename %s ...\n", filename);
inFile = fopen(filename, "r");
if (inFile == NULL) //check if file handler is invalid
{
printf("Could not open file %s\n", filename);
exit(1); //error status code
}
test = fscanf(inFile, "%d:%d:%d:%d",
&array[count].src, &array[count].dest, &array[count].type, &array[count].port);
fgets(array[count].data, 100, inFile);
while (test != EOF){
count++;
array = (struct record *) realloc(array, (count + 1)*sizeof(struct record));
test = fscanf(inFile, "%d:%d:%d:%d:%s",
&array[count].src, &array[count].dest, &array[count].type, &array[count].port, &array[count].data);
}
fclose(inFile); //must always close file once done
outFile = fopen("data_1.txt", "wt");
errorFile = fopen("data_error.txt", "wt");
if (outFile == NULL) //check if file handler is invalid
{
printf("Could not write to file \n", filename);
exit(1);
}
if (count > 0){
printf("Viewing all records: ", count);
for (i = 0; i < count; i++){
if (array[count].src >= 1 && array[count].src <= 1024 && array[count].dest >= 1 && array[count].dest <= 1024 && array[count].type >= 1 && array[count].type <= 10 && array[count].port >= 1 && array[count].port <= 1024)
n1++;
fprintf(outFile, "%d %d %d %d",
(i + 1),
array[count].src,
array[count].dest,
array[count].type,
array[count].port
);
}
}
else
{
n2++;
fprintf(errorFile, "%d %d %d %d",
(i + 1),
array[count].src,
array[count].dest,
array[count].type,
array[count].port
);
}
fclose(errorFile);
fclose(outFile);
return 0;
}
There are many common errors in this. Which book are you reading?
array = (struct record *) malloc(sizeof(struct record));
test = fscanf(inFile, "%d:%d:%d:%d",
&array[count].src, &array[count].dest, &array[count].type, &array[count].port);
fgets(array[count].data, 100, inFile);
while (test != EOF){
count++;
array = (struct record *) realloc(array, (count + 1)*sizeof(struct record));
test = fscanf(inFile, "%d:%d:%d:%d:%s", &array[count].src, &array[count].dest
, &array[count].type, &array[count].port
, &array[count].data);
}
Forgive me. I took the liberty to clean up a bit of your code and condense some of the logic.
You shouldn't cast the return value of malloc or realloc.
While I'm on the topic of types, isn't your compiler warning you about the type of &array[count].data being incompatible with the type that corresponds to %s? Don't cast it. Just remove the & and recognise how the expression array[count].data that denotes an array is converted to a pointer of the appropriate type.
x = realloc(x, ...); where x is whatever expression is (almost) always incorrect. You need to use a temporary variable so you can handle errors correctly without leaking memory (example below)... While I'm on the topic of realloc usage, the first argument can be NULL and realloc will act like malloc in that case, so technically that first malloc is unnecessary bloat...
struct record *array = NULL;
void *temp = realloc(array, (count + 1) * sizeof *array);
if (!temp) {
puts("ERROR ALLOCATING MEMORY!");
exit(EXIT_FAILURE);
}
array = temp;
Have you considered the difference between fgets and fscanf("%s", ...)? Are you aware that the former is for reading lines, while the latter is for reading words? This would explain your problem; fscanf is halting when it sees a space, leaving everything after the space to be processed by the next fscanf call. The result? An infinite loop of fscanf fails.
Have you considered that not all fscanf fails return EOF? If you ask fscanf to read an int (using %d) and it immediately encounters non-decimal digits it can't proceed any further; a conversion failure occurs.
If you want to ensure that fscanf reads all 5 fields successfully, you need to compare the return value to 5, not to EOF.
I think you most likely meant to read the remainder of the line following your four colon-separated ints, and here's how I'd naively do that:
array = NULL;
struct record record;
while (fscanf(inFile, "%d:%d:%d:%d:%99[^\n]", &record.src, &record.dest
, &record.type, &record.port
, record.data) == 5) {
/* It's possible that a user might enter more than *
* 99 chars for the last field, so when that happens *
* we should discard the remainder... */
if (getchar() != '\n') {
puts("WARNING: Maximum field length for data is 99; user input truncated");
fscanf(inFile, "%*[^\n]");
}
void *temp = realloc(array, (count + 1) * sizeof *array);
if (!temp) {
puts("ERROR ALLOCATING MEMORY!");
exit(EXIT_FAILURE);
}
array = temp;
array[count++] = record;
}

Reading text into a linked list using structs in C

I'm attempting to create a linked list using a struct from a txt file. Initially, I'm testing it with a txt file with only one line of information. This code compiles correctly, however when I run it, it returns "Line...didn't scan properly". As an aside, if I remove the if statement that returns such a value I get complete gibberish. I have no clue why the line isn't being scanned correctly, however I feel as though it may having something to do with the hyphen/plus sign in two of the terms that I tried to scan as strings. Thank you very much for any help you can provide.
This is the txt file:
1 20959U 90103A 14091.58762725 -.00000015 00000-0 00000+0 0 3197
This is the tester.c file:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct noradData {
// line one
int lineNum;
char * satNum;
char * intDesig;
float epoch;
float firstTimeDeriv;
char * secondTimeDeriv;
char * drag;
int zero;
int set;
struct noradData * next;
} Data;
Data * first = NULL, * last = NULL;
int main() {
char line[80], secondTimeDeriv[7], drag[7], satNum[6], intDesig[6];
int lineNum, zero, set;
float epoch, firstTimeDeriv;
FILE * fIn;
Data * node;
fIn = fopen("data1.txt", "r");
if (fIn == NULL) {
printf("Cannot open file\n");
return 1;
}
while (fgets(line, sizeof(line), fIn) != NULL) {
// Check line for various problems (too short, too long).
if (line[0] == '\0') {
printf ("Line too short\n");
return 1;
}
if (line[strlen (line)-1] != '\n') {
printf ("Line starting with '%s' is too long\n", line);
return 1;
}
line[strlen (line)-1] = '\0';
// Scan the individual fields.
if (scanf("%d %s %s %f %f %s %s %d %d", &lineNum, satNum, intDesig,
&epoch, &firstTimeDeriv, secondTimeDeriv, drag, &zero, &set)
!= 9) {
printf ("Line '%s' didn't scan properly\n", line);
return 1;
}
node = malloc(sizeof(Data));
if (node == NULL) {
printf ("Ran out of memory\n");
return 1;
}
node->lineNum = lineNum;
node->satNum = strdup(satNum);
node->intDesig = strdup (intDesig);
node->epoch = epoch;
node->firstTimeDeriv = firstTimeDeriv;
node->secondTimeDeriv = strdup(secondTimeDeriv);
node->drag = strdup(drag);
node->zero = zero;
node->set = set;
node->next = NULL;
if (first != NULL) {
last->next = node;
last = node;
}
else {
first = node;
last = node;
}
}
fclose (fIn);
node = first;
while (node != NULL) {
printf("%d %s %s %f %f %s %s %d %d", node->lineNum, node->satNum,
node->intDesig, node->epoch, node->firstTimeDeriv,
node->secondTimeDeriv, node->drag, node->zero, node->set);
node = node->next;
}
return 0;
}
First of all change size of character arrays satnum and intdDesig to 7
that is satnum[7] and intDesig[7]. You want to store 6 characters in these leave last index for null value.
if (line[strlen (line)-1] != '\n') {
printf ("Line starting with '%s' is too long\n", line);
return 1;
}
This if statement instead of line[strlen(line)-1]!='\n' put this-
line[strlen(line)-1]=='\n'
and statement goes like this
if (line[strlen (line)-1]=='\n') {
printf ("Line starting with '%s' is too long\n", line);
return 1;
}
And remove this line
line[strlen (line)-1] = '\0';
Then line will not be returned twice .

C - Parsing an input file into lines and characters

I am trying to write a C program to parse an input file so that individual lines are parsed, and in each line, the individual characters are then parsed further and stored in different variables in a struct. Here is my code so far (I have managed to parse individual characters without considering which line they are on):
/* create struct instances */
/* file open code */
...
int currentChar = fscanf(fp, "%s", storageArray);
while (currentChar != EOF) {
printf("%s\n", storageArray);
currentChar = fscanf(fp, "%s", storageArray);
}
...
/* file close code */
How can I adapt my code so that, instead of having each individual character print to the screen, I get behaviour like the following: (Note: in my program I assume the user input will have three characters to a line.)
INPUT FILE:
a b c
f e d
LINE STRUCT 1:
char1 = a
char2 = b
char3 = c
LINE STRUCT 2:
char1 = f
char2 = e
char3 = d
I feel like the solution might involve nested loops similar to the while I have written, where the outer one keeps track of lines and the inner one keeps track of characters.
Or try this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define READ_OPTIONS "r"
struct line {
char char1;
char char2;
char char3;
struct line* next;
};
struct line* g_lines = NULL;
int main(int argc, char** argv) {
char buf[8] = {0};
struct line* newline, *iter, *head;
int counter = 1;
FILE* fp = fopen("file.txt", READ_OPTIONS);
if(NULL != fp) {
while(fgets(buf, 8, fp)) {
newline = malloc(sizeof(struct line));
if(NULL != newline) {
memset(newline, 0, sizeof(struct line));
sscanf(buf, "%c %c %c",
&newline->char1,
&newline->char2,
&newline->char3);
if(NULL != g_lines) {
for(iter = g_lines;
NULL != iter->next;
iter = iter->next);
iter->next = newline;
} else g_lines = newline;
}
}
fclose(fp);
} else return -1;
/* print the contents */
for(iter = g_lines;
NULL != iter;
iter = iter->next,
++counter)
printf("Line %d: char1=%c char2=%c char3=%c\n",
counter, iter->char1, iter->char2,
iter->char3);
/*
now to free memory before returning
control to the operating system
*/
for(iter = g_lines;
NULL != iter;)
{
head = iter->next;
free(iter);
iter = head;
}
return 0;
}
Try This
int i=1,j-1;
printf("Line STRUCT 1: ");
while( ( ch = fgetc(fp) ) != EOF ){
if(ch=='\n'){
printf("Line STRUCT %d \n",++i);
j=1;
}
printf("Char %d = %c \n",ch,j++);
}
Do this:
for (int i=0; !feof(fp); i++)
fscanf(fp,"%c %c %c ",
&storageArray[i].char1,
&storageArray[i].char2,
&storageArray[i].char3);

Resources