• C

reading and modifying a file in C

Hi ,
I have a file of the following format

8366 , 6699 , 1
10520 , 5145 , 1
4503 , 7473 , 1
10365 , 9453 , 1

depending upon a certain condition i need to be able to
modify the third field i.e the "1" field and increment its value by 1 or 2 or whatever .


How should i read this file and modify the field (i.e. write the value back to the file ), i can use functions like fseek and ftell pos but i dont know exactly how to go about the whole process,


thanks
matu

matu007Asked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

shivsaCommented:

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
shivsaCommented:
/* This is outline, if u know more then get the idea and complete the code. */
/* This will change last charecter of a line in a file to 'a' */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
main(){
char ch;
FILE *fp;
long pos;

fp=fopen("exp.dat","r+");

fseek(fp,0,SEEK_SET);
while((ch = fgetc(fp))!='\n');

pos = ftell(fp);   /* now u got the position of last charecter in the line */

pos2 = pos -2; /* we have to go back 2 charecter, last one is \n and before that we have to replacement */
/* now u got the position of last charecter in the line */

/* code whatever condition u are checking  to increase by 1 or 2 */

fseek(fp,pos-2,SEEK_SET);
fputc('a',fp); /* I am changing the last charecter to a */
}
matu007Author Commented:
Can i get a solution for scrolling thriough the whole file , also it does not replace the last character but write an 'a' to the end after the last character.I tried "pos = pos-4" and then it works for one line replacing the '1' by an 'a' but i am not sure wether it will work for the other lines.IS it necessary that the newline character will be immediately next to the last character in the line??

By the way i have tried

int main(void)

{

    char ch;
    FILE *fp;
    long pos;
    long pos2;
   

    fp=fopen("new.doc","r+");
    fseek(fp,0,SEEK_SET);
   
      while(!feof(fp))    //Addition ??? IS this right
            {
               
             while((ch = fgetc(fp))!='\n');

                 pos = ftell(fp);  /* now u got the position of last charecter in the line */
                 pos2 = pos -2;    /* we have to go back 2 charecter, last one is \n and before that we have to replacement */
                 /* now u got the position of last charecter in the line */
       
                 /* code whatever condition u are checking  to increase by 1 or 2 */

                  fseek(fp,pos2,SEEK_SET);
                  fputc('a',fp);
            }
    return 0;
}
Determine the Perfect Price for Your IT Services

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden with our free interactive tool and use it to determine the right price for your IT services. Download your free eBook now!

sunnycoderCommented:
Hi matu007,

While it is possible to replace a char in the file with another one, it is not recommended for simple reason that if your replacement string is bigger in size than the original string, your useful data will get overwritten ... If you suspect that such a situation may arise, you should use a temporary file ...

char buffer[256];
char * temp;
infile = fopen ( "inputfile", "r" );
outfile = fopen ( "outfile", "w" );

while ( fgets ( buffer, 256, infile ) != NULL )
{
           temp = strrchr ( buffer, ',' ); /*locate the last , in the line*/
           temp = temp+2;              /* single blank space */
           * temp = 'x';     /* replace value with x or add chars or do whatever you like ... make sure that there is a end of string present*/
           fputs ( buffer, outfile );
}

fclose (infile);
fclose (outfile);

char buffer[256];
char * temp;
infile = fopen ( "inputfile", "r" );
outfile = fopen ( "outfile", "w" );

while ( fgets ( buffer, 256, infile ) != NULL )
{
           temp = buffer + strlen ( buffer );
           * temp = 'a'; /* make sure that there is a end of string present*/
           * (temp + 1) = '\n';
           * (temp + 2 ) = 0;
           fputs ( buffer, outfile );
}

fclose (infile);
fclose (outfile);
sunnycoderCommented:
the second code snippet appends an a to the end of each file
shivsaCommented:
here is complete solution.
----------------------------------
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

main(){
char ch;
FILE *fp;

long pos;
long i,j;
char tmp_str[8];

fp = fopen("/tmp/1","r+");

i=0;
while ((ch=fgetc(fp)) != EOF ) {
     i++;
     if(ch == '\n'){

          pos=ftell(fp);

          j=2;    /* u have to go back atleast 2 since fgetc move when it read one char, and we have encounter \n too */

          fseek(fp,(long)(i-j), SEEK_SET);

          while (i !=0 ){       /* go till u find a digit */
          if(!isdigit(ch=fgetc(fp))) {          /* check char if it digit backward starting from end of line*/
               j = j+1;
               fseek(fp,(long)(i-j), SEEK_SET);
          }
          else{          /* we got end digit */
               tmp_str[0]=ch;
               tmp_str[1]='\0';
               num = atoi(tmp_str);
               num = num +1;
               ch = (char)(num +48);    /* Ascii char are offset by 48 wrt num */
               fseek(fp,(long)(i-j), SEEK_SET);
               fputc(ch,fp);
               break;
          }
          }          
          fseek(fp,(long)(pos), SEEK_SET);
     }
         
}
}
sunnycoderCommented:
compare with this

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

int main ()
{
      char buffer[256];
      char * temp;
      FILE * infile, *outfile;

      infile = fopen ( "inputfile", "r" );     /* open the files */
      outfile = fopen ( "outputfile", "w" );

      while ( fgets ( buffer, 256, infile ) != NULL )    /* read in line by line */
      {
             temp = buffer + strlen ( buffer );        /* get length of line read and make temp point to the end  */
             * temp = 'a'; /* append a to buffer*/
             * (temp + 1) = '\n';  /* end the string properly */
             * (temp + 2 ) = 0;
             fputs ( buffer, outfile );
      }

      fclose (infile);
      fclose (outfile);
}
rstaveleyCommented:
Presumably you need to interpret the values to decide what to do with the 3rd field. Here's a skeleton for a program which takes input from STDIN and outputs to STDOUT. This tokenises the input expecting integers separated by commas and/or spaces and passes the integers to a doit function. You could put your logic into doit.

--------8<--------
/*
    Usage:
        ./a.out < inputfile > outputfile
 */

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

void doit(int,int,int,int);

int main()
{
int a,b,c,line = 0;
char buf[256],*cptr;
static char seps[] = ", "; /* Commas and spaces treated as separation between tokens */

/* Read line from input and interpret the tokens */

        while (fgets(buf,sizeof(buf),stdin)) {
                ++line;
                if (cptr = strtok(buf,seps)) {
                        a = atoi(cptr);
                        if (cptr = strtok(NULL,seps)) {
                                b = atoi(cptr);
                                if (cptr = strtok(NULL,seps)) {
                                        c = atoi(cptr);
                                        doit(line,a,b,c);
                                }
                        }
                }
        }
}

/* Function is passed the line number and the three integer fields from the input */
void doit(int line,int a,int b,int c)
{

/* Here's where you put your logic. I'm just going to
   increment c in my example. You might base your logic
   on line number or the values of a, b and c */

        c++;

/* Write revised integers to the output */

        fprintf(stdout,"%d , %d , %d\n",a,b,c);
}
--------8<--------
itchi-itchiCommented:
try this..
first store all the records in memory
then overwrite the file.


************************************************************

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

int main(){

  // first read the data file
  FILE *source;
  if((source = fopen("data.txt", "r")) == NULL)
    printf("Can't open file. Bad Filename.");

   char str_temp[50];
   int no_of_records=0;

   while(!feof(source)){
      fgets(str_temp, sizeof(str_temp), source);
       no_of_records++;
   } rewind(source);


   // allocate memory to store all records
   int **storage;
   if((storage = (int **) malloc(no_of_records * 3 * sizeof(int))) == NULL)
      printf("Not enough memory space.");
   for(int i=0; i<no_of_records; i++)
      storage[i] = (int *) malloc(3 * sizeof(int));


   // store records to array
   for(int i=0; i<no_of_records; i++){
      fscanf(source, "%d, %d, %d", &storage[i][0], &storage[i][1], storage[i][2]);
     
      // manipulate the last field
      storage[i][2]++;
   } fclose(source);


   // reopen the source to overwrite
   if((source = fopen("data.txt", "w")) == NULL)
         printf("File access denied.");

   for(int i=0; i<no_of_records; i++){
      fprintf(source, "%d, %d, %d", storage[i][0], storage[i][1], storage[i][2]);
      if(i != (no_of_records-1)) fprintf(source, "\n");
   }
   fclose(source);

free(storage);
}
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C

From novice to tech pro — start learning today.