Thread: Read in float values from two columns

  1. #1
    Registered User
    Join Date
    Feb 2010
    Posts
    14

    Unhappy Read in float values from two columns

    Hello All,

    I'm having trouble getting this code to work. Basically, I have been given a '.txt' file with two columns of extensive float values. We have been asked to write a program that will separate the columns into two arrays in order to perform various calculations on them later.

    I have tried to create a while loop that runs through and alternates between the arrays causing 'fscanf' to insert data into each of the alternating arrays as it passes through. My main problem is within the 'if' statements. I don't know how to perform a comparison of variable names rather than the variable contents. I'm sure you'll notice what I've tried to achieve when looking at this code:

    Code:
    /* 
     * File:   newmain.c
     * Author: paul
     *
     * Created on 09 February 2010, 19:37
     */
    
    #include <stdio.h>
    #include <stdlib.h>
    
    /*
     * 
     */
    int main() {
        FILE *file;
        float col1[100];
        float col2[100];
        float curr_arr;
        /* make sure it is large enough to hold all the data! */
        int i, j;
    
        file = fopen("/home/paul/short.txt", "r");
    
        if (file == NULL) {
            printf("Error: can't open file.\n");
            return 1;
        } else {
            printf("File opened successfully.\n");
    
            i = 0;
            curr_arr = col1[0];
    
            while (!feof(file)) {
                /* loop through and store the numbers into the array */
                fscanf(file, "%f", &curr_arr);
                if (&curr_arr == &col1[i]) {
                    curr_arr = col2[i];
                } else if (&curr_arr == &col2[i]) {
                    curr_arr = col1[i];
                } else {
                    printf("An error ocurred.\n");
                    return 1;
                }
                i++;
            }
        }
    
        printf("Number of numbers read: %d\n\n", i);
        printf("The numbers are:\n");
    
        for (j = 0; j < i; j++) { /* now print them out 1 by 1 */
            printf("%f\n", col1[j]);
            printf("%f\n", col2[j]);
        }
    
        fclose(file);
        return 0;
    }
    I'll be very grateful for any help you may offer on the matter!

    Kind Regards,

    Paul S.

  2. #2
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    No if statements are needed for this. Handle the name explicitly.

    Code:
    while you still have data to read {
    
      fscanf(filePointer, "%f %f", &array1[i], &array2[i])
      ++i;
    
    }
    Another way to go (probably better):

    fgets() each line into a char buffer and then sscanf() on that buffer,
    just use the same kind of explicit logic.
    Last edited by Adak; 02-09-2010 at 03:15 PM.

  3. #3
    Registered User
    Join Date
    Oct 2006
    Location
    Canada
    Posts
    1,243
    Code:
            while (!feof(file)) {
    Cprogramming.com FAQ > Why it's bad to use feof() to control a loop

    Code:
                fscanf(file, "%f", &curr_arr);
    I think for us to really understand the scenario is to know what the input file is. You say its "two columns". Are the columns separated by spaces? a tab? a comma? etc. Since it appears you're on Linux or UNIX, try "cat -A short.txt" which will show the exact characters in the file. The purpose of this is to see if your file is separate by spaces versus tabs (which are hard to visually distinguish from spaces). When you know the format, you can read both columns at once and store each in their corresponding array, like
    Code:
    int line = 0;
    // while loop
    fscanf(file, "%f\t%f", &col1[line], &col2[line]);
    line++
    // end loop

  4. #4
    Registered User
    Join Date
    Feb 2010
    Posts
    14
    Thanks for your reply Adak. I have tried your first suggestion but this doesn't seem to separate the columns into one array from the other. Here is a shortened version of the text file:

    Code:
    2.67	2.464
    
    2.393	1.228
    
    2.167	0.657
    
    5.047	2.033
    
    7.993	2.169
    
    7.917	1.249
    
    4.874	1.66
    
    4.384	2.166
    
    5.355	2.896
    
    4.505	2.637
    
    5.286	2.787
    
    8.948	-2.205
    
    11.186	-8.404
    
    12.918	-8.903
    
    13.453	-7.927
    
    13.996	-7.884
    
    13.8	-7.362
    
    13.906	-7.886
    
    14.254	-8.287
    
    14.185	-8.359
    
    14.01	-9.107
    
    13.854	-9.074
    
    13.876	-6.198

  5. #5
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Look at my edited post. I was trying to be general, rather than just specify every detail of the line of code.

    If it doesn't work, print out what it is that you're getting, with the updated code.

  6. #6
    Registered User
    Join Date
    Feb 2010
    Posts
    14
    Thanks also nadroj. Above is the text file, the columns are seemingly only separated by a space. (Ignore the alternate line spaces).

  7. #7
    Registered User
    Join Date
    Feb 2010
    Posts
    14
    OK - thanks folks I now have the data into two arrays! nadroj - you mentioned it to be bad practice using feof() to control a loop, and I can now see for why as the last value stored into the array is '0.000000'

    With being a novice I'm a little unsure how I would go about improving the code? Below is the code as it currently stands:

    Code:
    /* 
     * File:   newmain.c
     * Author: paul
     *
     * Created on 09 February 2010, 19:37
     */
    
    #include <stdio.h>
    #include <stdlib.h>
    
    /*
     * 
     */
    int main() {
        FILE *file;
        float col1[100];
        float col2[100];
        float curr_arr;
        /* make sure it is large enough to hold all the data! */
        int i, j;
    
        file = fopen("/home/paul/short.txt", "r");
    
        if (file == NULL) {
            printf("Error: can't open file.\n");
            return 1;
        } else {
            printf("File opened successfully.\n");
    
            i = 0;
    
            while (!feof(file)) {
                /* loop through and store the numbers into the array */
                fscanf(file, "%f\t%f", &col1[i], &col2[i]);
                i++;
            }
        }
    
        printf("Number of numbers read: %d\n\n", i);
        printf("The numbers are:\n");
    
        printf("\nColumn 1:\n\n");
        for (j = 0; j < i; j++) { /* now print them out 1 by 1 */
            printf("%f\n", col1[j]);
        }
        printf("\nColumn 2:\n\n");
        for (j = 0; j < i; j++) {
            printf("%f\n", col2[j]);
        }
    
        fclose(file);
        return 0;
    }

  8. #8
    Registered User
    Join Date
    Oct 2006
    Location
    Canada
    Posts
    1,243
    Quote Originally Posted by sirsmilealot
    Above is the text file, the columns are seemingly only separated by a space.
    Quote Originally Posted by nadroj
    Since it appears you're on Linux or UNIX, try "cat -A short.txt" which will show the exact characters in the file. The purpose of this is to see if your file is separate by spaces versus tabs (which are hard to visually distinguish from spaces). When you know the format...
    Quote Originally Posted by sirsmilealot
    OK - thanks folks I now have the data into two arrays!
    Quote Originally Posted by sirsmiealot
    Code:
                fscanf(file, "%f\t%f", &col1[i], &col2[i]);
    Hopefully you see this flow of events. Assuming that is the code that is working, the columns are not separated by spaces, as you assumed, but by a tab, which is what the "\t" is in the fscanf line.

  9. #9
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    I copied your text file into notepad, so my text file may or may not have tabs in it, now.

    Tabs should be seen as whitespace by fscanf(), and skipped if you're format is for a number.

    Code:
    #include <stdio.h>
    
    int main() {
      int i, n, gotNum; 
      FILE *fp;
      float array1[100];
      float array2[100];
    
      if((fp=fopen("floats.txt", "rt")) == NULL) {
        printf("\nError opening file floats.txt\n");
        return 1;
      }
      i = 0;
      do {
        gotNum = 0;
        gotNum = fscanf(fp, "%f%f", &array1[i], &array2[i]);
        if(gotNum > 1)
          printf("\n%f   %f", array1[i], array2[i]);
        ++i;
        
      }while(gotNum > 1);
    
      
      fclose(fp);   
      printf("\n\n\t\t\t     press enter when ready");
    
      i = getchar(); ++i;
      return 0;
    }

  10. #10
    Registered User
    Join Date
    Feb 2010
    Posts
    14
    Ah, I see where we're goin' with this. I only started programming in C a couple of days ago so I've a long way to go yet but already it's starting to make sense! I'm still slightly confused about how to implement a 'buffer' as opposed to feof().

    Cheers,

    Paul.

  11. #11
    Registered User
    Join Date
    Feb 2010
    Posts
    14
    Well, thanks a lot for all your help - I'd have been stuck for hours more otherwise! I've now got to:

    b) Calculate and print to screen the total and average of each column
    c) Calculate and print to screen the maximum values in each column
    d) Calculate and print to screen the minimum values in each column

    ...so that ought to keep me busy!

    Cheers,

    Paul.

  12. #12
    Registered User
    Join Date
    Oct 2006
    Location
    Canada
    Posts
    1,243
    Quote Originally Posted by Adak
    Tabs should be seen as whitespace by fscanf(), and skipped if you're format is for a number.
    OK, thanks.

    sirsmilealot, maybe this is a relatively complex thing to be doing only a few days into learning programming--keep it up. I just want to emphasize that as you continue learning, try to understand what you're doing, and not simple writing code or doing things a certain way because "you're supposed to". The whole buffer thing isnt too, too bad, so just try and read and understand it.

  13. #13
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Quote Originally Posted by sirsmilealot View Post
    Ah, I see where we're goin' with this. I only started programming in C a couple of days ago so I've a long way to go yet but already it's starting to make sense! I'm still slightly confused about how to implement a 'buffer' as opposed to feof().

    Cheers,

    Paul.
    A great way to get data, in general, is to use a char buffer[] to put one line in at a time, and then you can "pick" out what you need and see if it's good input, using sscanf() (which works like fscanf(), but on a string, instead of a file.

    char buffer[100]; //leave plenty of room for a line

    fgets(buffer, sizeof(buffer), YourFilePointer); //puts one line into the buffer
    Also, *very important*, it prevents the buffer from being overflowed and crashing your program. fgets() will only put 100 char's at most, into your buffer - no matter what.

    sscanf(); //with the right format parameters, can pull out what you need from the buffer.

    getting good data from a user is more difficult than it sounds, and fscanf() (and it's "cousins" of scanf(), and sscanf() and such), are not up to the task, without the support of a buffer string that the logic can go back to, with new logic , if necessary.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Pass by reference
    By mcgeady in forum C Programming
    Replies: 11
    Last Post: 02-17-2005, 03:01 AM
  2. problems storing values in varibles
    By stodd04 in forum C Programming
    Replies: 7
    Last Post: 02-08-2005, 11:56 AM
  3. Multidimensional String
    By Beast() in forum C Programming
    Replies: 14
    Last Post: 07-03-2004, 12:47 AM
  4. Repetition in do{}while
    By Beast() in forum C Programming
    Replies: 25
    Last Post: 06-16-2004, 10:47 PM
  5. Why does it work in Visual Studio and Not Borland
    By MonteMan in forum C++ Programming
    Replies: 14
    Last Post: 10-20-2002, 09:36 PM