1. Welcome to the new MacRumors forums. See our announcement and read our FAQ

C Question - Can't open an input file in Xcode?

Discussion in 'Mac Programming' started by ocolange, Oct 31, 2010.

  1. macrumors newbie

    So this is a pretty beginner question; all my program has to do is open a text file and perform some operations on it, but mine will not even open the file when I try to run it in Xcode. I just get a message that reads: ERROR: Cannot open A5.txt. Also, the exact same program runs perfectly on my friend's Dell laptop using Windows and an lcc compiler, so I feel like its probably something small I'm missing that needs changed for it to work in Xcode. My code is posted below; any insight would be greatly appreciated.

    #include <stdio.h>
    #include <time.h>
    /* Global variable declarations.*/
    double a[5000][5000];  /* The two-dimensional matrix A. */
    double b[5000];        /* The right-hand side vector b. */
    double x[5000];        /* The solution vector x. */
    int n;                 /* The dimension (n x n) of the matrix system. */
    /* This is the main program. */
    int main(void)
        /* Local variable declarations. */
        char fileaname[100];        /* The name of the input file containing the matrix A. */
        char filebname[100];        /* The name of the input file containing the vector b. */
        char filexname[100];        /* The name of the input file containing the vector x. */
        int gausselimination(void); /* Declare our gausselimination function. */
        char line[100];             /* The input line from stdin. */
        clock_t time1;              /* The current time before the call to gausselimination. */
        clock_t time2;              /* The current time after the call to gausselimination. */
        FILE *filea;                /* The input file containing the matrix A. */
        FILE *fileb;                /* The input file containing the vector b. */
        FILE *filex;                /* The input file containing the vector x. */
        int i;                      /* Loop index. */
        int j;                      /* Loop index. */
        int ntemp;                  /* A temporary n that we'll use to check the input files. */
        /* Get the file name for the matrix A. */
        printf("Enter the name of the file containing the matrix A: ");
        fgets(line, sizeof(line), stdin);
        sscanf(line, "%s", &fileaname);
        /* Open the file for the matrix A.  If the file cannot be open, then send
         * an error message to the user. */
        filea = fopen(fileaname, "r");
        if(filea == NULL)
            printf("ERROR: Cannot open %s.\n", fileaname);
        printf("Reading the matrix A ... ");
        /* Get the dimension n of the matrix A. */
        fgets(line, sizeof(line), filea);
        sscanf(line, "%d", &ntemp);
        n = ntemp;
        /* Loop over the rows using the index i.  Then loop over the columns using
         * the index j.  At each row, read the entry a[i][j]. */
        for(i = 0; i <= n-1; ++i)
            for(j = 0; j <= n-1; ++j)
                fgets(line, sizeof(line), filea);
    			sscanf(line, "%lf", &a[i][j]);
        /* Close the file. */
        /* Get the file name for the vector b. */
        printf("Enter the name of the file containing the vector b: ");
        fgets(line, sizeof(line), stdin);
        sscanf(line, "%s", &filebname);
        /* Open the file for the vector b.  If the file cannot be open, then send
         * an error message to the user. */
        fileb = fopen(filebname, "r");
        if(fileb == NULL)
            printf("ERROR: Cannot open %s.\n", fileaname);
        printf("Reading the vector b ... ");
        /* Read the dimension n of the vector b.  If this n does not match the n
         * that we read above, then alert the user. */
        fgets(line, sizeof(line), fileb);
        sscanf(line, "%d", &ntemp);
        if(ntemp != n)
            printf("ERROR: The dimension of b does not match the dimension of A.\n");
        n = ntemp;
        /* Loop over the rows using the index i.  At each row, read the entry b[i]. */
        for(i = 0; i <= n-1; ++i)
            fgets(line, sizeof(line), fileb);
    		sscanf(line, "%lf", &b[i]);
        /* Close the file. */
        printf("Performing the Gauss elimination ... ");
        /* We are going to time how long it takes to perform the Gauss elimination.
         * The variable time1 contains the current time before the call to the subroutine. */
        time1 = clock();
        /* This is the call to the Gauss elimination function. */
        /* The variable time2 contains the current time after the call to the subroutine. */
        time2 = clock();
        /* Compute how long it took to perform the Gauss elimination, and print the answer
         * to the user. */
        printf("The elapsed CPU time was %.8f seconds.\n", (float) (time2-time1)/CLOCKS_PER_SEC);
    	/* Get the file name for the vector x. */ 
        printf("Enter the name of the file to write the vector x: ");
        fgets(line, sizeof(line), stdin);
        sscanf(line, "%s", &filexname);
        /* Open the file for the vector x.  If the file exists already, then it will be
         * written over. */
        filex = fopen(filexname, "w");
        /* Print the dimension n to the file containing the vector x. */    
        sprintf(line, "%d\n", n);
        fputs(line, filex);
        /* Loop over the rows using the index i.  At each row, print the entry x[i]
         * to the file. */
        for(i = 0; i <= n-1; ++i)
            sprintf(line, "%.14lf\n", x[i]);
    		fputs(line, filex);
        /* Close the file. */
    /* This function does the Gauss elimination on A and b and returns
     * the solution vector x. */
    int gausselimination(void)
        /* Local variable declarations. */
        float elementbelowpivot; /* The elements below the pivot element but in the same column. */
        float pivot;             /* The value of the pivot element. */
        float tempsum;           /* A temporary sum for the backward substitution. */
        int i;                   /* Loop index for rows. */
        int ii;                  /* Loop index for rows. */
        int j;                   /* Loop index for columns. */
        /* First triangularize the coefficient matrix A.
         * Loop over all of the rows. */
        for(i = 0; i <= n-1; ++i)
    		/* Divide every element in the row by the pivot element.
    		 * First save the pivot element. */
    		pivot = a[i][i];
    		/* Then loop over all of the columns after the pivot element.*/
            for(j = i; j <= n-1; ++j)
                /* Then divide each element by the pivot element. */
                a[i][j] = a[i][j] / pivot;
    		/* Divide the element in the vector b by the pivot element. */
    		b[i] = b[i] / pivot;
            /* Loop over the remaining rows.  Multiply the current row
    		 * by each element in the column below the pivot element,
    		 * and then subtract the current row from each remaining row.
    		 * We are zero-ing out the lower triangular portion of the
    		 * matrix A.  First loop over all of the rows below the
    		 * current row. */
            for(ii = i+1; ii <= n-1; ++ii)
                /* Save the element below the pivot but in this row. */
                elementbelowpivot = a[ii][i];
    			/* Then loop over the columns, starting at the column that
    			 * contains the pivot element. */
                for(j = i; j <= n-1; ++j)
    				/* Multiply the pivot row by the element below the pivot,
    				 * and then subtract that quantity from the element in
    				 * the row below the pivot. */
                    a[ii][j] = a[ii][j] - a[i][j] * elementbelowpivot;
    			/* Don't forget to do the same thing to the vector b. */
    			b[ii] = b[ii] - b[i] * elementbelowpivot;
        /* The coefficient matrix A has been triangularized.  Now it should be
         * easy to use back substitution to solve for the vector x.
         * Loop over the rows, starting at the bottom and going up. */
        for(i = n-1; i >= 0; --i)
            /* Each element in x is equal to the corresponding element in b
    		 * minus the sum of the products of any a's and x's below the current
    		 * x.  (See page 2.10 in Dr. Westerink's lecture notes for a better
    		 * description of backward substitution.)  So we need to sum the
    		 * products of the coefficients a and any already-solved-for x.
    		 * Zero out our temporary sum. */
            tempsum = 0.0;
    		/* Loop over any columns/rows to the right/below the current x. */
            for(j = i+1; j <= n-1; ++j)
                tempsum = tempsum + a[i][j] * x[j];
    		/* Solve for the current x. */
    		x[i] = b[i] - tempsum;
  2. macrumors 68000

    Can you post A5.txt?

    Try running it from Terminal, not Xcode:

    gcc matrix.c -o matrix

    Xcode compiles to the 'debug' sub-directory in your projects main folder, and you would have to have A5.txt in that folder for the program to see it.

    Try giving the whole file name, /Users/John/Documents/A5.txt, or whatever the location of your file is
  3. macrumors 603

    Add the following lines shown hilited in red. It uses a C Standard Library function, so should work on any platform, even Windows.
    /* Get the file name for the matrix A. */
    printf( "working directory: %s\n", getcwd(line, sizeof(line)) );
    printf("Enter the name of the file containing the matrix A: ");
    Post the value displayed as working directory, and explain whether the file pathname you entered as "A5.txt" is or isn't located in that directory.

    If you don't know what a working directory is, read this:

    For changing an executable's working directory when run in Xcode, see this:

    By the way, your program will behave very badly if the contents of the files is malformed in any way. For example, if the array or matrix size isn't followed by exactly the right number of data lines. And it has other problems, too, such as the inability to use filenames or pathnames containing spaces.
  4. macrumors newbie

    I Had a similar problem to you with very similar file opening writing and reading code.

    I solved it and so I tried your code and ran it successfully using the same approach - although with empty files.

    I created empty files A5.txt, B5.txt etc. and placed them in the /build/release folder together with the application file.

    I found that if they had the extension .txt your code did not work (same as in my own program) but BY SIMPLY REMOVING the extension and naming the files simply A5 and B5 etc. the error did not occur.

    This is exactly what I had to do to get my program working.

    So although there may be a directory location problem as well, (as discussed by "chown33"), I believe there is also an issue with file extension naming, which I do not claim to fully understand. All I do know is that this workaround is consistently working for me.

    Hope this helps in some way.:)
  5. macrumors 603

    Exactly how did you create your original A5.txt & B5.txt files?

    If it was in the Finder, and Finder is hiding extensions (the default), then the actual filename would be "A5.txt.txt". You would see "A5.txt" in Finder, but the real filename is not what you see. If you run the 'ls' command on the directory where your A5.txt file is located, it should show the real name.

    There is no reason that a command-line program would fail because a file has a ".txt" extension. I use that extension every day, and every command I've ever used or written is able to see and use files with that extension. It's almost certain that something else was causing the failure in your case.

    Another problem I've seen is when people save a file using TextEdit (or something similar), and give it what they think is a ".txt" extension, but they again don't notice that extensions are being hidden. Or they save a Rich Text file as "something.txt", which actually writes RTF text format to the file, because they neglected to do Format > Make Plain Text before saving.

    Without knowing exactly what was done, all anyone can do is guess.
  6. macrumors newbie

    Hi chown33
    I created my first text file for today's experiment by renaming a file originally created from a C program fopen command. I named it simply as A5.
    However I think I made a mistake by creating the second A5.txt file from Textedit in exactly the erroneous way you described, and the combination led to the results I described.
    I have repeated the experiment with correctly created files A5 and A5.txt running in the OPs program and both work fine if the files are in the correct sub directory. Furthermore I have rechecked my own program which has been developed considerably from the stage when I myself had the problem and I can't make mine fail at all now - so Thankyou for your help and sorry for any confusion. Incidentally if you do create a text file in Textedit (using Format Plain text) is it considered bad practice to subsequently completely remove the extension. I would appreciate your comment. Also, I am creating a series of "scenario" data files for storing (and simultaneously accessing) regularly updated data and I'm not sure what naming convention (for the extension) is considered professional. - do you have any advice?
  7. macrumors 603

    Bad practice for whom? The main reason I use ".txt" is so I can view and edit the file simply by double-clicking it. If it's just you editing the file, you can do what works for you. No one else will care. If the files are for an app that's distributed to others, then extension-less files are usually a bad idea.

    Define what you mean by "professional". If you mean something like "accessible to users without being confusing", then your first step is to define who your users are: define your audience.

    A file's suffix should indicate either the nature of its content, if that content is general-purpose, or it should imply a specific (and hopefully unique) program that is responsible for interpreting that content.

    Examples of general-purpose: .png, .jpeg, .pdf, .aiff, .mp3, .plist. The content format is well-defined, and any number of different programs can operate on the content. Different programs may do different things with the content (e.g. iTunes doesn't do the same thing with a jpeg that Preview.app does).

    Examples of special-purpose: .xcodeproj, .numbers, .pages. The content format is not publically defined, and its interpretation is left to a particular app. This doesn't mean the format is entirely unknown, only that you can't rely on it being a specific thing forever.

    Note that .numbers and .pages are ordinary zip files containing multiple files, some of which are in general-purpose formats, e.g. the images are in png or jpeg. Also note that a document bundle (such as .xcodeproj) is a directory containing multiple separate files. Maybe one of those fits your intent better than an uncollected set of files. It depends on who your target audience is, and what you mean by "professional".
  8. macrumors newbie

    Since my activity is purely a hobby then I think you have answered my question. When I said "professional" I was really meaning "good practice" and as you pointed out, the target audience is the important consideration - since I am the only user it doesn't particularly matter. I should have said that my data is simply long numeric lists , and I think I will continue using the .txt extension, if only for the very good reason you give, namely that it can be viewed and edited simply by double clicking on it.
    Thanks for your comments.

Share This Page