Link to home
Start Free TrialLog in
Avatar of Celiowin
Celiowin

asked on

Reading and displaying 2 text files in 2 arrays

Hello, i'm new with c programming and i need help with the code, I've worked with just intergers before , but i am having trouble with strings, characters when involved with arrays
I have name.text file like this,

Alexander
Alice
Brian
Kylie
Mark
Michelle

I need to read the text file and store them in a two dimensional array of characters (10 columns and 6 rows), and display the infromation stored in the array.
 
Then I have a second text file (results.txt),

Round 1 Quiz Results
Alice 17 Alexander 13
Brian 18 Kylie 12
Mark 15 Michelle 15

Round 2 Quiz Results
Michelle 19 Alice 11
Alexander 18 Brian 12
Mark 16 Kylie 14

I need store them in a second two dimensional floating point array (6 columns and 6 rows), and display the infromation stored in the array and display both of them.

E.g.
After Round 1
Names           Played     Won   lost     Drawn    Average     Points
-----------------------------------------------------------------------------
Alexander           1                    1                       13             0
Alice                   1          1                                 17             2
Brian                  1           1                                 18             2
Kylie                   1                   1                         12            0
Mark                   1                              1             15             1
Michelle              1                               1             15             1

It also needs to be updated each round.

I started like this for reading and displaying the first text files, which does not work -

#include <stdio.h>
#include <stdio.h>

#define nameLength 10
#define maxNames 6

void inputNames(char name[nameLength][maxNames]);
void outputNames(char name[nameLength][maxNames]);

int main ()
{
char name[nameLength][maxNames];
inputNames(name);
outputNames(name);

return 0;
}
***********************************************
void inputNames(char name[nameLength][maxNames])
{
FILE*fptr
int i,j;

if ((fptr = fopen ("name.txt","r"))==NULL)
{
printf ("Cannot Open Input File."\n);
exit(0);
}
for (i=0;i<nameLength;i++)
{
fscanf(fptr,"%c",&nameLength[i]);
}
for (j=0;j<maxNames;j++)
fscanf(fptr,"%c",&maxNames[j]);

fclose (fptr);
}
*********************************************
void outputNames(char name[nameLength][maxNames])
{
int i, j;

for (i=0;i<nameLength;i++)
{
for (j=0;j<maxNames;j++)
printf ("%c",name[nameLength][maxNames]);
}
}
Avatar of avizit
avizit

one obvious mistake is

fscanf(fptr,"%c",&nameLength[i]);

and

fscanf(fptr,"%c",&maxNames[j]);


nameLength is defined as 10   a constant .. and maxNames as 6 .

so the above two really dont make sense..

more later

/abhijit/

also in function "outputNames"

you have

for (j=0;j<maxNames;j++)
printf ("%c",name[nameLength][maxNames]);

now in the printf you have "name[nameLength][maxNames] " where nameLength is 10 and maxNames is 6  so the statement is equivalent to

printf("%c",name[10][6]);

so you are effectively printing the same character 60 times !  

Hint : use  i and  j   in the expression

/abhijit/


come back when you have made the above corrections and paste your code here and then we can look further what you are doing wrong




Hi

Here are corrections you need to make:


for (i=0;i<nameLength;i++)
{
fscanf(fptr,"%c",&nameLength[i]);
}
for (j=0;j<maxNames;j++)
fscanf(fptr,"%c",&maxNames[j]);


should be changed to something like:


for(i=0;i<maxNames;i++)
{
fscanf(fptr,"%s",name[i]);           //%s is for string   and '&' is  not req for %s
}

or if you want to be safer use fgets() like

for(i=0;i<maxNames;i++)
{
fgets(name[i],nameLength,fptr);
}

Similarly for printing use:

for(i=0;i<maxNames;i++)
   printf("%s",name[i]);          



Dhyanesh
> #define nameLength 10
> #define maxNames 6

As the identifier signifies, the name should be declared as
name[maxNames][nameLength]. It doesn't matter in the scenario but it may cause confusion. Also for reading one line at a time you should use fgets instead of reading one charecter at a time. So, for reading you can use fgets in a loop.

char *res;

for(i=0;i<maxNames;i++)
{
    res = fgets ( name[i], nameLength, fptr);
    if ( res == NULL ) {
        if (feof(fptr))
            break;         /* End of file reached */
        else
            exit(1);       /* Error in reading from file */
    }
}

This will read all the lines in the array. Each alement of the array is a char* pointing to one line.
I'd say use fgets to read the file one line at a time.

The names.txt is simple as you just need to read one string from each line.

for results.txt,use fgets to get the entire line into a char array,then use strtok() to tokenize the string based on spaces,and store each char pointer returned using strcpy.

For the numeric value,convert the char pointer to integer using atoi().

Example of strtok():

 char str[]="Hello 1 Hello 2";
 char *p;

// strtok places a NULL terminator in front of the token, if found
p = strtok(str, " ");
printf("%s\n", p);
while(p!=NULL)
{
/* A second call to strtok using a NULL
as the first parameter returns a pointer
to the character following the token  */
p = strtok(NULL, " ");
if (p)   printf("%s\n", p);
}

Now you need to figure out how to convert which of the tokens into integer using atoi()

atoi() Syntax:
int n;
char *ptr="123";
n=atoi(ptr);

Once you have this info.,storing them into arrays should be relatively simple.
Avatar of Celiowin

ASKER

warning C4013: 'exit' undefined; assuming extern returning int
Okay, I am able to display the first text file (Is this okay ?)

#include <stdio.h>
#include <stdlib.h>

#define nameLength      10
#define maxNames      6
#define      Columns      6
#define      Rows      6

void inputNames (char name[maxNames][nameLength]);
void outputNames (char name[maxNames][nameLength]);

void inputResults (char table[Rows][Columns]);
void outputResults (char table[Rows][Columns]);

int main ()
{

      char name[maxNames][nameLength];

      inputNames (name);
      outputNames (name);

      return 0;
}
/*************************************************/
void inputNames (char name[maxNames][nameLength])
{
      FILE *fptr;
      int i;

      if ((fptr = fopen ("names.txt","r"))==NULL)
      {
            printf ("Cannot open file.\n");
            exit(0);
      }
      for(i=0;i<maxNames;i++)
      {
            fscanf(fptr,"%s\n", name[i]);
      }

      fclose(fptr);
}
/*************************************************/
void outputNames (char name[maxNames][nameLength])
{
      int i;
      for(i=0;i<maxNames;i++)
      {
            printf("%s\n", name[i]);
      }
}
/*************************************************/
void inputResults (char table[Rows][Columns])
{
}
/*************************************************/

void outputResults (char table[Rows][Columns])
{
}
But for the second text file, how would you read it in by each rounds, and how do you guys create a second multi-dimensional array and diplay it with the other multi-dimensional array like a propper table. I really stuck.

Round 1 Quiz Results
Alice 17 Alexander 13
Brian 18 Kylie 12
Mark 15 Michelle 15

Round 2 Quiz Results
Michelle 19 Alice 11
Alexander 18 Brian 12
Mark 16 Kylie 14

Create a multidimensional array

int scores[6][6];

scores[0][0]...scores[0][5] are the columns of the table for the first player. and so on.

Since all your values are numbers,u can use an int array.
You want to display the table after reading values for each round?
I just noticed:

>I need store them in a second two dimensional floating point array (6 columns and 6 >rows),

Are you supposed to have fractions in your values as well?

In your program in you last post,
>void inputResults (char table[Rows][Columns]);
>void outputResults (char table[Rows][Columns]);

The arguments should be float in that case.
A few modifications to my prev. post:

char str[]="Hello 1 Hello 2";
char *p;
int pos=-1;
int pos2=-1;
int flag=0;
// strtok places a NULL terminator in front of the token, if found
p = strtok(str, " ");
for(i=0;i<6;i++)
{
 if(strcmp(name[i],p)==0) {pos=i;break;}
}

while(p!=NULL)
{
/* A second call to strtok using a NULL
as the first parameter returns a pointer
to the character following the token  */
float val;
p = strtok(NULL, " ");
if (p)
{
  if(flag==0)
 {
  val=atof(p);
  table[pos][4]+=val; //add to average
  table[pos][0]+=1;     //add to played
 }
 else
 {
  for(i=0;i<6;i++)
  {
   if(strcmp(name[i],p)==0) {pos2=pos;pos=i;break;}
  }
 }
 //printf("%s\n", p);
}
 flag=!flag;
}

Now after you have this info in your table array,and you have the 2 indexes for the 2 players in pos and pos2,you can calc. who has higher avg,thus who won and who gets the points.

This will be repeated for every line.

For displaying the table roundwise:
After you read in the line using fgets into an array,search for the string "round" using
strstr().
If it exists,display the table(check if its the first round,first calc, before printing.)
How do u read and display the table after reading values for each round?
ankuratvb,
how do you do this ?
After you read in the line using fgets into an array,search for the string "round" using
strstr().
If it exists,display the table(check if its the first round,first calc, before printing.)
All you have to do is keep reading line by line till you get a blank line i.e. line="\n";
I noticed this in your text file,there's an empty line b/w round results.
SO whenever there's a blank line,display the table.

#define MAX 255
char line[MAX];//for example

    FILE *fptr;
    int i;

    if ((fptr = fopen ("results.txt","r"))==NULL)
    {
         printf ("Cannot open file.\n");
         exit(0);
    }
    while(fgets(line,MAX,fptr)!=NULL)
    {//now you have one line of text in the char[] line

      if(strcmp(line,"\n")==0) {displaytable(table);continue;}

      if(strstr(line,"Round")!=NULL)//strstr checks with case sensitivity
      {
        continue;
      }
      //calculate your values here and store them in table[][]
   }

Please note that this is not the complete code.You may have to change it somewhat.
This is just to give you an idea of how to go about reading your file.
I am not allow to use break statements, the code envolving void inputResults (float table[tableRows][tableColumns]), and
void outputResults (float table[tableRows][tableColumns]) is not working properly it is displaying 124506, 6 times. and when i change it diplays. Could someone please fix my code for the 2 function.

Round 124506
Quiz 124506
Results 124506
Alice 124506
Alexander 124506
Brian 124506 etc.....


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define nameLength      10
#define maxNames      6
#define      tableColumns 8
#define      tableRows      6

void inputNames (char name[maxNames][nameLength]);
void outputNames (char name[maxNames][nameLength]);

void inputResults (float table[tableRows][tableColumns]);
void outputResults (float table[tableRows][tableColumns]);

int main ()
{

      char name[maxNames][nameLength];
      float table[tableRows][tableColumns];

      inputNames (name);
      outputNames (name);
      inputResults (table);
      outputResults (table);

      return 0;
}
/*************************************************/
void inputNames (char name[maxNames][nameLength])
{
      FILE *fptrOne;
      int i;

      if ((fptrOne = fopen ("names.txt","r"))==NULL)
      {
            printf ("Cannot open file.\n");
            exit(0);
      }
      for(i=0;i<maxNames;i++)
      {
            fscanf(fptrOne,"%s\n", name[i]);
      }

      fclose(fptrOne);
}
/*************************************************/
void outputNames (char name[maxNames][nameLength])
{
      int i;
      for(i=0;i<maxNames;i++)
      {
            printf("%s\n", name[i]);
      }
}
/*************************************************/
void inputResults (float table[tableRows][tableColumns])
{
      FILE *fptrTwo;
      int i;

      if ((fptrTwo = fopen ("results.txt","r"))==NULL)
      {
            printf ("Cannot open file.\n");
            exit(0);
      }
      for(i=0;i<maxNames;i++)
      {
            fscanf(fptrTwo,"%s %d\n", &table);

      }

      fclose(fptrTwo);
}
/*************************************************/

void outputResults (float table[tableRows][tableColumns])
{
      int i;
      for(i=0;i<tableRows;i++)
      {
            printf("%s %d\n", &table);
      }
      
}
/**************************************************/
Your table[][] is a float array and you are storing characters into it.

plus
> fscanf(fptrTwo,"%s %d\n", &table);
it should be &table[somevalue][somevalue];
plus youre reading two values %s %d but storing only one.


Here's the working code,it fills in entries for played and average.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define nameLength     10
#define maxNames     6
#define     tableColumns 6
#define     tableRows     6

void inputNames (char name[maxNames][nameLength]);
void outputNames (char name[maxNames][nameLength]);

void inputResults (char name[maxNames][nameLength],float table[tableRows][tableColumns]);
void outputResults (char name[maxNames][nameLength],float table[tableRows][tableColumns]);

int main ()
{

    char name[maxNames][nameLength];
    float table[tableRows][tableColumns]={0.0};

    inputNames (name);
    outputNames (name);
    inputResults (name,table);
    outputResults (name,table);

    return 0;
}
/*************************************************/
void inputNames (char name[maxNames][nameLength])
{
    FILE *fptrOne;
    int i;

    if ((fptrOne = fopen ("name.txt","r"))==NULL)
    {
       printf ("Cannot open file.\n");
       exit(0);
    }
    for(i=0;i<maxNames;i++)
    {
       fscanf(fptrOne,"%s\n", name[i]);
    }

    fclose(fptrOne);
}
/*************************************************/
void outputNames (char name[maxNames][nameLength])
{
    int i;
    for(i=0;i<maxNames;i++)
    {
       printf("%s\n", name[i]);
    }
}
/*************************************************/
void inputResults (char name[maxNames][nameLength],float table[tableRows][tableColumns])
{
    FILE *fptrTwo;
    int i,t,pos=-1,j;
    char temp[100];
    if ((fptrTwo = fopen ("results.txt","r"))==NULL)
    {
       printf ("Cannot open file.\n");
       exit(0);
    }
    while(!feof(fptrTwo))//for(i=0;i<maxNames;i++)
    {
       fscanf(fptrTwo,"%s %d\n",temp, &t);
       pos=-1;
       for(j=0;j<maxNames;j++)
       {
        if(strcmp(name[j],temp)==0) {pos=j;break;}
       }
       if(pos!=-1)
       {
       table[pos][4]+=t;
       table[pos][0]+=1;
       }
    }

    fclose(fptrTwo);
}
/*************************************************/

void outputResults (char name[maxNames][nameLength],float table[tableRows][tableColumns])
{
    int i,j;
    for(i=0;i<tableRows;i++)
    {
     printf("%s ",name[i]);
     for(j=0;j<tableColumns;j++)
     {
       printf("%f ",table[i][j]);
     }
     printf("\n");
    }

}
For round wise results:


int main ()
{

    char name[maxNames][nameLength];
    float table[tableRows][tableColumns]={0.0};

    inputNames (name);
    outputNames (name);
    inputResults (name,table);
    //outputResults (name,table);
    //dont call outputresults from here
    return 0;
}

void inputResults (char name[maxNames][nameLength],float table[tableRows][tableColumns])
{
    FILE *fptrTwo;
    int i,t,pos=-1,j;
    int flag=0;
    char temp[100];
    if ((fptrTwo = fopen ("results.txt","r"))==NULL)
    {
       printf ("Cannot open file.\n");
       exit(0);
    }
    while(!feof(fptrTwo))//for(i=0;i<maxNames;i++)
    {
       fscanf(fptrTwo,"%s %d\n",temp, &t);
       pos=-1;

       if(strcmpi(temp,"round")==0)
       {
        if(flag==0) flag++;
        else
        {
         printf("\nRound %d results\n",flag);
         flag++;
          outputResults (name,table);
        }
       }
       for(j=0;j<maxNames;j++)
       {
        if(strcmp(name[j],temp)==0) {pos=j;break;}
       }
       if(pos!=-1)
       {
       table[pos][4]+=t;
       table[pos][0]+=1;
       }
    }

    fclose(fptrTwo);
    printf("\nRound %d results\n",flag);//Last round results
    outputResults (name,table);
}
Thank you all for the help, but i have 1 more question, i'm still studying ankuratvb last codes. The last question is say in round 1 alice 17 defeated alexander 13, i need help to find the winner so i can reward them the points.

Well,here it is:

void inputResults (char name[maxNames][nameLength],float table[tableRows][tableColumns])
{
    FILE *fptrTwo;
    int i,t,pos=-1,pos2=-1,j;
    int flag=0;
    char temp[100];
    if ((fptrTwo = fopen ("results.txt","r"))==NULL)
    {
       printf ("Cannot open file.\n");
       exit(0);
    }
    while(!feof(fptrTwo))//for(i=0;i<maxNames;i++)
    {
       fscanf(fptrTwo,"%s %d\n",temp, &t);
       pos=-1;
       //pos2=-1;
       if(strcmpi(temp,"round")==0)
       {
        if(flag==0) flag++;
        else
        {
         printf("\nRound %d results\n",flag);
         flag++;
          outputResults (name,table);
        }
       }
       for(j=0;j<maxNames;j++)
       {
        if(strcmp(name[j],temp)==0) {pos=j;break;}
       }
       if(pos!=-1)
       {
       table[pos][4]+=t;
       table[pos][0]+=1;
       if(pos2==-1) pos2=pos;
       else
       {
        if(table[pos][4]>table[pos2][4])
        {table[pos][1]+=1;table[pos2][2]+=1;table[pos][5]+=2;}
        else if(table[pos][4]==table[pos2][4])
        {table[pos][3]+=1;table[pos2][3]+=1;table[pos][5]+=1;table[pos2][5]+=1;}
        else
        {table[pos2][1]+=1;table[pos][2]+=1;table[pos2][5]+=2;}
        pos2=-1;
       }
       }
    }

    fclose(fptrTwo);
    printf("\nRound %d results\n",flag);
    outputResults (name,table);
}

If you have trouble undersvoid inputResults (char name[maxNames][nameLength],float table[tableRows][tableColumns])
{
    FILE *fptrTwo;
    int i,t,pos=-1,pos2=-1,j;
    int flag=0;
    char temp[100];
    if ((fptrTwo = fopen ("results.txt","r"))==NULL)
    {
       printf ("Cannot open file.\n");
       exit(0);
    }
    while(!feof(fptrTwo))//for(i=0;i<maxNames;i++)
    {
       fscanf(fptrTwo,"%s %d\n",temp, &t);
       pos=-1;
       if(strcmpi(temp,"round")==0)
       {
        if(flag==0) flag++;
        else
        {
         printf("\nRound %d results\n",flag);
         flag++;
          outputResults (name,table);
        }
       }
       for(j=0;j<maxNames;j++)
       {
        if(strcmp(name[j],temp)==0) {pos=j;break;}
       }
       if(pos!=-1)
       {
       table[pos][4]+=t;
       table[pos][0]+=1;
       if(pos2==-1) pos2=pos; //store previous position
       else
       {//pos has one position,pos2 has the other,compare their avg and set points
        if(table[pos][4]>table[pos2][4])
        {table[pos][1]+=1;table[pos2][2]+=1;table[pos][5]+=2;}
        else if(table[pos][4]==table[pos2][4])
        {table[pos][3]+=1;table[pos2][3]+=1;table[pos][5]+=1;table[pos2][5]+=1;}
        else
        {table[pos2][1]+=1;table[pos][2]+=1;table[pos2][5]+=2;}
        pos2=-1;
       }
       }
    }

    fclose(fptrTwo);
    printf("\nRound %d results\n",flag);
    outputResults (name,table);
}
Under inputResults (char name[maxNames][nameLength],float table[tableRows][tableColumns]), I have made some changes, i took out points awarded to the winner, and replaced it by points scored against them += each round. I thought i understood the code but it only worked for the 1st round, and the numbers gets a bit to large afterwards. I put ********* next to the bit i changed/added.

while(!feof(fptrTwo))//for(i=0;i<maxNames;i++)
    {
      fscanf(fptrTwo,"%s %d\n",temp, &t);
      pos=-1;
      //pos2=-1;
      if(strcmpi(temp,"round")==0)
      {
       if(flag==0) flag++;
       else
       {
        printf("\nRound %d results\n",flag);
        flag++;
         outputResults (name,table);
       }
      }
      for(j=0;j<maxNames;j++)
      {
       if(strcmp(name[j],temp)==0)
         {
               pos=j;
         }
        }
      if(pos!=-1)
      {
      table[pos][4]+=t;
      table[pos][0]+=1;
      if(pos2==-1)
              pos2=pos;
      else
      {
              if(table[pos][4]>table[pos2][4])
              {
                    table[pos][1]+=1;
                    table[pos2][2]+=1;
                    table[pos][5]+=table[pos2][4];*******************************
                    table[pos2][5]+=table[pos][4];*******************************
              }
              else
                    if(table[pos][4]==table[pos2][4])
              {
                    table[pos][3]+=1;
                    table[pos2][3]+=1;
                    table[pos][5]+=table[pos2][4];*******************************
                    table[pos2][5]+=table[pos][4];*******************************
              }
              else
                    if(table[pos][4]<table[pos2][4])
              {
                    table[pos2][1]+=1;
                    table[pos][2]+=1;
                    table[pos2][5]+=table[pos][4];********************************
                    table[pos][5]+=table[pos2][4];********************************

              }
              pos2=-1;
        }
        }
      }
So,now in the points column,you want to store the points scored against the player rather than points score by him?
ASKER CERTIFIED SOLUTION
Avatar of ankuratvb
ankuratvb
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thank you all for helping.