invalid argument read write file - c

typical beginner's phonebook program, attempting to add read and write to file capabilities. It's not compiling just fine but when I execute either functions 7 or 8, my errorhandler returns "invalid argument"
EDIT* updated code for the whole thing, including several fixes:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct phonebook
{
char cFirstName[20];
char cLastName[20];
char PhoNo[20];
} pb;
//function prototypes
void AddContact (pb * );
void DeleteContact (pb * );
void ShowContacts (pb * );
void FindContact (pb * );
void RandContact (pb * );
void FindContact (pb * );
void DeleteAll (pb *);
void Read (pb *);
void Write (pb *);
char FileName[100];
FILE *pRead;
FILE *pWrite;
int counter = 0;
main ()
{
pb *phonebook;
phonebook = (pb*) malloc(sizeof(pb)*1);
int iChoice = 0;
while (iChoice <= 8)
{
printf("\n-Choose an option- \n");
printf("\n\t(1)\tAdd Contact");
printf("\n\t(2)\tDelete Contact");
printf("\n\t(3)\tShow All Contacts");
printf("\n\t(4)\tSearch for a Contact");
printf("\n\t(5)\tRandom Contact");
printf("\n\t(6)\tDelete All Contacts");
printf("\n\n\t(7)\tWrite contacts to file");
printf("\n\t(8)\tRead contacts from file");
printf("\n\n\t(9)\tExit\n\n\t");
scanf("%d", &iChoice);
if (iChoice == 1)
{
AddContact(phonebook);
}
if (iChoice == 2)
{
DeleteContact (phonebook);
}
if (iChoice == 3)
{
ShowContacts(phonebook);
}
if (iChoice == 4)
{
FindContact(phonebook);
}
if (iChoice == 5)
{
RandContact(phonebook);
}
if (iChoice == 6)
{
DeleteAll(phonebook);
}
if (iChoice == 7)
{
Write(phonebook);
}
if (iChoice == 8)
{
Read(phonebook);
}
if (iChoice == 9)
{
free(phonebook);
return 0;
}
} //end while
} //end main
//function definitions
//add contact
void AddContact (pb * phonebook)
{
counter++; //counter incremented for each entry
realloc(phonebook, sizeof(pb)); //realloc with every new contact
printf("\nFirst Name: ");
scanf("%s", phonebook[counter-1].cFirstName);
printf("Last Name: ");
scanf("%s", phonebook[counter-1].cLastName);
printf("Phone Number: ");
scanf("%s", phonebook[counter-1].PhoNo);
printf("\n\tContact added\n");
}
//delete contact
void DeleteContact (pb * phonebook)
{
int x = 0;
char scrapcFirstName[20]; //strings for deleting original strings
char scrapcLastName[20];
char nullStr[20] = {"\0"};
printf("\nFirst name: ");
scanf("%s", scrapcFirstName);
printf("Last name: ");
scanf("%s", scrapcLastName);
//compare strings
for (x = 0; x < counter; x++)
{
if (strcmp(scrapcFirstName, phonebook[x].cFirstName) == 0)
{
for (x = 0; x < counter; x++)
{
if (strcmp(scrapcLastName, phonebook[x].cLastName) == 0)
{
strcpy(phonebook[x].cFirstName, nullStr);
strcpy(phonebook[x].cLastName, nullStr);
strcpy(phonebook[x].PhoNo, nullStr);
}//end if
else
{
printf("Invalid Input");
}
}//end for
}//end if
} // end for
counter--; // Contact deleted, update counter
printf("Contact Deleted\n");
}
// show phonebook
void ShowContacts (pb * phonebook)
{
int x = 0;
printf("\nPhonebook:\n\n ");
for( x = 0; x < counter; x++)
{
printf("\n(%d)\n", x+1);
printf("Name: %s %s\n", phonebook[x].cFirstName, phonebook[x].cLastName);
printf("Number: %s\n", phonebook[x].PhoNo);
} //end for
}
//Find a specific contact
void FindContact (pb * phonebook)
{
int x = 0;
char TempFirstName[20];
char TempLastName[20];
printf("\nWho are you looking for?");
printf("\n\nFirst Name: ");
scanf("%s", TempFirstName);
printf("Last Name: ");
scanf("%s", TempLastName);
for (x = 0; x < counter; x++)
{
if (strcmp(TempFirstName, phonebook[x].cFirstName) == 0)
{
if (strcmp(TempLastName, phonebook[x].cLastName) == 0)
{
printf("\n%s %s \n%s\n", phonebook[x].cFirstName, phonebook[x].cLastName, phonebook[x].PhoNo);
}
}
}
}
//show a random contact
void RandContact (pb * phonebook)
{
int iRand = 0;
srand(time(NULL));
iRand = rand() % counter;
int x = iRand;
printf("\n%s %s\n", phonebook[x].cFirstName, phonebook[x].cLastName);
printf("%s\n", phonebook[x].PhoNo);
}
//delete all
void DeleteAll (pb * phonebook)
{
int x = 0;
char nullStr[20] = {'\0'};
for ( x = 0; x < counter; x++ )
{
strcpy(phonebook[x].cFirstName, nullStr);
strcpy(phonebook[x].cLastName, nullStr);
strcpy(phonebook[x].PhoNo, nullStr);
--counter;
}
printf("Contacts have been wiped.\n");
}
void Read(pb * phonebook)
{
FILE *pRead;
char name[256];
printf("File to read: ");
gets(name);
pRead=fopen(name,"a");
if(pRead != NULL)
{
printf("Contact List");
while(!feof(pRead)){
fread(phonebook, sizeof (struct phonebook), 1, pRead);
fclose(pRead);
if (!feof(pRead)){
fread(phonebook, sizeof (struct phonebook), 1, pRead);
fclose(pRead);
}
}
}
else{
goto ErrorHandler;
}
exit(EXIT_SUCCESS);
ErrorHandler:
perror("The following error occured");
exit(EXIT_FAILURE);
}
void Write(pb * phonebook)
{
FILE *pWrite;
char name[256];
printf("File to write:");
gets(name);
pWrite=fopen(name,"a");
if(pWrite != NULL)
{
fwrite(phonebook, sizeof (struct phonebook), 1, pRead);
fclose(pWrite);
}
else{
goto ErrorHandler;
}
exit(EXIT_SUCCESS);
ErrorHandler:
perror("The following error occured");
exit(EXIT_FAILURE);
}
It's still giving me the same error, "invalid argument"

In read function you have used pWrite instead of pRead
pWrite=fopen(name,"a");
And checking for EOF condition for pRead
while(!feof(pRead))

The file name is not being set: char name[256]; and then fopen(name,"a") that's why fopen fails.
Apparently gets() does not work after your scanf, correct your scanf on line 49: to scanf("%d\n"
Input in C. Scanf before gets. Problem
The other problems have been already pointed out (*pRead instead of *pWrite), not closing files etc.

Related

How to count the number of collisions in hash table?

Here's the task: "Develop a program for the formation and processing of hash tables, built on the principle of open addressing (private hashing). Practical evaluation of hash tables for the set structure, including the data key N-bit digital code (N >= 10). Explore two probing methods: linear and quadratic. Analyze and calculate the results obtained, first of all, the occurrence of collisons and the search time data for different indicators table coverage ratios"
???For some reason I can't do the last one. I can't count collisions and their output in any way, and calculate the search time. Suggest ideas for the algorithm, plz???
Here`s code:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define LEN 20
typedef struct inform {
char* key, * name;
} INFO;
typedef struct hash_table {
int count, size;
INFO** array;
}HTAB;
INFO* New_Item(char* key, char* name)
{
INFO* result = (INFO*)malloc(sizeof(INFO));
result->key = key;
result->name = name;
return result;
}
void free_item(INFO* item)
{
if (item != NULL)
free(item);
}
HTAB* NewHTAB(int size)
{
HTAB* result = (HTAB*)malloc(sizeof(HTAB));
result->count = 0;
result->size = size;
result->array = (INFO**)malloc(sizeof(INFO*) * size);
memset(result->array, NULL, sizeof(INFO*) * size);
return result;
}
void free_hash_table(HTAB* table)
{
if (table != NULL) {
for (int i = 0; i < table->size; i++) {
INFO* item = table->array[i];
if (item != NULL) free_item(item);
}
free(table->array);
free(table);
}
}
int ht_hasItem(HTAB* table, int idx)
{
return table->array[idx] != NULL;
}
int ht_IsFull(HTAB* table)
{
return table->count == table->size;
}
int Hash_Code(int key, int size)
{
return key % size;
}
int Insert(HTAB* table, char* keycpy, char* namecpy)
{
int result = 0;
char* key = _strdup(keycpy);
char* name = _strdup(namecpy);
if (ht_IsFull(table)) printf("Hash table is FULL!!!");
else {
INFO* item = New_Item(key, name);
int idx = Hash_Code(atoi(key), table->size);
//int h = 1;
while (ht_hasItem(table, idx)) {
idx = Hash_Code(idx + 1, table->size);
}
//idx = Hash_Code(idx + (h*h), table->size);
//h++;
table->array[idx] = item;
table->count++;
}
return result;
free(key);
free(name);
}
void Display(HTAB* table)
{
printf("-------------------------------------------------\n");
for (int i = 0; i < table->size; i++) {
if (ht_hasItem(table, i)) {
INFO* item = table->array[i];
printf(" %d\t| %s\t| %s \t|\n", i, item->key, item->name);
printf("-------------------------------------------------\n");
}
else {
printf(" %d\t| ---\t| \t---\t\t|\n", i);
printf("-------------------------------------------------\n");
};
}
printf("\n");
}
int Search(HTAB* table, char* key)
{
int result = -1;
int idx = Hash_Code(atoi(key), table->size);
// int h = 1;
while (ht_hasItem(table, idx)) {
if (strcmp(table->array[idx]->key, key) == 0) {
result = idx;
break;
}
else idx = Hash_Code(idx + 1, table->size);
//idx = Hash_Code(idx + (h*h), table->size);
//h++;
}
return result;
}
INFO* Remove(HTAB* table, char* key)
{
INFO* result = NULL;
int idx = Search(table, key);
if (idx != -1) {
result = table->array[idx];
table->array[idx] = NULL;
table->count--;
}
return result;
}
int main() {
int itemIdx = 0;
INFO* item = NULL;
HTAB* table = NewHTAB(30);
char name[LEN], key[LEN];
int choice = 0, c;
system("chcp 1251");
FILE* ftxt;
if (!(ftxt = fopen("RGR_2_AP.txt", "r"))) {
puts("\n File not found...\n");
return 0;
}
while (fscanf(ftxt, "%s%s", name, key) == 2)
Insert(table, key, name);
printf("\n Іndex\t| Кey\t| \t NAME\t\t|\n");
Display(table);
do {
printf("MENU-: \n1.Insert new item"
"\n2.Search item"
"\n3.Delet item"
"\n\n Please choose one point-:");
scanf_s("%d", &choice);
switch (choice) {
case 1:
printf("\nEnter name: ");
rewind(stdin);
gets_s(name);
printf("\nВведіть ключ: ");
gets_s(key);
while (strlen(key) < 10) {
printf("\nWrong key");
printf("\nTry again: ");
gets_s(key);
}
Insert(table, key, name);
printf("\n");
Display(table);
break;
case 2:
printf("\nEnter key: ");
rewind(stdin);
gets_s(key);
while (strlen(key) < 10) {
printf("\nWrong key");
printf("\nTry again: ");
gets_s(key);
}
itemIdx = Search(table, key);
if (itemIdx != -1) {
item = table->array[itemIdx];
printf("Item found: (%d, %s, %s)\n", itemIdx, item->key, item->name);
}
else printf("Item not found\n");
break;
case 3:
printf("\nEnter key: ");
rewind(stdin);
gets_s(key);
while (strlen(key) < 10) {
printf("\nWrong key");
printf("\nTry again: ");
gets_s(key);
}
Remove(table, key);
Display(table);
break;
default:
printf("Wrong Input\n");
}
printf("\n Do you want continue(enter 1 if yes)?-:\t");
scanf_s("%d", &c);
} while (c == 1);
free_hash_table(table);
printf("End...\n");
return 0;
}
You could add variables which count collisions in the Insert and Search methods, as well as the run time. You may need to return a list in that case, with the first element being the index, second being the # of collisions, and third being the run time.
Use the chrono library to time your functions.

Searching a name in a text file by ID

I have a text file with 2 lines in it:
Voicu;Catalin;1234;2.32
Diana;Cadar;2345;1.01
I'm trying to make my program search in .txt file the ID (1234 or 2345) and match it to the name. Below is the code I've tried to make, but it won't find the ID in .txt after I write it in first scanf, the first thing that appears is the "else" line.
void alegereStudent(struct student *stud)
{
FILE *scStudenti = fopen("studenti.txt", "a");
char *error;
int i=0,n;
if(scStudenti==NULL)
{
error = strerror(errno);
printf("Fisierul nu poate fi creat: \n %s", error);
}
printf("\nIntroduceti Numele: ");
scanf("%39s", stud->numeStudent);
printf("Introduceti Prenumele: ");
scanf("%39s", stud->prenumeStudent);
printf("Introduceti ID-ul studentului: ");
scanf("%d", &stud->idStudent);
printf("Introduceti Media de admitere: ");
scanf("%f", &stud->medieAdmitere);
fprintf(scStudenti,"<%s>;", stud->numeStudent);
fprintf(scStudenti,"<%s>;", stud->prenumeStudent);
fprintf(scStudenti,"<%d>;", stud->idStudent);
fprintf(scStudenti,"<%.2f>\n", stud->medieAdmitere);
fclose(scStudenti);
}
//
void optiunea_2()
{
printf("\n1.Despre studenti.\n");
printf("2.Despre profesori.\n");
printf("3.Revenire la meniu principal.\n");
printf("\nAlegeti o optiune: ");
scanf("%d",&alegere_opt2);
switch(alegere_opt2)
{
case 1: while(&stud!=NULL)
{
FILE *scStudenti = fopen("studenti.txt", "r");
char *error;
int cautareID;
if(scStudenti==NULL)
{
error = strerror(errno);
printf("Fisierul nu poate fi creat: \n %s", error);
}
printf("\nIntroduceti ID-ul studentului: ");
scanf("%d", &cautareID);
fscanf(scStudenti,"%d",&stud->idStudent);
if(cautareID==&stud->idStudent)
{
printf("Numele Studentului este %s %s",&stud->numeStudent, &stud->prenumeStudent);
}
else
printf("\nAcest ID nu exista!\n");
optiunea_2();
}break;
fprintf(scStudenti,"<%s>;", stud->numeStudent);
fprintf(scStudenti,"<%s>;", stud->prenumeStudent);
fprintf(scStudenti,"<%d>;", stud->idStudent);
fprintf(scStudenti,"<%.2f>\n", stud->medieAdmitere);
fclose(scStudenti);
This makes formatting much more difficult. The output file will contain:
<first>;<last>;<1234>;<0.5>
You want to start with a new file and simplify the output to write:
first;last;1234;0.5
Don't always put & in front of integer. Just use:
if(cautareID == stud->idStudent)
{
...
}
Example:
const char *filename = "studenti.txt";
void alegereStudent()
{
struct student stud;
FILE *scStudenti = fopen(filename, "a");
if(scStudenti == NULL)
{
printf("error\n");
return;
}
printf("\nIntroduceti Numele: ");
scanf("%39s", stud.numeStudent);
printf("Introduceti Prenumele: ");
scanf("%39s", stud.prenumeStudent);
printf("Introduceti ID-ul studentului: ");
scanf("%d", &stud.idStudent);
printf("Introduceti Media de admitere: ");
scanf("%f", &stud.medieAdmitere);
fprintf(scStudenti, "%s;", stud.numeStudent);
fprintf(scStudenti, "%s;", stud.prenumeStudent);
fprintf(scStudenti, "%d;", stud.idStudent);
fprintf(scStudenti, "%.2f\n", stud.medieAdmitere);
fclose(scStudenti);
}
void find_by_id(int id)
{
FILE *fin = fopen(filename, "r");
if(!fin)
return;
int count = 0;
struct student stud;
while(fscanf(fin, "%39[^;];%39[^;];%d;%f\n",
stud.numeStudent, stud.prenumeStudent, &stud.idStudent, &stud.medieAdmitere) == 4)
{
if(id == stud.idStudent)
{
printf("found %s %s\n", stud.numeStudent, stud.prenumeStudent);
}
count++;
}
if(count == 0)
printf("failed to read any record. Start with a new file.\n");
}
int main(void)
{
alegereStudent();
find_by_id(1234);
return 0;
}
If <> characters are added, then read according to that format, you then have to remove the extra <> characters from the string.
void alegereStudent()
{
struct student stud;
...
fprintf(scStudenti, "<%s>;", stud.numeStudent);
fprintf(scStudenti, "<%s>;", stud.prenumeStudent);
fprintf(scStudenti, "<%d>;", stud.idStudent);
fprintf(scStudenti, "<%.2f>\n", stud.medieAdmitere);
fclose(scStudenti);
}
void find_by_id(int id)
{
...
struct student stud;
while(fscanf(fin, "%39[^;];%39[^;];<%d>;<%f>\n",
stud.numeStudent, stud.prenumeStudent, &stud.idStudent, &stud.medieAdmitere) == 4)
{
if(id == stud.idStudent)
{
char *p;
size_t i;
//remove the extra <> characters
p = stud.numeStudent;
if (strlen(p) > 1)
{
for(i = 1; i < strlen(p) - 1; i++)
p[i - 1] = p[i];
p[i - 1] = 0;
}
//remove the extra <> characters
p = stud.prenumeStudent;
if (strlen(p) > 1)
{
for(i = 1; i < strlen(p) - 1; i++)
p[i - 1] = p[i];
p[i - 1] = 0;
}
printf("found %s %s\n", stud.numeStudent, stud.prenumeStudent);
}
count++;
}
if(count == 0)
printf("failed to read any record. Start with a new file.\n");
}
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char const *filename = "test.txt";
FILE *input = fopen(filename, "r");
if (!input) {
fprintf(stderr, "Couldn't open \"%s\" for reading!\n\n", filename);
return EXIT_FAILURE;
}
char name[101];
char surname[101];
int id;
double value;
while (fscanf(input, "%100[^;];%100[^;];%d;%lf%*[\n]", name, surname, &id, &value) == 4) {
if (id == 2345) {
printf("Found \"%s %s\" by id %d\n\n", name, surname, id);
break;
}
}
}

Remove element from struct type

I'm trying to create this function to remove an element of the user's choosing from a pointer struct array type.
Here is my function. I keep getting this error when my code hits this function.
error: incompatible types when assigning to type ‘char[1000]’ from type ‘char *’
PhoneBook[iRecord - 1].cFirstName = PhoneBook[x].cFirstName;
void delete_record(pb *PhoneBook)
{
int x;
int iRecord = 0;
print(PhoneBook);
printf("\nEnter number of record you want to delete: ");
scanf("%d", &iRecord);
printf("\nRecord to be deleted: %d. %s\n", iRecord - 1, PhoneBook[iRecord - 1].cFirstName);
for (x = strlen(PhoneBook[iRecord - 1].cFirstName); x <= strlen(PhoneBook[iRecord - 1].cFirstName); x--) {
PhoneBook[iRecord - 1].cFirstName = PhoneBook[x].cFirstName;
}
printf("\nModified record: %s\n\n",PhoneBook[iRecord - 1].cFirstName);
}
Here's the full code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef struct phonebook {
char cFirstName[1000];
char cLastName[1000];
char cNumber[1000];
} pb;
int entry(pb *);
void modify(pb *);
void delete_record(pb *);
void print(pb *);
void convert_u(char *);
//global variable
int MAX_NAME_ENTRY = 0;
int main()
{
int iResponse = 0;
pb *PhoneBook = (pb *) calloc(0, sizeof(pb));
if (PhoneBook == NULL) {
printf("\nMemory allocation failed.\n\n");
return 1;
}
do {
printf("\nPhonebook Menu\n****************\n\n");
printf("1. Enter new contact\n2. Modify existing contact\n3. Delete contact\n4. Print Phonebook \n5. Exit\n\n");
printf("Please make selection: ");
scanf("%d", &iResponse);
if (iResponse == 1) {
entry(PhoneBook);
}
else if (iResponse == 2) {
modify(PhoneBook);
}
else if (iResponse == 3) {
delete_record(PhoneBook);
//printf("\nWorking on it...\n");
}
else if (iResponse == 4) {
print(PhoneBook);
}
} while (iResponse != 5);
free(PhoneBook);
return 0;
}
int entry(pb *PhoneBook)
{
int x;
char yes_no[] = "YES";
pb *newPhoneBook = realloc(PhoneBook, (10 * sizeof(pb)));
if (newPhoneBook == NULL) {
printf("\nOut of memory!\n\n");
return 1;
}
else {
PhoneBook = newPhoneBook;
}
if (MAX_NAME_ENTRY == 10) {
printf("\nMax Number of names entered.\n");
}
for (x = MAX_NAME_ENTRY; x < 10; x++) {
if (MAX_NAME_ENTRY == 9) {
printf("\nLast entry.\n");
}
if (x > 0) {
system("clear");
printf("\nAnother entry(yes/no)? ");
scanf("%s", yes_no);
convert_u(yes_no);
}
if (strcmp(yes_no, "YES") == 0) {
printf("\nFirst Name: ");
scanf("%s", PhoneBook[x].cFirstName);
printf("\nLast Name: ");
scanf("%s", PhoneBook[x].cLastName);
printf("\nPhone Number: ");
scanf("%s", PhoneBook[x].cNumber);
MAX_NAME_ENTRY++;
}
else if (strcmp(yes_no, "NO") == 0) {
break;
}
}
}
void modify(pb *PhoneBook)
{
int iModify = 0;
char name_num[6] = {'\0'};
print(PhoneBook);
printf("\nWhich entry would you like to modify? ");
scanf("%d", &iModify);
printf("\nModify name or number? ");
scanf("%s", name_num);
convert_u(name_num);
if (strcmp(name_num, "NAME") == 0) {
printf("\nEnter new name: ");
scanf("%s %s", PhoneBook[iModify - 1].cFirstName, PhoneBook[iModify - 1].cLastName);
}
else if (strcmp(name_num, "NUMBER") == 0) {
printf("\nEnter new number: ");
scanf("%s", PhoneBook[iModify - 1].cNumber);
}
}
void delete_record(pb *PhoneBook)
{
int x;
int iRecord = 0;
print(PhoneBook);
printf("\nEnter number of record you want to delete: ");
scanf("%d", &iRecord);
printf("\nRecord to be deleted: %d. %s\n", iRecord - 1, PhoneBook[iRecord - 1].cFirstName);
for (x = strlen(PhoneBook[iRecord - 1].cFirstName); x <= strlen(PhoneBook[iRecord - 1].cFirstName); x--) {
PhoneBook[iRecord - 1].cFirstName = PhoneBook[x].cFirstName;
}
printf("\nModified record: %s\n\n",PhoneBook[iRecord - 1].cFirstName);
}
void print(pb *PhoneBook)
{
int x;
for (x = 0; x < 10; x++) {
if (strlen(PhoneBook[x].cFirstName) == 0 && strlen(PhoneBook[x].cLastName) == 0) {
break;
}
printf("\n%d. Name: %s %s", x + 1, PhoneBook[x].cFirstName, PhoneBook[x].cLastName);
printf("\n Number: %s\n\n", PhoneBook[x].cNumber);
}
}
void convert_u(char *string)
{
int x;
for (x = 0; x < strlen(string); x++) {
string[x] = toupper(string[x]);
}
}
Any suggestions on what I'm doing wrong?
An array name is not a modifiable lvalue. Hence, arrays are not assignable in C.
Quoting C11, chapter §6.5.16
An assignment operator shall have a modifiable lvalue as its left operand.
and regarding the modifiable lvalue, chapter §6.3.2.1
A modifiable lvalue is an lvalue that
does not have array type, [...]
You need to use strcpy() instead to copy the content.
it will not work strcpy, you have to copy the whole record over the other. then realloc the phonebook to new size.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef struct phonebook {
char cFirstName[50];
char cLastName[50];
char cNumber[50];
} pb;
int entry();
void modify();
void delete_record();
void print_record(int rec);
void print();
void convert_u(char *);
//global variables
int MAX_NAME_ENTRY = 0;
pb *PhoneBook = NULL;
#define YES "YES"
#define NO "NO"
const char *menu=
" Phonebook Menu \n"
" **************** \n"
" \n"
" 1. Enter new contact \n"
" 2. Modify existing contact \n"
" 3. Delete contact \n"
" 4. Print Phonebook \n"
" 5. Exit \n"
" \n"
" Please make selection: ";
int main(void){
int iResponse = 0;
do {
printf("%s",menu);
scanf("%d", &iResponse);
switch (iResponse) {
case 1:
entry();
break;
case 2:
modify();
break;
case 3:
delete_record();
break;
case 4:
print();
}
} while (iResponse != 5);
free(PhoneBook);
return 0;
}
int str_input(const char *text, char *buff){
printf("%s" , text);
scanf("%s" , buff);
}
int entry(void)
{
int x;
char yes_no[] = YES;
pb *newPhoneBook;
if (MAX_NAME_ENTRY == 10) {
printf("\nMax Number of names entered.\n");
return 0;
}
while(1) {
newPhoneBook = realloc(PhoneBook,(MAX_NAME_ENTRY +1) * sizeof(pb)) ;
if (!newPhoneBook) {
perror("entry::realloc()");
return 1;
}
PhoneBook = newPhoneBook;
if (MAX_NAME_ENTRY == 9) {
printf("\n *** This is the Last entry. *** \n");
}
printf("RECORD: %d\n",MAX_NAME_ENTRY+1);
str_input("\nFirst Name: " , PhoneBook[MAX_NAME_ENTRY].cFirstName);
str_input("\nLast Name: " , PhoneBook[MAX_NAME_ENTRY].cLastName);
str_input("\nPhone Number: " , PhoneBook[MAX_NAME_ENTRY].cNumber);
MAX_NAME_ENTRY++;
if(MAX_NAME_ENTRY == 10)
break;
printf("\nAnother entry(yes/no)? ");
scanf("%s", yes_no);
convert_u(yes_no);
if (strcmp(yes_no, YES))
break;
system("clear");
}
}
int checkRecordExists(int iRecord){
if(iRecord<1 || iRecord>MAX_NAME_ENTRY){
printf("Record %d do not exists\n",iRecord);
return 0;
}
return 1;
}
void modify(void){
int iModify = 0;
char name_num[6] = {'\0'};
printf("\nWhich entry would you like to modify? ");
scanf("%d", &iModify);
if(!checkRecordExists(iModify))
return;
iModify --;
print_record(iModify);
str_input("\nModify name or number? ", name_num);
convert_u(name_num);
if (strcmp(name_num, "NAME") == 0) {
str_input("\nFirst Name: " , PhoneBook[iModify].cFirstName);
str_input("\nLast Name: " , PhoneBook[iModify].cLastName);
}
else if (strcmp(name_num, "NUMBER") == 0) {
str_input("\nPhone Number: " , PhoneBook[iModify].cNumber);;
}
}
void delete_record(void)
{
int x;
int iRecord = 0;
printf("\nEnter number of record you want to delete: ");
scanf("%d", &iRecord);
if(!checkRecordExists(iRecord))
return;
iRecord--;
MAX_NAME_ENTRY--;
for( x=iRecord;x<MAX_NAME_ENTRY;x++)
memcpy(&PhoneBook[x],&PhoneBook[x+1],sizeof(pb));
PhoneBook = realloc(PhoneBook,(MAX_NAME_ENTRY + 1) * sizeof(*PhoneBook) );
}
void print_record(int rec){
printf("\n"
"%02d. Name: %s %s\n"
" Number: %s\n"
"\n",
rec + 1, PhoneBook[rec].cFirstName, PhoneBook[rec].cLastName, PhoneBook[rec].cNumber);
}
}
void print(void){
int x;
for (x = 0 ; x < MAX_NAME_ENTRY ; x++) {
print_record(x);
}
}
void convert_u(char *string){
while(*string){
*string = toupper(*string);
string ++;
}
}

Sorting array filled with lines of string

I have a data in text like this:
1,jack,3,7.3
2,mike,4,8.6
3,gol,2,9
Could any one help me how to sort the data by the last column that represent the grades in descending using c language?
The question was posted before but with no code so I posted it again to get more help.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
int cid;
char name[40];
char term[2];
double gpa;
}student;
typedef struct
{
char line[300];
}data;
typedef struct
{
int cid;
}finds;
typedef struct
{
double score;
}gpa;
void menu();
int calculateMax(void);
void addStudent();
void find();
void display();
void sort();
int main()
{
menu();
system("PAUSE");
return 0;
}
void menu()
{
int selection;
printf("%s", "Program menu :\n");
printf("%s", "1. Add a new student\n");
printf("%s", "2. Find/retrieve information for a particular Student\n");
printf("%s", "3. Display STUDENTS list\n");
printf("%s", "4. Find a student that has the lowest and the highest deposit\n");
printf("%s", "5. Quit\n");
printf("%s", "Selection : ");
scanf("%d", &selection);
if(selection == 1)
{
addStudent();
}
else if(selection == 2)
{
find();
}
else if(selection == 3)
{
display();
}
else if(selection == 4)
{
sort();
}
else if(selection == 5)
{
exit(0);
}
else {
printf("%s", "\n\aError, please key in correct input!\n\n");
menu();
}
}
void addStudent()
{
int max, i;
FILE *f, *id, *name, *term, *gpa , *sort;
printf("%s", "\n\nADD student\n");
printf("%s", "How many students you would like to add : ");
scanf("%d", &max);
student *student_info;
student_info = (student *) malloc(max * sizeof(student)); /*Allocate Memory For Client's Info*/
if(student_info == NULL)
{
printf("Unable to allocate space for client\n\n");
exit (EXIT_FAILURE);
}
if ((id = fopen("id.txt", "a+")) == NULL) /*Open file id.txt*/
{
printf("Error, the file cannot be opened\n");
}
if ((name = fopen("name.txt", "a+")) == NULL) /*Open file name.txt*/
{
printf("Error, the file cannot be opened\n");
}
if ((term = fopen("term.txt", "a+")) == NULL) /*Open file TERM.txt*/
{
printf("Error, the file cannot be opened\n");
}
if ((gpa = fopen("gpa.txt", "a+")) == NULL) /*Open file GPA.txt*/
{
printf("Error, the file cannot be opened\n");
}
if ((f = fopen("student.txt", "a+")) == NULL) /*Open file STUDENTS.txt*/
{
printf("Error, the file cannot be opened\n");
}
if ((sort = fopen("sort.txt", "a+")) == NULL) /*Open file SORT.txt*/
{
printf("Error, the file cannot be opened\n");
}
else {
for (i = 0; i < max ; i++) { /*Get the input data*/
printf("student %d\n", i + 1);
printf("%s", "student's Id : ");
scanf("%5d", &student_info[i].cid);
printf("%s", "student's Name : ");
fflush(stdin);
gets(student_info[i].name);
printf("%s", "student's term : ");
fflush(stdin);
gets(student_info[i].term);
printf("%s", "student's GPA : ");
scanf("%7lf", &student_info[i].gpa);
printf("\n");
}
}
for(i = 0; i < max; i++) { /*Store input data into files*/
fprintf(id, "%d\n", student_info[i].cid);
fputs(student_info[i].name, name);
fprintf(name, "\n");
fputs(student_info[i].term, term);
fprintf(term, "\n");
fprintf(gpa, "%lf\n", student_info[i].gpa);
fprintf(sort,"%d,%s,%s,%lf\n",student_info[i].cid,student_info[i].name,student_info[i].term,student_info[i].gpa);
}
for(i = 0; i < max; i++) {
fprintf(f, "%d", student_info[i].cid, "");
fprintf(f, "%3s", "");
fputs(student_info[i].name, f);
fprintf(f, "%5s", "");
fputs(student_info[i].term, f);
fprintf(f, "%7s", "");
fprintf(f, "%lf\n", student_info[i].gpa);
}
fclose(f);
fclose(id);
fclose(name);
fclose(term);
fclose(gpa);
fclose(sort);
free(student_info);
student_info = NULL;
printf("\n");
menu();
}
void find()
{
int find_id = 0, i = 0, student_cid, n = 0, max, selection;
FILE *id, *f;
max = calculateMax();
finds *result;
result = (finds *) malloc(max * sizeof(finds));
if(result == NULL)
{
printf("Unable to allocate space for student\n\n");
exit (EXIT_FAILURE);
}
if ((id = fopen("id.txt", "r")) == NULL)
{
printf("Error, the file cannot be opened\n");
}
else {
while (!feof(id)) { /*Get all clients' id number and store to array*/
fscanf(id, "%d", &result[i].cid);
i++;
}
}
fclose(id);
printf("%s", "\n\nFIND STUDENT\n");
printf("%s", "Key in Student's id : "); /*Get the client's id that user want to query*/
scanf("%d", &student_cid);
data *student_info;
student_info = (data *) malloc(max * sizeof(data));
if(student_info == NULL)
{
printf("Unable to allocate space for student\n\n");
exit (EXIT_FAILURE);
}
if ((f = fopen("student.txt", "r")) == NULL)
{
printf("Error, the file cannot be opened\n");
}
i = 0;
while (!feof(f)) { /*Get all the students' data from clients.txt and stored to array*/
fflush(stdin);
fgets(student_info[i].line, 300, f);
i++;
}
fclose (f);
for(i = 0; i < max + 1; i++)
{
if(student_cid == result[i].cid)
{
printf("\n\n%s%6s%20s%17s\n", "ID", "NAME", "TERM", "GPA");
puts(student_info[i].line);
free(student_info);
student_info = NULL;
free(result);
result = NULL;
printf("Would you like to find another student?\nKey in 1 for yes or 2 to go to menu : ");
scanf("%d",&selection);
if(selection == 1) {
find();
}
else if(selection == 2) {
menu();
}
break;
}
else if(i == max)
{
printf("\nSory, there's no student with that exist in database.\n");
free(student_info);
student_info = NULL;
free(result);
result = NULL;
printf("Would you like to find another student?\nKey in 1 for yes or 2 to go to menu : ");
scanf("%d",&selection);
if(selection == 1) {
find();
}
else if(selection == 2) {
printf("\n\n");
menu();
}
}
}
}
void display()
{
int max = 0, i;
FILE *f;
printf("\n\nDISPLAY STUDENT");
max = calculateMax();
data *student_info;
student_info = (data *) malloc(max * sizeof(data));
if(student_info == NULL)
{
printf("Unable to allocate space for student\n\n");
exit (EXIT_FAILURE);
}
if ((f = fopen("student.txt", "r")) == NULL)
{
printf("Error, the file cannot be opened\n");
}
i = 0;
while (!feof(f)) {
fflush(stdin);
fgets(student_info[i].line, 200, f);
i++;
}
fclose (f);
printf("\n\n%s%6s%20s%17s\n", "ID", "NAME", "TERM", "GPA");
for(i = 0; i < max; i++)
{
puts(student_info[i].line);
}
free(student_info);
student_info = NULL;
}
int calculateMax(void)
{
char str[150];
int maximum = 0;
FILE *f;
if ((f = fopen("student.txt", "r")) == NULL)
{
printf("Error, the file cannot be opened\n");
}
else {
while (!feof(f)) {
maximum++;
fgets (str , 200 , f);
}
}
fclose (f);
maximum = maximum - 1;
return maximum;
}
////////////////////////////////////////////////////////////////////
static int student_info_compare(const void *a, const void *b)
{
const student_info *sia = a, *sib = b;
return strcmp(sia->name, sib->name);
}
void Sortdisplay()
{
int max = 0, i;
FILE *f;
printf("\n\nDISPLAY SORTED STUDENT");
max = calculateMax();
data *student_info;
student_info = (data *) malloc(max * sizeof(data));
if(student_info == NULL)
{
printf("Unable to allocate space for student\n\n");
exit (EXIT_FAILURE);
}
if ((f = fopen("sort.txt", "r")) == NULL)
{
printf("Error, the file cannot be opened\n");
}
i = 0;
while (!feof(f)) {
fflush(stdin);
fgets(student_info[i].line, 200, f);
i++;
}
fclose (f);
printf("\n\n%s%6s%20s%17s\n", "ID", "NAME", "TERM", "GPA");
student_info_compare();
for(i = 0; i < max; i++)
{
// iwant to sort here
qsort(student_info, max, sizeof student_info[0], student_info_compare);
puts(student_info[i].line);
}
free(student_info);
student_info = NULL;
}
Try this:
static int student_info_compare(const void *a, const void *b)
{
const student_info *sia = a, *sib = b;
return strcmp(sia->name, sib->name);
}
then add this before the print loop:
qsort(student_info, max, sizeof student_info[0], student_info_compare);
This uses the standard qsort() function to sort the array. The student_info_compare() function serves as the comparison-callback, since qsort() doesn't know how your data looks.
The arguments to the comparison-callback have type const void *, which basically means "here's a pointer to something whose exact type is not known, and you're supposed to treat it as a read-only pointer". That's how qsort() passes pointers to the array elements, since (again) it doesn't know that they are of type const student_info *.

Stack of strings

Hi i have program here that accept int as value. i wanted to translate it to accept strings in array then. i have read about using struct but i couldnt get into it. i hope someone can help me getting into that without using struct i dont know where to start i want to keep this lines of code.
#include <stdio.h>
#include <ctype.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
int top = 0;
int *stack = NULL;
int size = 0;
main()
{
int opt, num;
char cont[] = { 'y' };
clrscr();
/* <start Declaring Stack Size { */
printf("Stacking Program");
printf("\n\nData Size: ");
scanf("%d", &size);
printf("\n");
/* } end> */
/* <start Allocates size of stack { */
if(size > 0)
{
stack = malloc(size * sizeof(int));
if(stack == NULL)
{
printf("ERROR: malloc() failed\n");
exit(2);
}
}
else
{
printf("ERROR: size should be positive integer\n");
exit(1);
}
/* } end> */
while((cont[0] == 'y') || (cont[0] == 'Y'))
{
clrscr();
/* <start Main Menu { */
printf("Stacking Program");
printf("\n\nData Size: %d\n\n", size);
printf("MAIN MENU\n1. Pop\n2. Push\n3. Pick\n4. View\nChoose: ");
scanf("%d", &opt);
printf("\n");
switch(opt) {
case 1:
pop();
break;
case 2:
if(top==size)
{
printf("You can't push more data");
}
else
{
printf("Enter data for Stack[%d]: ", top+1);
scanf("%d", &num);
push(num);
}
break;
case 3:
pick();
break;
case 4:
view();
break;
default:
printf("Your choice is not on the list.");
break;
}
/* } end> */
printf("\n\nDo you want continue\(Y\/N\)?");
scanf("%s", &cont[0]);
}
free(stack);
}
pop()
{
int a;
loading();
if(top <= 0)
{
printf("Stack empty.");
return 0;
}
else
{
top--;
a=stack[top];
printf("\(Stack[%d] = %d\) removed.", top+1, a);
}
}
push(int a)
{
stack[top]=a;
top++;
loading();
}
pick()
{
loading();
if(top <= 0)
{
printf("Nothing to display.");
return 0;
}
else
{
printf("\(Stack[%d] = %d\) is the last data.", top, stack[top-1]);
}
}
view()
{
int i;
loading();
if(top <= 0)
{
printf("Nothing to display.");
return 0;
}
else
{
for(i=0;i<top;i++)
{
printf("Stack[%d] = %d\n", i+1, stack[i]);
}
}
}
loading()
{
float i, x;
float load;
int loadarea[] = { 5000, 10000, 15000, 20000, 25000, 30000 };
int percentLoad;
x=0;
load=0;
percentLoad = loadarea[random(5)];
gotoxy(26,11);
printf("[");
for(i=0;i<25;i++)
{
x = i+27;
gotoxy(x, 11);
printf("=");
delay(percentLoad);
gotoxy(51,11);
printf("]");
gotoxy(53,11);
load=(i/25)*104.5;
if(load>100)
load = 100.00;
printf("%.2f\%",load);
}
delay(60000);
for(i=0;i<60;i++) {
printf("\b \b");
}
printf("\n");
}
Easiest way is to convert your stack to store char* instead of int.
char **stack;
stack = malloc( size * sizeof(char*) );
Now, your push operation will accept a char* from some buffer that is storing the string that was just input, duplicate it with strdup, and store that new pointer in the stack.
typedef enum {
STACK_MEM_ERROR = -1,
STACK_FULL = 0,
STACK_OK = 1
} StackStatus;
StackStatus push(const char *str)
{
char *newstr;
if( top >= size ) return STACK_FULL;
newstr = strdup(str);
if( newstr == NULL ) return STACK_MEM_ERROR;
stack[top++] = newstr;
return STACK_OK;
}
When you pop a string, you just get a pointer.
char *pop()
{
if( top == 0 ) return NULL;
return stack[--top];
}
You are responsible for freeing that memory when you are finished with the pointer (by calling free).
char * val;
while( NULL != (val = pop()) )
{
printf( "I popped: %s\n", val );
free(val);
}

Resources