1

I'm trying to do matrix chain multiplication and I need to take input from a file in C

It works fine for one test case while for other run fails

testcase #1 (this works fine)

3 5
5 7
7 9
9 6
6 7
7 9

testcase #2 (this gives matrix.exe stopped working)

30 35
35 15
15 5
5 10
10 20
20 25

NOTE: In testcases consecutive numbers are rows and columns of matrices

This is the code I'm using

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++;
    }
}
12
  • Hi - Unfortunately, what you are doing is wrong. Q: What are you trying to do? Does each line in "matrix.txt" contain data for an entire matrix? How do you know how big the matrix is? EXAMPLE: for a 3x3 matrix, you'll need something like: p = (int *)malloc (3 * 3 * sizeof(int)) Commented Aug 11, 2012 at 19:49
  • The file doesn't actually contain matrix data. It contains n lines for n matrices and each line has 2 integers 1 is for no of rows and the other for columns Unless I read the whole file, I won't know how many matrices are there Commented Aug 11, 2012 at 19:53
  • is this homework? otherwise i would suggest using c++ and std::vector or similar Commented Aug 11, 2012 at 19:56
  • Yes, This is homework and I need to do it in C. I seriously don't understand why it's working once and failing the next time Commented Aug 11, 2012 at 20:01
  • 1
    "This is homework and I need to do it in C. I seriously don't understand why it's working once and failing the next time – Sai Teja Reddy" - it's because you incorrectly allocating memory assuming *(p + i) is yours to take, but your code might have other problems, try using a debugger Commented Aug 11, 2012 at 20:14

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.