Google Answers Logo
View Question
 
Q: c program project help ( Answered 5 out of 5 stars,   0 Comments )
Question  
Subject: c program project help
Category: Computers > Programming
Asked by: derekwtp-ga
List Price: $10.00
Posted: 15 Mar 2003 20:13 PST
Expires: 14 Apr 2003 21:13 PDT
Question ID: 176811
I guess it's all about project interpretation, but I am first
struggling to determine how to interpret this. But while I am slowly
interpreting this I am getting segmentation errors on the little that
I have done. Here is the project description:
 Your instructor is an avid baseball card collector. So, he must keep
track of the cards he needs to complete his sets. To this end he has a
list of cards that he needs from each year in a separate file. These
files are named according to the card manufacturer and the year. For
example, "topps.52" contains a list of all the cards he needs to
complete his 1952 Topps set. One day, a friend takes the time to enter
all of your instructors lists into his data base and generate a list
of card numbers with the player name. This list is all in one file
called "want.names". Since that day, your instructor has updated only
his numbered lists. Now, your job is to write a C program that will
update the player name list according to the data in the topps.xx
files. All the data is in the directory ~smcgowan/Cyber/PS/Cards You
can copy the entire directory with the command:
%cp -r ~smcgowan/Cyber/PS/Cards .
Remember that unix is case sensitive and note that the dot (.) at the
end must be preceded by a space. It refers to the current directory
you are in when you execute the cp command. This is where the copy of
the directory will be created.
Conditions:

   1. The program should expect a list of 2-digit years on the command
line. These numbers will represent the topps.xx files that need to be
opened and processed. You may use the file name "want.names" in the
source code, but use it only once (make a #define constant for it).
   2. If there are cards from a particular year listed in "want.names"
but there is no topps.xx file for that year, then that year should not
be included in the output.
   3. The output should look just like the file "want.names" (of
course with many fewer names)
   4. Do not consider the possibility that there is a number listed in
the topps.xx file and not listed in the want.names file. You don't
need to make your code handle this situation.
   5. Make sure you follow all good programming practices. Use good
variable and constant names. Format (indent) your code properly. Use
comments where needed, not to few, not too many. Put each function in
it's own file. Make sure each file/function has a comment header with
who/what/why information at the top. Put all structure definitions in
an include file. NO GLOBAL VARS! All information that any function
needs should come from the function parameter list.
   6. This program should have no standard input. The output should go
to standard output, so the original file "want.names" will remain
unchanged. To save your output (the new list of names) use the unix
output redirect char >. EX:
      project1 53 55 56 57 58 61 62 63 64 66 67 > new.names
   7. You should email me a copy of the source for each function and a
copy of the file "new.names"



this is what I have so far:


 #include<stdio.h>
 #include"baseball.h"

 main()
 {
 void readwants(ball*,char*,int);
 ball* baseball;
 char nambo[30];
 int num=4;
 strcpy(nambo,"want.names");
 

 readwants(baseball,nambo,num);
 }

struct baseball
{
char name[50];
int date;
int number;
};
typedef struct baseball ball;


#include<stdio.h>
 #include"baseball.h"
 
 void readwants (ball baseball[50],char fn[],int numofelem)
{

 FILE *fp;
 char tmp[30];
 int i;

   /* try to open the file */
  if(!(fp=fopen(fn,"r"))) {
    printf("%s does not exits, starting with empty list\n",fn);

    return;
  }

  for(i=0;i<numofelem;i++){
    fscanf(fp,"%s %d",tmp,&baseball[i].date);
    strcpy(baseball[i].name,tmp);
    printf ("%s %d",&baseball[i].name,&baseball[i].date); }



  
  fclose(fp);
  printf ("this is the end of readlist\n");


 }


any guidance from one of you pros would be great.

Request for Question Clarification by answerguru-ga on 15 Mar 2003 23:39 PST
Hi Derek,

Could you also provide your baseball.h file that you are including in your program?

Thanks,
answerguru-ga
Answer  
Subject: Re: c program project help
Answered By: jeanluis-ga on 16 Mar 2003 06:19 PST
Rated:5 out of 5 stars
 
Seg faults, these are caused by tring to access memory that is not
allocated. (or should i say mallocated hehe :) From visual inspection
it appears that your  1st seg fault is in the following line in
readwants():

fscanf(fp,"%s %d",tmp,&baseball[i].date);

This is because in your main function you declare 
ball* baseball;

then you pass baseball into readwants() then you try and access
baseball in readwants() but you never allocated any memory for
baseball... I advise either using malloc() to alloc some memory to
baseball in your main function as follows:

ball* baseball = (ball*)malloc(sizeof(ball) * 50);

Note the I multiply the sizeof(ball) by 50 because that is the length
of the array readwants expects.
OR declaring baseball as an array of length 50 in main. Doing either
one of these things should clear up all the seg faults. Note: I was
not able to test compile the program, but I don't see anything else
off hand.

Let me know if you have any other questions, comments, concerns.
Thanks,
--jld

Request for Answer Clarification by derekwtp-ga on 16 Mar 2003 11:52 PST
sorry . I didnt give you the rest of it, before I do here is my output
now after memory allocation. It still is not giving me the desired
result.

[root@localhost first_p]# ./one
line above readwants
want.names
beginning of readwants function
want.names
1967 134518900
Topps 134518960
baseball 134519020
Killebrew 134519080
this is the end of readlist


struct baseball
{
char name[50];
int date;
int number;
};
typedef struct baseball ball;


some of the file "want.names"

1967 Topps baseball
460    Killebrew
536    Niekro
543    Schneider
546    Woodward
553    Hegan
554    Rodgers
559    Tracewski
562    Blass
567    Hamilton
568    Sullivan
569    Carew
570    Wills
577    Short
578    Boccabella
580    Colavito
585    Bunker
586    Jimenez
590    Richert
593    Westrum
594    Osinski
597    Abernathy
603    Rookies
606    Taylor
607    Stanley

1966 Topps baseball
472    Fox

Request for Answer Clarification by derekwtp-ga on 16 Mar 2003 16:02 PST
okay. i have gotten around the last time, but I am not sure if even
though i am getting desired output if this is the right way to right
it. My next function is supposed to compare the files so that I can
print a list w/ the updated information. I am supposed to used stacks
and push and pop. do you know where i can find a good reference to use
this in this scenario?


updated main and twofuctions

 main()
 {
 void readwants(ball*,char*);
 void readtopps(ball*,char*);
 ball* baseball = (ball*)malloc(sizeof(ball) * 1000);
 char nambo[50];
 int num=4;
 strcpy(nambo,"want.names");
 
 printf ("line above readwants\n");
 printf ("%s\n",nambo);
 readwants(baseball,nambo);

#include<stdio.h>
 #include"baseball.h"
 
 
 void readwants (ball baseball[1000],char fn[])
{

 FILE *fp;
 char tmp[30];
 int i = 0;

 printf ("beginning of readwants function\n");
 printf ("%s\n",fn);
   /* try to open the file */
  if(!(fp=fopen(fn,"r"))) {
    printf("%s does not exits, starting with empty list\n",fn);

    return;
  }
     while (fscanf(fp,"%s %s",tmp,&baseball[i].number)!=EOF) {
    strcpy(baseball[i].name,tmp);
    printf ("%s %s \n",&baseball[i].name,&baseball[i].number); ++i; }



  
  fclose(fp);
  printf ("this is the end of readlist\n");


 }
 #include<stdio.h>
 #include"baseball.h"
 

 void readtopps (ball baseball[1000],char fn[])
{

 FILE *fp;
 char tmp[30];
 int i = 0;

 printf ("beginning of readtopps function\n");
 printf ("%s\n",fn);
   /* try to open the file */
  if(!(fp=fopen(fn,"r"))) {
    printf("%s does not exits, starting with empty list\n",fn);

    return;
  }
     while (fscanf(fp," %s ",&baseball[i].number)!=EOF) {
     printf ("%s \n",&baseball[i].number); ++i; }




  fclose(fp);
  printf ("this is the end of readtopps\n");


 }

Clarification of Answer by jeanluis-ga on 16 Mar 2003 16:45 PST
Push and pop are very simple functions, while I dont know a very
*good* reference for these functions you should be able to implement
them with out a problem.
Here is the best reference I could come up with:
 "The C Programming Language", 2nd edition, Kernighan and Ritchie
Answer to Exercise 4-5, page 79
http://users.powernet.co.uk/eton/kandr2/krx405.html

In there you can find (very short) push and pop functions, I am sure
you will not have a problem figuring out how they work. For your
functions you can basically use the exact same functions implemented
in the above link, except use ball rather than doubles for your
"stack" (i.e. where they declare double val[MAXVAL]; you would declare
ball val[MAXVAL];)

I hope this helps, but you know the drill, please let me know if you
have any other questions, comments, concerns, etc... :)
Thanks again,
--jld

Clarification of Answer by jeanluis-ga on 16 Mar 2003 16:47 PST
By the way, so far everything looks good (except your main function
doesn't have a closing brace, but I assume that is a cut+paste
error...)
Thanks
--jld

Request for Answer Clarification by derekwtp-ga on 17 Mar 2003 11:07 PST
What I am trying to do on this function is compare the two structures
and print out the name and number of only the numbers that appear in
both lists. Ill give you what I have as far as functions starting w/
the one I need help w/

this function is killing me cuz my logic must be wayyyy offff

void compare(Player plays[],Player top[])

 {
   int x = 0;
   int i = 0;
   
   do
   {
   if (plays[x].cardnum == top[i].cardnum)
   {
     printf ("%d %s\n",plays[x].cardnum,plays[x].name);
     x++;
     }
   else if (plays[x].cardnum != top[i].cardnum)
   {i++;}
   }
   while (plays[x].cardnum > 0);
   }



here is main

main()
 {
 int readwants(Player*,char*,int);
 int readtopps(Player*,char*);
 void compare(Player*,Player*);
 Player* baseball = (Player*)malloc(sizeof(Player) * 1000);
 Player* bigtopps = (Player*)malloc(sizeof(Player) * 1000);
 char nambo[50];
 char tango[50];
 int num = 52;
 strcpy(nambo,"want.names");
 strcpy(tango,"topps.52");
 
 printf ("line above readwants\n");
 printf ("%s\n",nambo);
 readwants(baseball,nambo,num);
 readtopps(bigtopps,tango);
 compare(baseball,bigtopps);
 
 }

 #include<stdio.h>
 #include"player.h"
 
int readtopps (Player topps[],char fn[])
{

 FILE *fp;
 char tmp[30];
 int i = 0;

 printf ("beginning of readtopps function\n");
 printf ("%s\n",fn);
   /* try to open the file */
  if(!(fp=fopen(fn,"r"))) {
    printf("%s does not exits, starting with empty list\n",fn);

    return;
  }
     while (fscanf(fp," %s ",&topps[i].cardnum)!=EOF) {
     printf ("%s \n",&topps[i].cardnum);  }
     



  fclose(fp);
  printf ("this is the end of readtopps\n");

  return(i);


 }

#include <stdio.h>
#include "player.h"

int readwants(Player* p, char* wantfn, int year)
{
  FILE* fp;
  char fn[CHARS];
  int i=0,wantyear,count;

  fp=fopen(wantfn,"r");

/*read first line from want.names*/
  fscanf(fp,"%d %*[^\n]%*c",&wantyear);

/* do loop executes until you have read the year of interest */
  do{
    if (wantyear == year + 1900){

/* this do loop reads the number and name until it finds the
   beginning line for the next year  */
      do{
        fscanf(fp,"%d %s ",&p[i].cardnum,p[i].name);
        printf ("%d %s \n",p[i].cardnum,p[i].name); 
        i++;
      }while (!feof(fp) && p[i-1].cardnum < 1900);
/* for every year except the last one in the file, you will have 
   read one line too far, so adjust count if you need to */
      if (p[i-1].cardnum > 1900) count=i-1; else count=i;
      wantyear= -1;

    }else{
/* here is where we go if the year did not match... first
   we read a line, then do the while loop to keep reading
   until we find another "year" value  ie > 1900  */
      fscanf(fp,"%d %*[^\n]%*c",&wantyear);
      while(wantyear < 1900){
        fscanf(fp,"%d %*[^\n]%*c",&wantyear);
      }
    }
  }while(!feof(fp) && wantyear!= -1);
  return (count);
}


#define wantfile "want.names"
#define CHARS 80
#define MAX 200
struct PLAYER {
    int cardnum;
    char name[CHARS];
};
typedef struct PLAYER Player;




here is a copy of the files that will be read from: first is a
topps.xx file

1952 Topps baseball
-------------------
  8  10  15  17  20  47  48  49  59  71  136
153 155 159 162 168 170 175 176 186 188 202
215 233 248 252 253 254 257 259 264 270 271 272 274
282 283 284 285 287 293 294 295 297 299 300 308 310 311
312 314 315 316 317 319 320 321 322 323 324 325 327 328 329
330 332 333 334 335 336 338 339 341 342 343 344 345 346
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
362 363 364 365 366 367 368 370 372 373 374 375 376 377
378 379 380 381 382 383 384 387 388 391 392 393 394
397 398 399 400 401 402 403 405 406 407


second is only a snippet of the want.names for 1952

1952 Topps baseball
4    Lenhardt
8    Marsh
9    Hogue
10    Rosen
11    Rizzuto
14    Elliott
15    Pesky
17    Hegan
20    Loes
22    DiMaggio
34    Valo
36    Hodges
37    Snider
42    Kretlow
47    Jones
48    Page
49    Sain
59    Roberts
66    Roe
71    Upton
72    Olson
74    Hansen
77    Kennedy
86    Gray
98    Pierce
99    Woodling
136    Schmitz
142    Perkowski
146    House
151    Post
152    Evans
153    Rush
154    Muir
155    Overmire
159    Rogovin
162    Crandall
166    LaPalme
168    Silvera
169    Judson
170    Bell
173    Smalley
175    Martin
176    Edwards
182    Hitchcock
184    Ramazzotti
186    Masterson
188    Podbielan
190    Johnson
192    Ginsberg
197    Strickland
199    Zuverink
202    Collins
205    King
215    Bauer
216    Ashburn
222    Evers
223    Ennis
227    Garagiola
230    Batts
233    Friend
237    Coleman
242    Poholsky
243    Doby
244    Wertz
247    Gumpert
248    Shea
250    Erskine
252    Bickford
253    Berardino
254    Dobson
256    Suder
257    Avila
258    Gromek
259    Addis
264    Hartsfield
267    Gordon
268    Lemon
269    Nixon
270    Brissie
271    Selsing
272    Garcia
273    Palica
274    Branca
276    Wilson
277    Wynn
279    Stewart
280    Boyer
281    Brown
282    Tebbetts
283    Masi
284    Arft
285    Fannnin
286    DeMaestri
287    Bilko
288    Nichols
289    Holmes
293    Sisti
294    Cooper
295    Caverretta
296    Rolfe
297    Seminick
299    Murray
300    McCosky
301    Porterfiel
302    Surkont
303    Dorish
304    Dente
305    Richards
307    Campos
308    Aloma
309    Busby
310    Metkovich
311    Mantle
312    Robinson

Clarification of Answer by jeanluis-ga on 17 Mar 2003 12:23 PST
Ok I dont have much time right now but I can give you a few quick
pointers, and I can come back later on tonight with more details I
hope that is ok.

Ok the 1st thing I would do is in your readtopps() function read the
cardnum as an integer (it is not a string)

Next: As you read in each file keep track of the number of entries you
read. Then use the number of entries in each file in the compare
function to setup some nested for loops as follows:
for (x = 0; x < num_in_wants_file; x++) {
   for (i = 0; i < num_in_topps_file; i++) {
   }
}

Inside that nested loop all you have to do is compare the cardnum of
the topps and the wants and if they are the same then you have a hit.
:)
If you have any other Q's let me know 
thanks --jld

Request for Answer Clarification by derekwtp-ga on 17 Mar 2003 12:45 PST
When I change the string to an integer I get output like:

136784800
136784884
136784968
136785052
136785136
136785220
136785304
136785388
136785472
136785556
136785640
136785724
136785808
136785892
136785976
136786060
136786144
136786228
136786312
136786396
136786480
136786564
136786648

 while (fscanf(fp,"%i",&topps[i].cardnum)!=EOF) {
     printf ("%i \n",&topps[i].cardnum);++i; }
                   


That is why i used %string. it never showed invalid output

Clarification of Answer by jeanluis-ga on 17 Mar 2003 13:34 PST
That is because in your printf statement you are printing the address
of cardnum... You want to print the contents of cardnum...
That means remove the & when you print the cardnum as an integer... :)
Let me know if you have any other questions, comments, concerns. 
  Thanks, 
  --jld

Request for Answer Clarification by derekwtp-ga on 17 Mar 2003 16:56 PST
sorry I meant to show you this output. Dont want you to think i dont t/shoot : )


beginning of readtopps function
topps.52
1952
0
0
0
0
0
0
0
0
0

and here is my function

while (fscanf(fp,"%d",&topps[i].cardnum)!=EOF) {
     printf ("%d \n",topps[i].cardnum);++i; }
                   

Also could you explain you explaination above w/ the embedded for loop?

-Derek

Clarification of Answer by jeanluis-ga on 18 Mar 2003 05:13 PST
The readtopps function you have now, gets all messed up with the
"header" (1952 Topps baseball). the function works perfectly for me
when I remove that line from the file, but produces the output you
described when I put the header back in...
So what you should do is read the 1st line in first, then read the
contents of the file with the loop you currently have.

And for the compare() function you want to do something like this:
for (x = 0; x < num_in_wants_file; x++) { 
   for (i = 0; i < num_in_topps_file; i++) { 
      if (??? == ???) {
         printf("%i %s\n", ???.cardnum, ???.name);
      }
   } 
} 

Where you loop through each cardnum in the wants array, with each
cardnum in the topps array. When they are equal then you record the
cardnum and name. (i.e. print them out) Above I provided an outline of
what the loop should look like, that will print a list of numbers and
names of people in both topps and wants... Which now that I have gone
back and re-read the assignment I am not sure that is what your prof
is looking for. Does he want a list of people that are in both files?
Or a list of people that are in wants but not in topps? If he wants
the latter then you can use very similar logic to what I have above,
but you must change it a bit to weed out the names in the wants list.I
will let you work on this for a little while, and see how far you can
get... If you need more help let me know... Also please clarify
exactly what the results are supposed to be, Thanks,
--jld

Request for Answer Clarification by derekwtp-ga on 18 Mar 2003 06:27 PST
He is looking for the list of people that are on both lists, printed
to standard output by name and number since only one list has the
names. I am reading the rest of you reply now. thanks. I know the
drill : )

Request for Answer Clarification by derekwtp-ga on 18 Mar 2003 13:11 PST
Looking at the format, do you understand why this is saying "parse
error before fclose?"


  #include<stdio.h>
 #include"player.h"
 
int readtopps (Player topps[],char fn[])
{

 FILE *fp;
 char temp[30];
 int i = 0;

 printf ("beginning of readtopps function\n");
 printf ("%s\n",fn);
   /* try to open the file */
  if(!(fp=fopen(fn,"r"))) {
    printf("%s does not exits, starting with empty list\n",fn);

    return;}       
     fscanf (fp,"%s %s %s",&temp,&temp,&temp);
     fscanf (fp,"%s %s %s",&temp,&temp,&temp);
     
     do{(fscanf(fp,"%d",&topps[i].cardnum)!=EOF); 
     printf("%d \n",topps[i].cardnum);++i; }  
   fclose(fp);
  printf("this is the end of readtopps\n");

  return(i);


 }

Clarification of Answer by jeanluis-ga on 18 Mar 2003 13:41 PST
Because you need a semicolon after:
printf("%d \n",topps[i].cardnum);++i; }

Typically parse errors are caused by missing semicolons, or
miss-matched braces, or something like that... Whenever you see a
generic syntax or parse error message from your compiler you should
always check your semicolons, braces, spelling and stuff like that in
the lines just before the error is reported.
Let me know if you have any other questions, comments, concerns.  
  Thanks,  
  --jld

Clarification of Answer by jeanluis-ga on 18 Mar 2003 13:57 PST
Whoops: your do loop is not formatted correctly what you want is
something more like this:
while (fscanf(fp,"%d",&topps[i].cardnum)!=EOF) {

}

Sorry about that last comment, I was in a rush, and I didn't have time
to really look at the code. Then I went back and did a double take and
noticed that I was totally wrong and way off base.. :)
fewf..  This is a good time to mention coding style, most people
adhear to some kind of coding style that makes the code easy to read.
Some simple rules to follow are: All code in the same scope is
indented to the same level. Closing braces are on a newline. One
semicolon per line. Just things like that to make the code easier to
read. :)
Thanks,
--jld

Request for Answer Clarification by derekwtp-ga on 18 Mar 2003 17:46 PST
Jean, this still does not get the required result. any ideas?

int readtopps (Player topps[],char fn[])
{

 FILE *fp;
 char temp[30];
 int i = 0;

 printf ("beginning of readtopps function\n");
 printf ("%s\n",fn);
   /* try to open the file */
  if(!(fp=fopen(fn,"r"))) {
    printf("%s does not exits, starting with empty list\n",fn);

    return;}       
    fscanf (fp,"%s",&temp);
     fscanf (fp,"%s",&temp); 
     
   while (fscanf(fp,"%d",&topps[i].cardnum)!=EOF) 
     {printf("%d \n",topps[i].cardnum); ++i; }
      
  fclose(fp);
  printf("this is the end of readtopps\n");

  return(i);


 }

Clarification of Answer by jeanluis-ga on 18 Mar 2003 19:28 PST
Well it is still the same problem as before really... The header is
messing the function up... You added 2 fscanfs but they only read in
the next word on the input stream. So when you do this:
 fscanf (fp,"%s",&temp); 
 fscanf (fp,"%s",&temp);

What you are reading is 1952 in the 1st fscanf, and Topps in the
second fscanf... When what you want is to read in everything up to the
newline. To do this you might want to consider replacing the fscanfs
with fgets() calls...
Here is a link to the docs for fgets:
"Stdio: fgets"
http://www.cplusplus.com/ref/cstdio/fgets.html

As you can see fgets reads upto the number of chars you specify, or
until a newline, which would make it ideal for this situation. :)
Thanks again, 
--jld
derekwtp-ga rated this answer:5 out of 5 stars
Thanks again Jeanluis

Comments  
There are no comments at this time.

Important Disclaimer: Answers and comments provided on Google Answers are general information, and are not intended to substitute for informed professional medical, psychiatric, psychological, tax, legal, investment, accounting, or other professional advice. Google does not endorse, and expressly disclaims liability for any product, manufacturer, distributor, service or service provider mentioned or any opinion expressed in answers or comments. Please read carefully the Google Answers Terms of Service.

If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you.
Search Google Answers for
Google Answers  


Google Home - Answers FAQ - Terms of Service - Privacy Policy