Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Hello! I want to read a file wit

Status
Not open for further replies.

SLider3

Programmer
Jun 17, 2003
56
PT
Hello!

I want to read a file with a specific text format to a struct (or array of structs...) and than write it to a new file.

The text format of the file is:
{int}{int}string\n

Some example lines:
{12}{34}The text i want
{56}{105}More and more text


This is parte of my code:

typedef struct
{
int num1;
int num2;
char text[100];
} Format;

while(!f_in)
{
fscanf(f_in,"{%d}{%d}%[^\n]\n", &Format->num1, &Format->num2, Format->text);
// then i change the num1 and num2
fprintf(f_out,"{%d}{%d}%s\n",Format->num1,Format->num1,Format->text);
}

Using this code i have a big problem: when i declare char text[100] i´m puting the limit in 100 char but i don´t want the text has a limit. What sould i do?

Other thing...instead of read a line change the numbers and then write the line in the other file i want to read all the lines of the input file to a array of structs (struct like the one i define above). But here i bave other problem, how can i defien a array o structs with no limit (because i don't know the number of lines th file has). What you sugest?

If you have any other sugestion to read the file and get the imformation it has (i heard fscanf is not very good) please tell me.
 
Dynamic memory allocation.
Use malloc, realloc, et.al..

Declare your character string variable as a
pointer.
Code:
typedef struct
     {
             int num1;
             int num2;
             char *text;
     } Format;

Then use fgetc(),fseek() and ftell() to read and reset
once you fgetc '\n' in a line, using your own function that
returns number of chars per line.

You then malloc the returned value * sizeof(char),
fgets() or fscanf() the line, terminate the string
and continue till your function returns indicator of
eof.

In the meantime you are using either a linked list
or a resizeable array of your struct. I suggest a
linked list but you can also use realloc() with an
array of structs. Using an array you will have to keep
track of each record read of course.

If you were hoping for an example...Well that's a bit
of work for free, sorry.
 
You can open the file in binary mode.
Let's suppose that f is a FILE pointer to your opened file.
You can read the numbers with the following:
Code:
#define MAX 100
char paranthesis, digit, characters[MAX], character;
int nr1, nr2;

  fread(& paranthesis, sizeof(char), 1, f);//you can test this to see if it returns 0, then you are at the end of the file
  nr1=0;
  while(1){
     fread(&digit, sizeof(char), 1, f);
     if( digit != '}' ){
        nr1 *= 10;
        nr1 += (digit - '0');        
     }
     else break;         
  }
[\code]
Call this code twice for your numbers.
To read the unknown size string you can use this code, but remember that I did not test it. You should see if there are syntactic mistakes etc.
[code]
char *text = NULL;
int length = 0, final_length = 0;

   while(1){
     length = 0;
     while(1){
         fread(&character, sizeof(char), 1, f);
         if(character != '\n'){
            characters[length++] = character;
            if(length == MAX) break;
         }
         else{
            characters[length++] = 0;
            break;
         }
     }
     if(length == MAX){
        if(text == NULL){
           text = (char*)calloc(sizeof(char), MAX);
           memcpy(text, characters, MAX);
           final_length = MAX;
        }
        else{
           final_length += MAX;
           text = (char*)realloc(text, sizeof(char) * final_length);
           memcpy(text+final_length-MAX, characters, MAX);
        }
     }
     else{
        final_length += length;
        text = (char*)realloc(text, sizeof(char)*final_length);
        memcpy(text+final_length-length, characters, length);
        break; 
     }
 
   }
[\code]

You should use the structure that marsd proposed. I think you can improve the algorithm, so you read more than one character at a time.

Hope it helps, 
  Liviu.
 
@TintaLiviu
thanks for your help

@marsd
You have suggested the use of fetll to tell the position of '\n' (which indicates the end of line) but now i have other text format and i want to know what you suggest.

The file has text structure:

num1 --> num2
string\n
string\n
(i don't know how many strings i have but i know they stop when i get a white line)


Look to this exampple:
100 --> 200
the text
i want

300 --> 400
something

500 --> 600
more text
and more...


Can you help me?
 
So each block is delimited by \n on it's own line, right?

As far as the first line goes. fscanf() will handle
this. Just use a set size buffer for the --> string,
and read the man page thoroughly for options to the
format string which should be useful.

To separate blocks:
In your reading function use a conditional that checks
for \n as first char read. Return an value indicating that
the block/record has ended.

Meanwhile you have been using strcat() or analagous
function to combine your record *text variable for each
text line in the block after the first.

After block end you record the data to your struct
for that record, increment the record count, and move to
the next.

Here's how it might look
Code:
  while ( (val = myfuncname(fd)) > 0) {
          switch (val) {
                  case 1: 
                       /*new record for array of structs
                       plus read first line*/
                       newrecord[a++] = allocNew();
                       fscanf(fd,formatstr,pointers);
                       newrecord[a]->int1 = intptr1;
                       newrecord[a]->int2 = intptr2;
                       break;
                   
                   case 2:
                        /*First text line*/
                        v = readline(fd);
                        line1 = malloc((v + 1) * sizeof(char));
                        fgets(line1,(v + 1),fd);
                        line1[(v + 1)] = '\0';
                        break;
 
                   case 3:
                        /*second text line:: as above*/
                        newrecord[a]->text = combine(line1,line2);
                        free(line1);
                        free(line2);
                        break;
                   
          }
   }
          puts("Read eof\n");
          do_something_with_array(newrecord);
          freeall(newrecord);
return 0;
}



 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top