So many problems and misconceptions; it is hard to provide useful advice.
As I understand it, you are meant to be reading the dimensions of a series of matrices with two numbers per line of input, and the second number in line N should be the same as the first number in line N+1. You don't know until you reach EOF how many lines of input there will be. Generally, the numbers should all be one or two digits (not longer). The actual data for the arrays is stored elsewhere, or generated — it is not handled in this code.
Your code is:
int *p,i=0;
char str[3],*extra;
FILE * file;
file = fopen("D:/Dump/testcases/matrix.txt", "r");
if (file) {
while (fscanf(file, "%s", str)!=EOF){
switch(i){
case 0: p=(int *)malloc(sizeof(int));
*(p)=atoi(str);
break;
default: *(p+i)=(int)malloc(sizeof(int));
*(p+i)=atoi(str);
break;
}
i++;
}
}
- The file opening is OK; you don't show the close, but that's a minor issue.
- You don't limit the size of the string that is read; you could use
%2s to ensure you do not overflow the (rather short) string you use.
- You don't check that
fscanf() actually read 1 item. With a character string, that's OK. If you were reading integers directly, that would not be OK. You could get 0 integers converted, which is neither EOF nor 1. You should be using while (fscanf(file, "%2s", str) == 1).
- There's no very obvious reason not to have
fscanf() do the conversion for you.
- OTOH, you cannot force
fscanf() to require two numbers (only) on a single line either; it will be happy to have all the numbers on a single line, or each number on a line on its own with 2 blank lines between each line containing numbers.
The switch is a bit odd. The default clause should probably be using realloc() rather than malloc(), and the cast in the default is seriously problematic. The memory allocation scheme as a whole is very flawed, which you knew because you asked the question. You could just about rescue it by writing:
default:
p = (int *)realloc(p, (i+1) * sizeof(int));
p[i] = atoi(str); /* Or *(p+i) if you prefer */
break;
Overall, I think you need to think in terms of reading a line at a time (fgets()), then parsing the lines with sscanf(). You should probably think in terms of allocating the array two integers at a time.
int *p = 0;
int i = 0;
FILE *file = fopen("D:/Dump/testcases/matrix.txt", "r");
if (file != 0)
{
char buffer[4096];
while (fgets(buffer, sizeof(buffer), file) != 0)
{
int d1, d2;
char c;
if (sscanf(buffer, "%d%d%c", &d1, &d2, &c) != 3 || c != '\n')
{
fprintf(stderr, "Badly formatted line: %s", buffer);
break;
}
void *space;
if (i == 0)
space = malloc(2 * (i + 1) * sizeof(int));
else
space = realloc(p, 2 * (i + 1) * sizeof(int));
if (space == 0)
{
fprintf(stderr, "Memory allocation failed (%d bytes)\n", 2 * (i + 1) * sizeof(int));
break;
}
p = (int *)space;
p[2*i + 0] = d1;
p[2*i + 1] = d2;
i++;
}
fclose(file);
}
/* i is the number of lines read (sets of matrix dimensions) */
/* p is the pointer to 2*i array dimensions */
/* ...Use i and p... */
free(p);
The code does not check that the second dimension on one line is the same as the first dimension on the next line. It does not check for positive integers of 1 or 2 digits (basically, 1..99); it allows bigger values, zeroes and negative values. (The test c == '\n' ensures that there's a newline after the second number; no trailing blanks etc allowed.)
Given that p is (now) initialized to 0 (a null pointer), you could do without the malloc() and simply use realloc() unconditionally. Most people prefer not to do that, but it avoids repetition.
p = (int *)malloc (3 * 3 * sizeof(int))