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 byopen
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 andexit
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 usingfprintf
to the standard streamstderr
. Then terminate the program. - Call the function of the previous exercise from your
main
function. Useargv[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.
- Elaborate your format string such that
- If
fscanf
signals an error useperror
/exit
us usual. - If
fscanf
signals the end of the file using the return valueEOF
, initialize the star using the initialization function that you have developed in the previous exercise and returnfalse
. - 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 thatstrncpy
takes an argument n and that at most n characters are copied. Note that you can apply thesizeof
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?
- Recall how
- 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
orfor
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 tellsgdbgui
(and also regulargdb
) 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