Struct listing , member delete - c

i'm a freshman computer engineering student. When i preparing an program to store students' info in a C program, some problems appeared.
screen : http://imgim.com/5025incii2829330.jpg
I've added two students and deleted first student's info. But first student's info still appears as empty.
here's the code : http://pastebin.com/R6rSXaft

In your orgListele function, you are iterating through an array of students in order to print out the information. Your for loop prints information like so:
for (i = 0; i<sayi; i++)
{
printf("\n\nStudent:%d\n", i + 1);
printf("ID:%s\n ", listeler[i].id);
printf("National ID:%s\n", listeler[i].tckimlik);
printf("Name:%s\n", listeler[i].isim);
printf("Address:%s\n", listeler[i].adres);
printf("Phone Number:%s\n", listeler[i].telefonnum);
}
It looks like you are not really deleting students from the array (not possible, anyways), just clearing their information. You have created the list of liste structures as an array rather than a list with variable size. When you iterate through it, you are printing the students, even if their information has been cleared.
To achieve the output that you want, I would do one of two things:
Use a linked list and delete the nodes that you want. When you traverse the list to print everything out, you will not be using deleted nodes because they are not referenced by your list any more. The array implementation does not offer this "deletion" aspect. It will also allow this application to scale past 30 students (which is a limitation posed by your array, declared as struct liste listeler[30];. This is the approach I would take. See here for some information on linked lists.
Add another flag to your liste struct to maintain deletion state. If you add something that acts as a boolean value, say int isValid, you will be able to clear that variable (make it 0) for the next time you run through the loop. Then, you can say if (listeler[i].isValid) {//print everything} and skip over those students who have been marked as invalid (isValid = 0)

change
for (i = 0; i<sayi; i++) //kayit sayisi degismediginden
{
printf("\n\nStudent:%d\n", i + 1);
printf("ID:%s\n ", listeler[i].id);
printf("National ID:%s\n", listeler[i].tckimlik);
printf("Name:%s\n", listeler[i].isim);
printf("Address:%s\n", listeler[i].adres);
printf("Phone Number:%s\n", listeler[i].telefonnum);
}
to
for (i = 0; i<sayi; i++) //kayit sayisi degismediginden
{
if(listeler[i].id == 0) contnue; // skip the element if id is zero (zero idicates deleted item)
printf("\n\nStudent:%d\n", i + 1);
printf("ID:%s\n ", listeler[i].id);
printf("National ID:%s\n", listeler[i].tckimlik);
printf("Name:%s\n", listeler[i].isim);
printf("Address:%s\n", listeler[i].adres);
printf("Phone Number:%s\n", listeler[i].telefonnum);
}

You don't keep track of which structures are "empty" or not, you always print all up to the limit imposed by the sayi global variable.
The simple solution is to skip printing those with an empty id, for example, or some other field.

Setting the variable's value to NULL doesn't delete the variable... It simply makes it null. Consider looking into dynamic memory allocation, and using the free() method when you want to delete a student, which has been malloced.

You have removed the information about the student, but you have not deleted the record. You need to delete the record and adjust the list (listeler) so that there are no empty entries within the entries contained.

Related

How to have a certain number of variables acordding to a main variable

I'm developing a program that asks you how many disciplines you have. Next it ask the name and the grade of each;
First asks how many disciplines, and after:
printf("\nInsira o nº de disciplinas: ");
scanf("%i", &NDISCIPLINAS);
for(i=0;i<=NDISCIPLINAS;i++)
{
puts("Name of discipline: ");
scanf("%s", disciplina);
printf("Grade: \n");
scanf("%d", &notas);
}
But It's not that what I really want.
I want the program to save each discipline and grade into a different variable.
Cause then I will want to fprintf the info to a specific file and it would be more easier if the info is well gathered.
My real question is basically:
IF i have 5 disciplines,how can I display the name and the grade of each,line by line, into a file?
thanks guys really strugglin' here
There are numerous ways, you can achieve your goal. I'll suggest you the three of them, which are popping in my mind right now:
Use 2 character arrays, scan values and then store them into the file. Then reuse them (using sentinel loop).
Use a dynamic structure array, which contains two members in it(Name, Grade), and use any function store(name, grade) to store values.
Get the no. of disciplines from the user in any int variable, then using a loop, get value from the user and store it directly to the file, within the loop.

How to remove elements from Struct

I am wondering how the previously entered info can be deleted using decrement.
case 4: printf("Remove Employee\n");
printf("===============\n");
do{
printf("Enter Employee ID: ");
scanf("%d", &number);
int i;
for(i=0;i<NOE; i--){
if(number == emp[i].Int_Num){
printf("Employee %d will be removed", emp[i].Int_Num);
// for(i=0;i<NOE; i++){
-- emp[i].Int_Num, --emp[i].Salary, --emp[i].Age;
// scanf("%11lf", &emp[i].Salary);
flag = 1;
break;
The typical data structure for a collection whose number of elements changes frequently, in arbitrary order, is a linked list. (Or, if you need faster access and have an order criteria like your employee number, a sorted tree). You would allocate new elements (here: employees) with malloc() and truly remove them from memory with free.
Alternatively, if there is a known maximum number of employees and you have enough memory you can use an array, which you appear to do here. The number of elements in the array would be the expected maximum number of employees; the program would therefore always need the maximum amount of memory, even with very few employees. On the other hand the memory footprint of the program would be statically known at compile time which can be an advantage.
The number of elements in an array cannot be changed (unless you allocate the whole array dynamically and reallocate if and when needed). Adding new employees or deleting existing ones would be done, as Bo Persson suggested, through a marker for those elements which are in use. That could be an extra boolean flag, or a special value in one of the existing fields.
In effect though you will be programming your own crude dynamic memory management that way, using the array as an "arena". It will probably be more buggy and slower than if you just used the built-in one.

comparing to arrays and returning the item that's missing?

I am not sure why I am not able to get this right, I spend some time on this, and I don't get what I want. and now I am upset. I have a list LL[] of desired items, and a list seenLL[] which may contain items from LL[], but in any random order. I wanted to put the missing items in unseen[] and then print unseen. At-least that is my idea :(
unsigned int i=0, j=0, k=0;
unsigned int LL[] = {0xB173,0xB193,0xB14D,0xB14E}; //Desired items
unsigned int seenLL[5]; // Seen items
unsigned int unseen[5]; // For unseen items
printf("\n List of Logcodes seen in filtered view :");
for(i=0;i<view->numFilters;i++){ // I can't explain this, as it's BIG
if(flt->filterType == LOGCODE_TYPE ){
printf(" 0x%04X,",flt->code); // This will print the list of items in the view. Usually about 2 or 3 items
seenLL[k]=flt->code; // Copy them to seenLL[]
k++;
}
}
k=0;
// At this point though my seenLL[] has a few of my desired items, it also contains junk information, which I am unable to explain.
for(i=0;i<sizeof(LL)/sizeof(LL[0]);i++){
for(j=0;j<sizeof(seenLL)/sizeof(seenLL[0]);j++){
if(LL[i] != seenLL[j]){
unseen[k]=LL[i]; // I was trying to copy to unseen[] items that are missing from the desired list LL[]
k++;
}
//else{ // Dumb, but what if seenLL[] had items from LL[] but not in the same order as they are in the array LL[], it can occur in any order
// if(sizeof(unseen)/sizeof(unseen[0])!=0)
// if(LL[i] == unseen[i]{
// k--;
// unseen[i]=0;
// }
}
}
if(k>0) printf(" Missing Logs Pkts :");
if(k>0) for(i=0;i<sizeof(unseen)/sizeof(unseen[0]);i++) //sigh! my pathetic attempt to print missing items.
printf("%d,",unseen[i]);
You must scan the seenLL array for each element of LL but properly detect if the element has been seen:
for (i = 0;i < sizeof(LL) / sizeof(LL[0]); i++) {
for (j = 0; j < sizeof(seenLL) / sizeof(seenLL[0]); j++) {
if (LL[i] == seenLL[j])
break;
}
if (j >= sizeof(seenLL) / sizeof(seenLL[0])) {
unseen[k++] = LL[i]; // scan went to the end, no match.
}
}
I suggest using the macro countof to clarify your code:
#define countof(a) ((sizeof(a) / sizeof((a)[0]))
The logic is wrong.
What you're doing: For each item in LL: if it is different from some item in seenLL, add it to unseen.
What you should do: For each item in LL: if it is different from every item in seenLL, add it to unseen.
(Another way to think of these two possible logics: the first one checks for some item whether it is the same as every item in seenLL, while the second one checks whether it is the same as some item in seenLL. It's clear that the first check cannot succeed if seenLL contains at least two different items.)
Array seenLL has space for only five elements, but there's nothing to suggest or ensure that the number of codes you attempt to record in it will be five or fewer if LL had more than five elements.
Furthermore, after you are done populating seenLL, you discard the value of variable k, which tells you how many of the elements of seenLL actually contain valied data.
Later, you test each element of LL against potentially all the elements of seenLL, possibly including some that do not contain valid data. In fact, you should test against all valid elements but no invalid ones, else you are likely to turn up all elements as unseen (they will fail to match at least one element of seenLL).
Array unseen also has space for only five elements, but there's nothing to suggest or ensure that the number of codes you attempt to record in it will be five or fewer.
Then, at the end, if you in fact did recognize any unseen elements, you print every element of unseen, likely including some that do not contain valid data.

Implementing a Hash Table using C

I am trying to read a file of names, and hash those names to a spot based on the value of their letters. I have succeeded in getting the value for each name in the file, but I am having trouble creating a hash table. Can I just use a regular array and write a function to put the words at their value's index?
while (fgets(name,100, ptr_file)!=NULL) //while file isn't empty
{
fscanf(ptr_file, "%s", &name); //get the first name
printf("%s ",name); //prints the name
int length = strlen(name); // gets the length of the name
int i;
for (i =0; i <length; i++)
//for the length of the string add each letter's value up
{
value = value + name [i];
value=value%50;
}
printf("value= %1d\n", value);
}
No, you can't, because you'll have collisions, and you'll thus have to account for multiple values to a single hash. Generally, your hashing is not really a wise implementation -- why do you limit the range of values to 50? Is memory really really sparse, so you can't have a bigger dictionary than 50 pointers?
I recommend using an existing C string hash table implementation, like this one from 2001.
In general, you will have hash collisions and you will need to find a way to handle that. The two main ways of handling that situation are as follows:
If the hash table entry is taken, you use the next entry, and iterate until you find an empty entry. When looking things up, you need to do similarly. This is nice and simple for adding things to the hash table, but makes removing things tricky.
Use hash buckets. Each hash table entry is a linked list of entries with the same hash value. First you find your hash bucket, then you find the entry on the list. When adding a new entry, you merely add it to the list.
This is my demo-program, which reads strings (words) from stdin, and
deposit into hashtable. Thereafter (at EOF), iterate hashtable, and compute number of words, distinct words, and prints most frequent word:
http://olegh.cc.st/src/words.c.txt
In hashtable, utilized double hashing algorithm.

Deleting rows from a structure

My project was to create a program with a menu that extracts data from a file and arranges it in a structure. Via the menu you are able to insert rows to the end of the structure or delete rows from the structure. The program then copies the structure and saves it to the same file.
So far I have everything working fine except for deleting rows.
Right now my code will just delete the last row of the structure no matter what.
else if( input == 3)
{
int delete;
printf("Enter row number to be deleted:\n");
scanf("%i", &delete);
if( delete > i )
{
printf("ERROR: Please enter a valid integer\n");
}
strcpy(data[delete].First, data[(delete+1)].First);
strcpy(data[delete].Last, data[(delete+1)].Last);
data[delete].Gender = data[(delete+1)].Gender;
data[delete].Age = data[(delete+1)].Age;
data[delete].Weight = data[(delete+1)].Weight;
data[delete].Height = data[(delete+1)].Height;
i = i - 1;
}
The variable i is a counter that keeps track of the number of rows in the structure. The code seems to me like it should replace the data of whatever the input delete is and replace it with the data above it in the structure, however it is not working.
Am I going about this the wrong way?
The variable i is a counter that keeps track of the number of rows …
Since you delete data[delete], the rows are apparently numbered from 0 to i-1. The if error condition delete > i should then rather be delete >= i.
if order isn't important, swap the last element with the one being
removed (unless you're removing the last element, obviously), then
just decrement i by one. No loop required. – WhozCraig
That's right, of course, albeit there is no point in the part of the swap which copies the element being removed to the position of the last element.
If the order is to be preserved, we can also do without an explicit loop:
memmove(data+delete, data+delete+1, (--i-delete) * sizeof *data);

Resources