Reading the Database

Download the Star Database

You can download the star database from here. Save it in the same directory as your C source code stars.c under the name stars.csv.

The input file use a format commonly called CSV, for comma-separated values. It is a simple form of a database, stored in a text file. Each line represents an entry in the data base, while columns hold different fields of an entry. The columns are separated by some delimiter symbol (often ',', ';', '\t', or ' ').

In our case the columns are separated by simple commas (','), where each column represents the following property of the star:

  • The star's numeric ID.
  • The star's textual identifier, which is composed of the constellation and the star's name.
  • The star's distance from Earth in Parsecs.
  • The star's magnitude.

You may open the CSV file in an editor or have a quick peak on the first couple of lines on the command line using the following command:

tp-5b07-26:> head stars.csv
676,And:Alpheratz ,29.744200,2.070000
744,Cas:Caph ,16.784201,2.280000
1065,Peg:Algenib ,120.047997,2.830000
2076,Phe:Ankaa ,25.974001,2.400000
2914,Cas:Fulu ,181.818207,3.690000
3172,Cas:Schedar ,69.978996,2.240000
3413,Cet:Diphda ,29.533400,2.040000
3814,Cas:Achird ,5.953100,3.460000
4412,Cas:Castula ,61.274502,4.620000
4417,Cas:Cih ,168.350204,2.150000

First off, you need to determine the number of entries in the CSV file. This can be done on the command line using the command wc. Look up the manual page (man page) of wc and find out how you can determine the number of lines in the CSV file. Command line tools are described in Section 1 of the manual page system (contrary to library functions you have seen before, which are described in Section 3). Write down the number you have obtained, you'll need it in one of the the following exercises.

Opening the Star Database File

In order to read information from the star database you have to open the file (and finally close the file) using the functions you have seen in the lecture. Implement the following function, which is supposed to read all stars of a CSV database:

  • Use a meaningful function name in your code.
  • The function takes a single argument, a constant string indicating the database's filename.
  • The function does not return any value.
  • Open the star database using the provided filename, i.e., the input string. The file is only used for reading all the information from the beginning of the file. Store the FILE pointer returned by open in a local variable.
  • Immediately close the file using the function fclose.
  • Check for errors in both cases and use use perror to print an error message and exit to terminate the program.

Implementing the main Function

The goal is now to open the star database file using a filename that is provided on the command line when you run your program. For this you should call the function you have developed above from the main function and process the command-line arguments in argv/argc.

  • First, remove the test code from the previous exercises in the main function (you may leave the test functions themselves in the code, they might be useful if you run into problems later).
  • Check that the value of argc is equal to 2. If this is not the case print a short error message using fprintf to the standard streamstderr. Then terminate the program.
  • Call the function of the previous exercise from your main function. Use argv[1] as the filename.
  • return EXIT_SUCCESS.

The main function should not contain any other code, i.e., comment or remove the function calls that you used for testing your code so far.

Test your code from the command line by running your program with different command-line arguments, e.g.:

./stars
./stars wrongfile.csv
./stars stars.csv

Make sure that your code compiles without errors or warnings and verify that the code prints error messages as expected.

Reading a Star

Now implement a function that reads a single star with all its information from the star database, i.e., reads a single line from the CSV file.

  • Use a meaningful function name in your code.
  • The function takes two arguments, a pointer to a FILE structure and a pointer to a star structure.
  • The function returns a boolean value.
  • You should use the fscanf function in order to read from the file.
  • Read the different columns following the CSV file format and store the information in local variables/arrays:
    • Elaborate your format string such that fscanf skips any white spaces in-between columns.
    • Elaborate your format string such that fscanf skips the comma (',') in-between columns.
    • Read the star identifier into a local array and chose the array size sufficiently large to store the constellation (up to 3 characters), the star name (up to 20 characters), the delimiter, and any additional characters needed to represent strings properly. Be careful to indicate the size of the local array in the format string in order to avoid a buffer overflow.
    • Use the appropriate format string for numerical values depending on the data format stored in the CSV file.
  • If fscanf signals an error use perror/exit us usual.
  • If fscanf signals the end of the file using the return value EOF, initialize the star using the initialization function that you have developed in the previous exercise and return false.
  • Otherwise assign the obtained values to the star structure to which points the second function argument:
    • Initialize the star structure using the initialization function that you have developed in the previous exercise.
    • Be careful to assign a value to all members of the star structure -- recall the member access operator for pointers (->).
    • Use casts where necessary.
    • You will notice that the star identifier is stored as a combined string in the CSV file, while the structure has two different members. Use the splitPrefix function to split the name into two strings:
      • Recall how splitPrefix works.
      • After calling splitPrefix the null-terminated string stored in the local array will represent the constellation, ...
      • ... while the returned pointer represents the star's name.
      • However, you cannot assign the pointer/local array to the members of the star structure directly.
      • Instead you have to use strncpy to copy the respective strings into the structure members. Recall that strncpy takes an argument n and that at most n characters are copied. Note that you can apply the sizeof operator on expressions.
      • What happens when strncpy did not reach the end of its input string? Do you have to modify your code to handle this situation?
    • Return true.
  • Don't forget to add the necessary lines with #include at the beginning of your file.

Reading all the Stars

Go back to the function that opens/closes the star database. In-between the calls to open and close insert the following code:

  • Use a while or for loop in order to read all stars from the file.
  • Declare a local array within this function (chose a meaningful name) that stores star structures and has static storage duration. Chose the size of the array such that all entries from the CSV file can be stored in the array.
  • Call the function you have just implemented in order to read individual stars and check its return value in order to determine whether you should stop or not.
  • Store the stars in the order that they appear in the star database in the local array.
  • Once a star has been read print it using the print function that you have implemented in a previous exercise and the standard stream stdout.

Debugging the Read function

In order to make sure that the code from before works as expected, lets debug it:

  • Start gdbgui on the command line as follows. The --args option tells gdbgui (and also regular gdb) that the remaining arguments are the program and its command-line arguments:
/comelec/softs/bin/gdbgui --args ./stars ./stars.csv
  • Set a breakpoint after the call to fscanf in the function that reads an individual star.
  • Verify that the local variables (after calling fscanf!) have the expected values for the first couple of stars in the CSV database.
    • gdbgui displays character arrays as a sequence of integer numbers (and not as string).
    • However, you may use the command shell at the bottom of the graphical interface. Simply type the command print followed by the name of your local char array to inspect the content of the entire array. The result is also displayed in the command shell.
    • Single step until your reach the call to splitPrefix and verify that it works as expected by printing the constellation and name.
  • Now set a breakpoint inside the while loop of the function that reads all stars.
  • Verify that the content of the array is correct. Inspect the first star in the array, look at the values of all of its members. Notably, check the constellation and name using the print command on the command shell at the bottom of the graphical interface.

Test

Make sure your program compiles without any errors or warnings. Let it run on the command line and verify that your program produces the same output as below:

   676 And  29 +2.07 Alpheratz
   744 Cas  16 +2.28 Caph
  1065 Peg 120 +2.83 Algenib
  2076 Phe  25 +2.40 Ankaa
  2914 Cas 181 +3.69 Fulu
  3172 Cas  69 +2.24 Schedar
  3413 Cet  29 +2.04 Diphda
  3814 Cas   5 +3.46 Achird
  4412 Cas  61 +4.62 Castula
  4417 Cas 168 +2.15 Cih
  5337 Phe  91 +3.94 Wurren
  5436 And  60 +2.07 Mirach
  5725 Psc  53 +5.21 Revati
  6397 And  65 +4.87 Adhil
  6672 Cas  30 +2.66 Ruchbah
  7083 Psc 107 +3.62 Alpherg
  7499 And  13 +4.10 Titawin
  7574 Eri  42 +0.45 Achernar
  7593 And  54 +3.59 Nembus
  8183 Psc  85 +4.26 Torcular
  8777 Tri  19 +3.42 Mothallah
  8813 Ari  50 +3.88 Mesarthim
  8867 Cas 126 +3.35 Segin
  8884 Ari  17 +2.64 Sheratan
  9618 And 120 +2.10 Almach
  9861 Ari  20 +2.01 Hamal
 10800 Cet  91 +6.47 Mira
 11734 UMi 132 +1.97 Polaris
 12673 Cet  24 +3.47 Kaffaljidhma
 13176 Ari  50 +3.61 Bharani
 13234 Per 269 +3.77 Miram
 13254 Eri  57 +4.76 Angetenar
 13667 Eri  41 +3.89 Azha
 13813 Eri  49 +2.88 Acamar
 14100 Cet  76 +2.54 Menkar
 14540 Per  27 +2.09 Algol
 14632 Per  34 +3.79 Misam
 14802 Ari  52 +4.35 Botein
 14843 For  14 +3.80 Dalim
 15159 Eri  33 +4.80 Zibal
 15824 Per 155 +1.79 Mirfak
 16496 Eri   3 +3.72 Ran
 17406 Per 343 +3.84 Atik
 17447 Tau 115 +5.45 Celaeno
 17457 Tau 124 +3.72 Electra
 17489 Tau 125 +4.30 Taygeta
 17532 Tau 117 +3.87 Maia
 17537 Tau 114 +5.76 Asterope
 17566 Tau 116 +4.14 Merope
 17661 Tau 123 +2.85 Alcyone
 17805 Tau 117 +3.62 Atlas
 17809 Tau 117 +5.05 Pleione
 18497 Eri  62 +2.97 Zaurak
 18567 Per 381 +3.98 Menkib
 19538 Eri  37 +4.04 Beid
 19799 Eri   4 +4.43 Keid
 20483 Eri  90 +3.97 Beemim
 20837 Tau  44 +3.53 Ain
 20842 Tau  46 +3.40 Chamukuy
 21340 Eri  65 +3.81 Theemin
 21368 Tau  20 +0.87 Aldebaran
 21541 Eri  33 +3.86 Sceptrum
 22396 Ori   8 +3.19 Tabit
 22961 Aur 151 +2.69 Hassaleh
 23361 Aur 653 +3.03 Almaaz
 23398 Aur 240 +3.69 Saclateni
 23712 Aur  74 +3.18 Haedus
 23820 Eri  27 +2.78 Cursa
 24378 Ori 264 +0.18 Rigel
 24549 Aur  13 +0.08 Capella
 25273 Ori  77 +1.64 Bellatrix
 25364 Tau  41 +1.65 Elnath
 25542 Lep  49 +2.81 Nihal
 25865 Ori 212 +2.25 Mintaka
 25920 Lep 680 +2.58 Arneb
 26142 Ori 336 +3.39 Meissa
 26176 Ori 714 +2.75 Hatysa
 26246 Ori 606 +1.69 Alnilam
 26386 Tau 136 +2.97 Tianguan
 26569 Col  80 +2.65 Phact
 26662 Ori 225 +1.74 Alnitak
 27298 Ori 198 +2.07 Saiph
 27559 Col  26 +3.12 Wazn
 27919 Ori 152 +0.45 Betelgeuse
 28288 Aur  24 +1.90 Menkalinan
 28309 Aur  50 +2.65 Mahasim
 28962 Col 221 +5.00 Elkurud
 29582 Gem 117 +3.31 Propus
 30049 CMa 111 +3.02 Furud
 30251 CMa 151 +1.98 Mirzam
 30270 Gem  71 +2.87 Tejat
 30365 Car  94 -0.62 Canopus
 31601 Gem  33 +1.93 Alhena
 32161 Gem 259 +3.06 Mebsuta
 32263 CMa   2 -1.44 Sirius
 32276 Gem  17 +3.35 Alzirr
 33492 CMa 124 +1.50 Adhara
 33769 CMa 343 +3.49 Unurgunite
 33956 CMa 135 +4.11 Muliphein
 34000 Gem 421 +4.01 Mekbuda
 34354 CMa 492 +1.83 Wezen
 35453 Gem  18 +3.50 Wasat
 35806 CMa 609 +2.45 Aludra
 36087 CMi  49 +2.89 Gomeisa
 36744 Gem  15 +1.58 Castor
 37159 Gem  50 +4.89 Jishui
 37173 CMi   3 +0.40 Procyon
 37718 Gem  10 +1.16 Pollux
 38062 Pup 367 +3.34 Azmidi
 39318 Pup 332 +2.21 Naos
 39644 Pup  19 +2.83 Tureis
 40411 Cnc  93 +3.53 Tarf
 40766 Cnc 140 +5.92 Piautos
 40921 Car 185 +1.86 Avior
 40959 Lyn 117 +4.25 Alsciaukat
 41586 UMa  54 +3.35 Muscida
 42283 Hya 114 +4.45 Minchir
 42437 Cnc 179 +6.29 Meleph
 42794 Vel  24 +1.93 Alsephina
 42990 Hya  39 +3.38 Ashlesha
 43464 Cnc  12 +5.96 Copernicus
 43939 Cnc  57 +4.26 Acubens
 44000 UMa  14 +3.12 Talitha
 44343 UMa 109 +3.57 Alkaphrah
 44689 Vel 166 +2.23 Suhail
 44819 Cnc 114 +5.16 Nahn
 45106 Car  34 +1.67 Miaplacidus
 45425 Car 234 +2.21 Aspidiske
 45809 Vel 175 +2.47 Markeb
 46259 Hya  55 +1.99 Alphard
 46339 UMa  85 +5.40 Intercrus
 46617 Leo 100 +4.32 Alterf
 47297 Hya  80 +3.90 Ukdah
 47373 Leo  39 +3.52 Subra
 48219 Hya  80 +4.11 Zhang
 48318 Leo  38 +3.88 Rasalas
 48478 Hya 188 +4.94 Felis
 49528 Leo  24 +1.36 Regulus
 50193 Leo  84 +3.43 Adhafera
 50440 Leo  39 +2.01 Algieba
 53075 LMi  29 +3.79 Praecipua
 53565 UMa  14 +5.03 Chalawan
 53584 Crt  48 +4.08 Alkes
 53754 UMa  24 +2.34 Merak
 53905 UMa  37 +1.81 Dubhe
 54712 Leo  17 +2.56 Zosma
 54718 Leo  50 +3.33 Chertan
 56044 Dra 102 +3.82 Giausar
 57226 UMa  56 +3.69 Taiyangshou
 57459 Leo  10 +2.14 Denebola
 57584 Vir  10 +3.59 Zavijava
 57828 UMa  25 +2.41 Phecda
 58777 Cam  97 +5.78 Tonatiuh
 59020 Crv  14 +4.02 Alchiba
 59565 Cru 105 +2.79 Imai
 59592 UMa  24 +3.32 Megrez
 59621 Crv  47 +2.58 Gienah
 59945 Vir  81 +3.89 Zaniah
 60075 Cru  70 +3.59 Ginan
 60530 Cru  98 +0.77 Acrux
 60776 Crv  26 +2.94 Algorab
 60893 Cru  27 +1.59 Gacrux
 61124 CVn   8 +4.24 Chara
 61166 Crv  44 +2.65 Kraz
 61748 Vir  11 +2.74 Porrima
 62228 Dra 227 +5.43 Tianyi
 62239 Cru  85 +1.25 Mimosa
 62757 UMa  25 +1.76 Alioth
 62876 Dra  29 +5.23 Taiyi
 62890 Vir  60 +3.39 Minelauva
 63405 Vir  33 +2.85 Vindemiatrix
 64037 Com  17 +4.32 Diadem
 65173 UMa  26 +2.23 Mizar
 65269 Vir  76 +0.98 Spica
 65272 UMa  25 +3.99 Alcor
 66040 Vir  22 +3.38 Heze
 67088 UMa  31 +1.85 Alkaid
 67711 Boo  11 +2.68 Muphrid
 68483 Cen 120 +0.61 Hadar
 68537 Dra  92 +3.67 Thuban
 68714 Cen  18 +2.06 Menkent
 69205 Vir  78 +4.18 Kang
 69451 Boo  11 -0.05 Arcturus
 69479 Vir  22 +4.07 Syrma
 69510 Boo  30 +4.18 Xuange
 69751 Vir  57 +4.52 Khambalia
 70532 Vir  36 +4.81 Elgafar
 70851 Boo  26 +3.04 Seginus
 71453 Cen   1 +1.35 Toliman
 71879 Boo  62 +2.35 Izar
 72261 Boo  48 +5.76 Merga
 72380 UMi  40 +2.07 Kochab
 72396 Lib  23 +2.75 Zubenelgenubi
 73327 Boo  69 +3.49 Nekkar
 73486 Lib  88 +3.25 Brachium
 74556 Lib  56 +2.61 Zubeneschamali
 74868 UMi 149 +3.00 Pherkad
 75182 Boo  34 +4.31 Alkalurops
 75229 Dra  31 +3.29 Edasich
 75466 CrB  34 +3.66 Nusakan
 76035 CrB  23 +2.22 Alphecca
 76100 Lib  50 +3.91 Zubenelhakrabi
 76835 Ser  22 +2.63 Unukalhai
 77214 Ser 117 +4.09 Gudja
 77868 Sco 144 +3.87 Iklil
 78029 Sco 179 +2.89 Fang
 78165 Sco 150 +2.29 Dschubba
 78580 Sco 123 +2.56 Acrab
 78804 Her 112 +5.00 Marsic
 79134 Sco 145 +4.00 Jabbah
 79870 Sco 213 +2.90 Alniyat
 80089 Dra  28 +2.73 Athebyne
 80221 Her  76 +4.57 Cujam
 80519 Sco 169 +1.06 Antares
 80571 Her  42 +2.78 Kornephoros
 80593 Her  79 +8.15 Ogma
 80637 Oph  53 +3.82 Marfik
 81020 Sco 145 +2.82 Paikauhale
 82022 TrA 119 +1.91 Atria
 82144 Sco  19 +2.29 Larawag
 82263 Sco 153 +3.00 Xamidimura
 82294 Sco 145 +3.56 Pipirima
 83351 Dra  27 +4.91 Alrakis
 83638 Dra 100 +3.17 Aldhibah
 83755 Oph  27 +2.43 Sabik
 84086 Her 110 +2.78 Rasalgethi
 84121 Her  23 +3.12 Sarin
 84147 Oph   5 +4.33 Guniibuu
 85410 Dra 116 +2.79 Rastaban
 85433 Her 113 +4.41 Maasym
 85436 Sco 176 +2.70 Lesath
 85560 UMi  52 +4.35 Yildun
 85665 Sco 175 +1.62 Shaula
 85769 Oph  14 +2.08 Rasalhague
 85965 Sco  92 +1.86 Sargas
 86347 Dra  22 +4.57 Dziban
 86475 Oph  25 +2.76 Cebalrai
 86515 Dra 163 +5.75 Alruba
 86529 Ara  15 +5.12 Cervantes
 86991 Sco  38 +3.19 Fuyue
 87314 Dra  34 +3.73 Grumium
 87561 Dra  47 +2.24 Eltanin
 88361 Sgr  29 +2.98 Alnasl
 90065 Dra  96 +4.82 Fafnir
 90979 Lyr   7 +0.03 Vega
 92133 Lyr 294 +3.52 Sheliak
 92471 Sgr 344 +4.86 Ainalrami
 92564 Sgr  69 +2.05 Nunki
 92654 Ser  47 +4.62 Alya
 92902 Lyr 190 +3.25 Sulafat
 93213 Sgr  27 +2.60 Ascella
 93452 Aql  25 +2.99 Okab
 93819 CrA  38 +4.11 Meridiana
 93846 Sgr 156 +2.88 Albaldah
 94081 Dra  29 +3.07 Altais
 94186 Lyr 425 +4.43 Aladfar
 95052 Sgr  55 +3.96 Rukbat
 95473 Vul  91 +4.44 Anser
 95648 Cyg 133 +3.05 Albireo
 95799 Dra   5 +4.67 Alsafi
 96450 Sge 130 +4.39 Sham
 96858 Cyg  50 +2.86 Fawaris
 96970 Aql 121 +2.72 Tarazed
 97338 Aql   5 +0.76 Altair
 97627 Aql  56 +4.71 Libertas
 97725 Aql  13 +3.71 Alshain
 97755 Sgr  25 +4.70 Terebellum
 99743 Cap  32 +3.58 Algedi
 99985 Cap  77 +4.77 Alshat
100020 Cap 100 +3.05 Dabih
100128 Cyg 561 +2.23 Sadr
100425 Pav  54 +1.94 Peacock
101095 Del 101 +4.03 Aldulfin
101442 Del  30 +3.64 Rotanev
101629 Del  77 +3.77 Sualocin
101767 Cyg 432 +1.25 Deneb
102157 Cyg  22 +2.48 Aljanah
102287 Aqr  63 +3.78 Albali
103195 Del  75 +5.51 Musica
104649 Equ  58 +3.92 Kitalpha
104861 Cep  15 +2.45 Alderamin
105691 Cep 210 +3.23 Alfirk
105936 Aqr 164 +2.90 Sadalsuud
106444 Aqr  54 +4.68 Bunda
106642 Cap  48 +3.69 Nashira
106795 Cyg 529 +4.69 Azelfafage
106972 Peg 211 +2.38 Enif
107742 Gru  64 +3.00 Aldhanab
108573 Cep  29 +4.26 Kurhah
108728 Aqr 160 +2.95 Sadalmelik
108922 Gru  30 +1.73 Alnair
109081 Peg  28 +3.52 Biham
109657 Aqr  57 +4.17 Ancha
110049 Aqr  50 +3.86 Sadachbia
111359 Aqr  65 +5.04 Situla
111676 Peg  62 +3.41 Homam
111768 Gru  54 +2.07 Tiaki
111804 Peg  65 +2.93 Matar
112389 Peg  32 +3.51 Sadalbari
112776 Aqr  49 +3.27 Skat
112997 Peg  15 +5.45 Helvetios
113008 PsA   7 +1.17 Fomalhaut
113521 Peg  60 +2.44 Scheat
113529 Psc 125 +4.48 Fumalsamakah
113603 Peg  40 +2.49 Markab
114887 Peg  49 +4.58 Salm
115258 Peg  52 +4.42 Alkarab
115711 And  79 +5.22 Veritate
116361 Cep  14 +3.21 Errai
119058 Sco  24 +4.84 Graffias
119127 Dra  23 +5.63 Alrakis