How to get a 2d character array from a file?

This is a discussion on How to get a 2d character array from a file? within the C Programming forums, part of the General Programming Boards category; Code: char men_names[num_each][MAX_NAMELEN]; char women_names[num_each][MAX_NAMELEN]; for (j=0; j < num_each; j++) { fscanf(ifp, "%s", &men_names[j]); printf("%s\n", men_names[j]); } for (j=0; ...

  1. #1
    Registered User
    Join Date
    Aug 2010
    Posts
    42

    How to get a 2d character array from a file?

    Code:
    char men_names[num_each][MAX_NAMELEN];
            char women_names[num_each][MAX_NAMELEN];
            
            
               
             for (j=0; j < num_each; j++)
            {
              fscanf(ifp, "%s", &men_names[j]);
              printf("%s\n", men_names[j]);
             }
             for (j=0; j < num_each; j++)
             {
              fscanf(ifp, "%s", &women_names[j]);
              printf(ifp, "%s\n", women_names[j]); 
             }

    Where num_each is an integer which ive already scanned for that represents how many women or (not combined) men there are. And MAX_NAMELEN is defined as 19.


    The names in the file are separated by spaces and the names of the men are on one line and the names of the women are on the next.


    I know fgets would be good for this but I never can get it to work if I use it with fscanf and since I am scanning in many integers, I really don't want to convert them all from strings to integers if possible.

    (Note this is CS 1 so just take that into consideration when you are helping)

  2. #2
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Edit: Oh! Thanks, msh! I missed the "all names for a sex are on one line".

    So what was the problem with the original double for loop?
    Last edited by Adak; 09-18-2010 at 11:27 AM.

  3. #3
    msh
    msh is offline
    Novice
    Join Date
    Jul 2009
    Posts
    568
    I understood that the input is in form:
    <begin input file>
    John Robert Martin Victor ...
    Sylvie Mary Alexandra Cherry ...
    <end input file>

    Your proposal won't work for that, Adak.

    Edit:
    What I would suggest is to read the entire line into char[num_each * (MAX_NAMELEN + 1)] and then use strtok() to split it up and fill your mens_names[] and womens_names[]. (Caution! I might be overengineering.)
    Last edited by msh; 09-18-2010 at 11:30 AM.

  4. #4
    Registered User
    Join Date
    Aug 2010
    Posts
    42
    Here are the errors i get:

    line 20: syntax error before "=" (first line posted)
    line 21: syntax error before "="

    men_names and women_names are undeclared in this function

  5. #5
    msh
    msh is offline
    Novice
    Join Date
    Jul 2009
    Posts
    568
    context error: no context

  6. #6
    Registered User
    Join Date
    Aug 2010
    Posts
    42
    Quote Originally Posted by msh View Post
    context error: no context
    Don't know what that means. I took it to mean that you can't tell whats wrong without the rest of my code

    Code:
    #include <stdio.h>
    #include <string.h>
    
    #define MAX_NAMELEN = 19
    
    int main() {
        
        int i, j, k, num_groups, num_each;
        FILE *ifp = fopen("input.txt", "r");
        
        fscanf(ifp, "%d", &num_groups);
        
        for ( i=0; i < num_groups; i++)
            {
            fscanf(ifp, "%d", &num_each);
            printf("\n%d\n", num_each);
            
            int rating[2*num_each][num_each];
            
            char men_names[num_each][MAX_NAMELEN];
            char women_names[num_each][MAX_NAMELEN];
            
            
               
             for (j=0; j < num_each; j++)
            {
              fscanf(ifp, "%s", &men_names[j]);
              printf("%s\n", men_names[j]);
             }
             for (j=0; j < num_each; j++)
             {
              fscanf(ifp, "%s", &women_names[j]);
              printf("%s\n", women_names[j]); 
             }
        
           }
           
        getchar();
        return 0;
        
    }
    
    
    
    /*for (j=0; j < 2*num_each; j++)
            {
             for (k=0; k < num_each; k++)
             {
              fscanf(ifp, "%d", &rating[j][k]); 
              printf("%d ", rating[j][k]);
                          
             }
             printf("\n");
            }
            */

    if thats not what that meant please inform me.

    num_groups is basically how many times we will be looping all of our code.

    the last part of this code that is commented out is for the ratings of the men about the women and the women's ratings of the men.
    Last edited by DaNxTh3xMaNx; 09-18-2010 at 11:51 AM.

  7. #7
    msh
    msh is offline
    Novice
    Join Date
    Jul 2009
    Posts
    568
    Code:
    #define MAX_NAMELEN 19    // We lost a '=' here

  8. #8
    Registered User
    Join Date
    Aug 2010
    Posts
    42
    Quote Originally Posted by msh View Post
    Code:
    #define MAX_NAMELEN 19    // We lost a '=' here
    thanks. man it is always the most simple thing.

  9. #9
    Registered User
    Join Date
    Aug 2010
    Posts
    42
    Quote Originally Posted by Adak View Post
    You need to declare these arrays, before the for loop starts - not inside them.


    Code:
    int rating[2*num_each][num_each];
            
            char men_names[num_each][MAX_NAMELEN];
            char women_names[num_each][MAX_NAMELEN];
    well num_each would change for every group it runs. the problem says the max will be 10 of each gender so should i declare it as that and then fill in what is needed for each run through and just leave the rest to null?

  10. #10
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    I would make a char *array[NameLength];

    Then do your counting, and then malloc the number of names that you need, for that.

    If your C compiler allows this kind of declaration, then OK, but I'm not familiar with it, and mine won't do it (neither one of them), although they're old.

    Will your compiler allow this declaration?

    Show an example of a line of text. where are you getting this "num_each" value? Better yet, post a short example file, and I'll show you.

  11. #11
    Registered User
    Join Date
    Aug 2010
    Posts
    42
    2
    3
    Adam Bob Carl
    Diana Ellen Fran
    4 8 7
    6 7 5
    5 9 6
    7 6 8
    6 5 9
    4 7 3
    2
    Brad Tom
    Katie Angelina
    5 8
    9 7
    4 8
    7 6


    first number is num groups. 2nd number in num each. then the names. then adams ratings, bobs, carls, diana, ellen, fran, then next group.





    yea my compiler allows it.

  12. #12
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Consider some design choices:

    1) Expand the struct to include a small int array, for each person's ratings. This groups all the persons data, into a single record.

    2) use 4 arrays: a men's names b) women's names c) men's ratings, d) women's ratings.

    This gets confusing because you need something to associate the name with the right ratings. So adding an ID number to the struct for everyone, would be an answer. You see the problem:
    Code:
    Index  Women         Men         Ratings:
    ============================================
    0:     Abby          Abraham     Are these ratings[0] Abby's or Abe's?
    One easy way around this is to use ONE name array, for both sexes, and add a char sex to each struct. Then when you want to view only the males, your display function filters accordingly, and same for when you want to view just females, or view both.

    That leaves the index to the name, as the index to the rating array. In any group of data records that I've dealt with, you want to combine the names, and give each a sex field (char). There will be many times that you want to display data together (like who is in the top 10% of the ratings?), so it makes sense.

    What compiler are you using?

  13. #13
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    This is an example of what I was thinking of - but it's not as good as I'd like it to be. Seems a bit inelegant.

    This version only does one group, would need a while (there is more input) loop around it, to handle more blocks.

    What I really wouldn't like is the constant realloc() for more memory, with every block of data. Make the initial size something big enough to handle 300 structs or so, and realloc() another 200 or 300, if needed.

    That's why I made the ratings array, just big.

    To make this simple, I have another idea. Read each row of the file with fgets(), and if buff[0] < 'A', then it's a number. put all the numbers in one file, (in order), and all the names into another file (also in their original order). Then malloc all your arrays from reading the file. Ignore or throw out the group and each numbers.

    That avoids several complications in the code, including the structs. If you need to sort the names, or etc., then use an index or pointer array to make it appear sorted, and leave the data in it's original order.

    Code:
    /*
    Contents of 0dan.txt
    2
    3
    Adam Bob Carl
    Diana Ellen Fran
    4 8 7
    6 7 5
    5 9 6
    7 6 8
    6 5 9
    4 7 3
    2
    Brad Tom
    Katie Angelina
    5 8
    9 7
    4 8
    7 6
    
    first number is num groups. 2nd number in num each. then the names. then adams ratings, bobs, carls, diana, ellen, fran, then next group.
    */
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define NLen 19
    #define ROW 50
    #define COL 50
    
    typedef struct {
      char name[NLen];
      char sex;
      int id;
    }rec;
    
    int main(void) {
      char buff[128], ch;
      char *pbuff;
      int i, j, count, groups, each, num;
      int ratings[ROW][COL]={0};
      FILE *fp;
      rec *names;
    
      if((fp=fopen("0dan.txt", "rt")) == NULL) {
        printf("\nError opening data file - terminating");
        return 1;
      }
      fgets(buff, sizeof(buff), fp);
      groups = buff[0]-'0';
      fgets(buff, sizeof(buff), fp);
      each = buff[0]-'0';
      printf("\n\ngroups: %d  each: %d", groups, each);
      
      num=groups*each;
      names = malloc(num * sizeof(rec));
      if(names==NULL) {
        printf("\nError allocating memory");
        return 1;
      }
      
      for(i=0, count=0;i<groups;i++) {
        buff[0]='\0';
        pbuff = buff;
        fgets(buff, sizeof(buff), fp);
        for(j=0;j<each;j++) {
          sscanf(pbuff, "%s", names[count].name);
          if(i%2==0)
            names[count].sex = 'M';
          else
            names[count].sex = 'F';
          names[count].id = count+1;
          pbuff += strlen(names[count++].name)+1;
        }
      }
      //for(i=0;i<count;i++)
        //printf("\n%-19s  %c  %2d", names[i].name, names[i].sex, names[i].id);
    
      /* get the ratings */
      for(i=0;i<count;i++) {
        for(j=0;j<each;j++) {
          fscanf(fp, "%d", &ratings[i][j]);
          fscanf(fp, "%c", &ch);
        }
      }    
      printf("\n\nName                Sex  ID  Ratings\n");
      printf("====================================");
    
      for(i=0;i<count;i++) {
        printf("\n%-19s  %c  %2d ", names[i].name, names[i].sex, names[i].id);
        for(j=0;ratings[i][j]>0;j++) {
          printf("  %d", ratings[i][j]);
        }
      }
    
      fclose(fp);
      free(names);
      printf("\n\n\t\t\t    press enter when ready");
      i=getchar();
      return 0;
    }  
    //Output:
    
    groups: 2  each: 3
    
    Name                Sex  ID  Ratings
    ====================================
    Adam                 M   1   4  8  7
    Bob                  M   2   6  7  5
    Carl                 M   3   5  9  6
    Diana                F   4   7  6  8
    Ellen                F   5   6  5  9
    Fran                 F   6   4  7  3
    
    			    press enter when ready

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. how to initialize declared 2d character array
    By Marksman in forum C++ Programming
    Replies: 7
    Last Post: 03-13-2008, 10:41 PM
  2. C++ std routines
    By siavoshkc in forum C++ Programming
    Replies: 33
    Last Post: 07-28-2006, 01:13 AM
  3. Read file in 2D array
    By Chook in forum C Programming
    Replies: 1
    Last Post: 05-08-2005, 01:39 PM
  4. Possible circular definition with singleton objects
    By techrolla in forum C++ Programming
    Replies: 3
    Last Post: 12-26-2004, 10:46 AM
  5. file into 2d array
    By lakai02 in forum C Programming
    Replies: 0
    Last Post: 12-22-2002, 04:02 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21