#include <stdio.h>
#include <string.h>
#include "import_register.h"
void print_person(int index, personal_data *data);
void print_all_data(int count, personal_data *data);
void search_by_first(char *first, int count, personal_data *data);
void search_by_last(char *last, int count, personal_data *data);
void search_by_age(int age, int count, personal_data *data);
void search_by_town(char *town, int count, personal_data *data);
void search_by_sex(int sex, int count, personal_data *data);
int main(int argc, char *argv[])
{
int count; /* håller reda på antalet element i vektorn 'data' */
personal_data *data; /* vektorn 'data' som lagrar alla personer */
int run; /* variabel för while loopen */
int choice; /* variabel för menyval, ålder och kön */
char string[BUFSIZ]; /* sträng för sökning av namn och stad */
/* när programmet exekveras är det som du säkert vet funktionen 'main'
som körs först. när man exekverar ett program i kommandotolken (eller
terminalen som den kallas i linux) kan man ange parametrar, som till
exempel när du anropar kompilatorn;
$ gcc -ansi -pedantic -Wall main.c import_register.c
där '-ansi', '-pedantic', '-Wall', 'main.c' och så vidare alla är
sådana parametrar.
antalet sådana parametrar lagras som du kanske vet i variabeln 'argc'
samtidigt som de olika parametrarna, vilka utgörs av strängar, lagras
i vektorn 'argv'. även om inga parametrar anges när ett program
exekveras så kommer 'argc' alltid vara lika med 1, och 'argv[0]'
innehåller i sin tur programmets sökväg och namn. för att kunna
specificera filen du vill läsa, istället för att hårdkoda filens namn
i koden, så kan du använda denna möjlighet på följande sätt: */
if (argc == 1) {
printf("Usage: %s <file>\n", argv[0]);
return 0;
}
if ((data = import_data(&count, argv[1])) == NULL) {
printf("Failed to import data from %s\n", argv[1]);
return 0;
}
/* nu loopar vi menyn med mer lättförståelig kod; så länge 'run' är sant
det vill säga har ett värde annat än 0 (i detta fallet 1) så körs
loopen om och om igen: */
run = 1;
while (run) {
printf("Register of personal data.\n"
"Make a choice:\n"
" 1. Print all data\n"
" 2. Search by first name\n"
" 3. Search by last name\n"
" 4. Search by age\n"
" 5. Search by town\n"
" 6. Search by sex\n"
" 7. Exit\n"
"Enter choice: ");
scanf("%d", &choice);
/* 'getchar' är nödvändig för att fånga radbrytet som 'scanf'
lämnar kvar i inmatningsströmmen (från ENTER-trycket)... */
getchar();
/* nu anropar vi rätt funktion eller funktioner baserat på
användarens val. observera att det är viktigt med 'break'
efter varje case (förutom efter default som alltid ska vara
det sista alternativet längst ner i switch-satsen). om man
missar ett 'break' efter exempelvis 'case: 1' så kommer koden
automatiskt fortsätta till 'case: 2', vilket betyder att
användaren som bara ville få all data utskriven också gör en
sökning efter förnamn.
oberserva att vi inte använder 'scanf' för inmatning a
strängar, detta då scanf inte bryr sig om hur stor sträng-
vektorn är (i detta fallet 'string'). detta är ett stort
problem då man på så sätt kan skriva data till minne som inte
är avsatt för strängen. istället används 'fgets' tillsammans
med 'strcspn' för inmatning, där 'strcspn' används för att
ta bort radbrytet (från ENTER-trycket). */
switch (choice) {
case 1:
print_all_data(count, data);
break; /* viktigt... */
case 2:
printf("Enter first name: ");
fgets(string, BUFSIZ, stdin);
string[strcspn(string, "\n\r")] = '\0';
search_by_first(string, count, data);
break; /* ...med... */
case 3:
printf("Enter last name: ");
fgets(string, BUFSIZ, stdin);
string[strcspn(string, "\n\r")] = '\0';
search_by_last(string, count, data);
break; /* ...'break'... */
case 4:
printf("Enter age: ");
scanf("%d", &choice);
search_by_age(choice, count, data);
break; /* ...efter... */
case 5:
printf("Enter town: ");
fgets(string, BUFSIZ, stdin);
string[strcspn(string, "\n\r")] = '\0';
search_by_town(string, count, data);
break; /* ...varje... */
case 6:
printf("Enter sex (0 = Man, 1 = Woman): ");
scanf("%d", &choice);
search_by_sex(choice, count, data);
break; /* ...'case'... */
case 7:
run = 0;
break; /* ...förutom... */
default:
printf("Invalid choice\n");
break; /* ...här. men det ser bra ut. */
}
}
free_data(data, count);
return 0;
}
void print_person(int index, personal_data *data)
{
/* skriv ut all information om en specifik person. eftersom variabeln
'sex' i strukturen 'personal_data' är av typen 'int' så gör jag
antagandet att män har värdet 0, och kvinnor värdet 1, detta beror
dock helt och hållet på hur funktionen 'import_data' är kodad. */
printf("%s\n%s\n%d\n%s\n%s\n\n",
data[index].first,
data[index].last,
data[index].age,
data[index].town,
((data[index].sex == 0)) ? "Man" : "Woman");
return;
}
void print_all_data(int count, personal_data *data)
{
/* skriv ut all information om alla personer, i detta fallet i bakvänd
ordning. */
while (count--)
print_person(count, data);
return;
}
void search_by_first(char *first, int count, personal_data *data)
{
/* loopa igenom alla personer i 'data' och skriv ut all information om
personerna med samma förnamn som eftersöks. observera att 'strcmp' är
shiftlägeskänslig, dvs. 'andreas' är inte samma sak som 'ANDREAS'. */
while (count--)
if (strcmp(first, data[count].first) == 0)
print_person(count, data);
return;
}
void search_by_last(char *last, int count, personal_data *data)
{
/* TODO */
return;
}
void search_by_age(int age, int count, personal_data *data)
{
/* TODO */
return;
}
void search_by_town(char *town, int count, personal_data *data)
{
/* TODO */
return;
}
void search_by_sex(int sex, int count, personal_data *data)
{
/* TODO */
return;
}