Sorting array filled with lines of string - c

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 *.

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.

Why gdb showed /stdlib/strtol_l.c: No such file or directory? Do I missing something to install?

I tried to compile with -g and then run gdb to find the line that caused the segmentation fault, but the error message confused me.
Program received signal SIGSEGV, Segmentation fault.
__GI_____strtol_l_internal (nptr=0x0, endptr=endptr#entry=0x0, base=base#entry=10, group=group#entry=0, loc=0x7ffff7fb04a0 <_nl_global_locale>)
at ../stdlib/strtol_l.c:292
292 ../stdlib/strtol_l.c: No such file or directory.
I tried reinstalling gdb to get it working again, but I failed. It still shows the same error message. I later found the problem myself and marked it in the code below. I'm just curious why something like this sometimes happens when I try to debug some string functions? Like strdup, strtok, strtol, etc.. Am I missing something to install? I hope I can solve this problem completely.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
char buff[255];
#define NUM_BUCKETS 32
typedef struct Customer {
char* email;
char* name;
int shoesize;
char* food;
struct Customer* next;
} Customer ;
unsigned long hash(char *str) {
unsigned long hash = 0;
int c;
while (*str != '\0') {
c = *str;
hash = ((hash << 5) + hash) + (unsigned char)c;
str++;
}
return hash;
}
Customer *add_friend_to_list(char *email, char *name, int shoesize, char *food, Customer *bucket) {
Customer* customer;
customer = malloc(sizeof(Customer));
customer->name = strdup(name);
customer->food = strdup(food);
customer->shoesize = shoesize;
customer->email = strdup(email);
customer->next = bucket;
return customer;
}
void add_consumer_to_hashtable(char *name, char *food, char *email, int shoesize, Customer **buckets, size_t num_buckets) {
size_t which_bucket = hash(name) % num_buckets;
buckets[which_bucket] = add_friend_to_list(email, name, shoesize, food, buckets[which_bucket]);
}
int main() {
Customer* buckets[NUM_BUCKETS] = {NULL};
int ittime = 0;
FILE *fp = NULL;
fp = fopen("customers.tsv", "r");
while (true) {
fgets(buff, 255, fp);
if (feof(fp)) {
break;
}
ittime++;
}
fclose(fp);
fp = NULL;
char *email = (char *)malloc(5 * sizeof(char));
char *name = (char *)malloc(5 * sizeof(char));
int shoesize;
char *food = (char *)malloc(5 * sizeof(char));
const char s[2] = "\t";
fp = fopen("customers.tsv", "r");
for (int i = 0; i < ittime + 1; i++) { //This line cause the Segmentation Fault
fgets(buff, 255, fp);
char *token;
token = strtok(buff, s);
email = token;
token = strtok(NULL, s);
name = token;
token = strtok(NULL, s);
shoesize = atoi(token);
token = strtok(NULL, s);
food = token;
add_consumer_to_hashtable(name, food, email, shoesize, buckets, NUM_BUCKETS);
}
fclose(fp);
while (true) {
char *cmd = (char *)malloc(5 * sizeof(char));
printf("command: ");
scanf("%s", cmd);
if (strcmp(cmd, "add") == 0) {
char *email1 = (char *)malloc(5 * sizeof(char));
char *name1 = (char *)malloc(5 * sizeof(char));
int shoesize1;
char *food1 = (char *)malloc(5 * sizeof(char));
printf("email address? ");
scanf("%s", email1);
printf("name? ");
scanf(" %[^\n]", name1);
printf("shoe size? ");
scanf("%d", &shoesize1);
printf("favorite food? ");
scanf("%s", food1);
add_consumer_to_hashtable(name1, food1, email1, shoesize1, buckets, NUM_BUCKETS);
free(name1);
free(food1);
free(email1);
} else if (strcmp(cmd, "lookup") == 0) {
char *Email = (char *)malloc(5 * sizeof(char));
printf("email address? ");
scanf("%s", Email);
bool exist = false;
for (int i = 0; i < 32; i++) {
Customer *cus = buckets[i];
if (buckets[i] == NULL) {
continue;
}
while ((cus != NULL)) {
if (cus->shoesize == EOF) {
break;
}
if (strcmp(cus->email, Email) == 0) {
printf("email: %s\n", cus->email);
printf("name: %s\n", cus->name);
printf("shoesize: %d\n", cus->shoesize);
printf("food: %s\n", cus->food);
exist = true;
break;
}
if (cus->next != NULL) {
cus = cus->next;
} else {
break;
}
}
}
if (exist == false) {
printf("user not found!\n");
}
} else if (strcmp(cmd, "delete") == 0) {
char *Email = (char *)malloc(5 * sizeof(char));
printf("email address? ");
scanf("%s", Email);
bool exist = false;
for (int i = 0; i < 32; i++) {
Customer *cus = buckets[i];
if (buckets[i] == NULL) {
continue;
}
while ((cus != NULL)) {
if (cus->shoesize == EOF) {
break;
}
if (strcmp(cus->email, Email) == 0) {
free(cus->email);
free(cus->food);
free(cus->name);
free(cus);
cus->shoesize = EOF;
cus = NULL;
exist = true;
break;
}
if (cus->next != NULL) {
cus = cus->next;
} else {
break;
}
}
}
if (exist == false) {
printf("user not found!\n");
}
} else if (strcmp(cmd, "list") == 0) {
for (int i = 0; i < 32; i++) {
Customer *cus = buckets[i];
if (buckets[i] == NULL) {
continue;
}
while ((cus != NULL) && ((cus->shoesize) != EOF)) {
printf("email: %s\n", cus->email);
printf("name: %s\n", cus->name);
printf("shoesize: %d\n", cus->shoesize);
printf("food: %s\n", cus->food);
if (cus->next != NULL) {
cus = cus->next;
printf("\n");
} else {
break;
}
}
}
} else if (strcmp(cmd, "quit") == 0) {
break;
} else if (strcmp(cmd, "save") == 0) {
fp = fopen("customers.tsv", "w");
for (int i = 0; i < 32; i++) {
Customer *cus = buckets[i];
if (buckets[i] == NULL) {
continue;
}
while ((cus != NULL) && ((cus->shoesize) != EOF)) {
fprintf(fp, "%s\t%s\t%d\t%s", cus->email, cus->name, cus->shoesize, cus->food);
if (cus->next != NULL) {
cus = cus->next;
fprintf(fp, "\n");
} else {
break;
}
}
}
fclose(fp);
} else {
printf("unknown command\n");
}
}
for (int i = 0; i < 32; i++) {
Customer *tmp;
Customer *cus = buckets[i];
if (cus == NULL) {
continue;
}
if (cus->next != NULL) {
tmp = cus;
cus = cus->next;
} else {
break;
}
while ((tmp != NULL)) {
if (tmp->shoesize != EOF) {
free(tmp->email);
free(tmp->food);
free(tmp->name);
free(tmp);
}
cus->shoesize = EOF;
cus = NULL;
}
if (tmp != NULL) {
free(tmp);
}
if (cus != NULL) {
free(cus);
}
}
return 0;
}
I tried to compile with -g and then run gdb to find the line that caused the segmentation fault, but the error message confused me.
The error message means:
crash happened inside GLIBC strtol_l_internal() function
GDB can't show you the source of that function because libc6-src (or similar) package is not installed.
Now, looking at the source for strtol_l_internal() is not going to be helpful -- the root cause of the problem is that you called it with incorrect parameter.
You should read man strtol and verify that you satisfied its preconditions.
It looks like you called strtol(NULL, NULL, ...), which is not a valid thing to do. You could use (gdb) up command to find out where the wrong call came from, and fix the caller.

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;
}
}
}

invalid argument read write file

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.

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