Hi there,
I need to make a piece of code in C that
1. opens a specified file,
2. Reads the data in the file and separates it as shown below,
3. Converts the strings into integers and then perfoms some manipulation on them,
4. returns the new values to a second text file (possibly, not quite sure on this one yet).
My data is given in the following format (there is one space between a1 and b1, b1 and c1, etc.):
x
y
a1 b1 c1 d1 e1 f1
a2 b2 c2 d2 e2 f2
while not EOF
I would like to read in data in the following format for further processing:
x
y
a b c d e f
a[i+1] b[i+1] c[i+1] d[i+1] e[i+1] f[i+1]
I guess I need to read it in as an array and then do some sort of concatenation/speration (my inputs can be one or two digits, i.e. a can be 0 or 99). This is probably not very difficult, but I haven't touched C in about 6-7 years. It must be done in C (no C++ or C#). I tried to search, but couldn't find my case (maybe it was posted before and I just did not see it).

Please give me some hints. Timewise, I should be able to have it working ASAP.

Thank You very much.

Dani AI

Generated

The file layout is simple: two header lines (x and y) followed by any number of data lines, each containing exactly six integers (0..99) separated by single spaces. Dynamic allocation is required because the number of data rows is unknown. Following 's suggestion to avoid fixed-size stacks, a robust pattern is to read the file line-by-line, parse six tokens with strtol (safer than raw scanf), and append each parsed row into one contiguous array that grows with realloc. A contiguous buffer makes indexing and later output simple and it is far faster and less error-prone than many small malloc calls for each row.

Example parsing sketch (conceptual, not a drop-in program):

/* read x and y from first two lines, then parse remaining lines of 6 ints */
FILE *fp = fopen("data.txt","r");
char buf[256], *end;
fgets(buf,sizeof buf,fp);
long x = strtol(buf,&end,10); /* validate end != buf */
fgets(buf,sizeof buf,fp);
long y = strtol(buf,&end,10);

/* dynamic flat storage: rows * 6 */
size_t cap = 64, rows = 0;
int *data = malloc(cap * 6 * sizeof *data);

while (fgets(buf,sizeof buf,fp)) {
  int vals[6];
  char *p = buf;
  for (int i=0;i<6;i++) {
    long v = strtol(p,&end,10);
    if (p==end) { /* malformed line -> handle or skip */ break; }
    vals[i] = (int)v;
    p = end;
  }
  if (rows == cap) { cap *= 2; data = realloc(data, cap * 6 * sizeof *data); }
  memcpy(data + rows*6, vals, 6 * sizeof *data);
  rows++;
}

Practical notes: always check fopen, fgets, strtol endptr and errno for overflow, and realloc return. Trim CR/LF and skip blank lines. Using fgets + strtol avoids the fread/fscanf confusion that hit and gives clear per-line error handling. For output, loop rows and fprintf the six ints per line (or write binary if needed). The flat-array approach keeps memory management simple and gives O(1) access to row i via index (i * 6 + j).

Recommended Answers

All 7 Replies

not clear what a1 b1 c1 ... represents.

not clear what a1 b1 c1 ... represents.

a1 b1 c1 are integers, which can vary between 0 and 99.

first, create the arrays of appropriate size. If you know the number of rows and columns in the file it will make it a lot easier. But if you don't (and normally you will not) then you will just have to dynamically allocate them with malloc().

Easiest way is to put it into one large array

// array to be allocated
int *array = 0;
int x = 0;
int y = 0;

// open the file for reading
FILE* fp = fopen("file","r");
// read x and y
fscanf(fp,"%d", &x);
fscanf(fp,"%d", &y);

// allocate the array
array = (int *)malloc(y * x * sizeof(int));

// read the data into the arra
int i = 0;
int maxi = x * y;
for(i = 0; i < maxi && fscanf(fp,"%d", array[i]) > 0; i++)
         ;
fclose(fp);

// now you can calculate the location of any x,y cell by this simple formula

int row = 5; // desired row
int col = 3;  // desired column
int cell = (<desired row number>-1) * <columns per row> ) + (<desired column number>)
or
cell = ((row-1) * x) + col;

Thanks Ancient Dragon,

I probably was not very clear on the task, so here are clarifications:
- x & y have no impact on the # of rows and columns
-I do not know the number of rows in the file and the number of rows will vary from file to file
-there are always 6 elements in a row (or line), but number of digits in each element can be 1 or 2 (i.e. a1 can vary from 0 to 99); the elements (columns) are separated by one space
-I would like to sort data into array as speficied in original post, I believe it will make the analysis better: I can just increment I to perform manipulations with the next row of data.

Thanks again.

so use realloc() to expand the 2d array to the desired size. Something like this untested code

// allocate first row
int **array = malloc( sizeof(int*) );
// allocate 6 columns
array[0] = malloc( 6 * sizeof(int));
int numRows = 0;
int n;
int row = 0;
int col = 0;
while( fread(fp,"%d", &n) > 0)
{
    if( col < 6)
    {
       array[row][col] = n;
       ++col;
    }
    else
    {
       ++row;
       array = realloc(array,row * sizeof(int*));
       array[row] = malloc( 6 * sizeof(int));
       col = 0;
       array[row][col] = n;
       ++col;
     }
 }

Getting the following error:

Error c:\lcc\projects\reading\reading.c: 23 type error in argument 2 to `fread'; found 'pointer to char' expected 'unsigned int'
Error c:\lcc\projects\reading\reading.c: 23 type error in argument 3 to `fread'; found 'pointer to int' expected 'unsigned int'
Error c:\lcc\projects\reading\reading.c: 23 insufficient number of arguments to `fread'

for the following line: while( fread(fp,"%d", &n) > 0)

I got it, you meant fscanf innstead of fread. It works. Thank you very much, Ancient Dragon.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.