Reading a csv file in c - c

I'm trying to read a csv file that contains 9 columns each having information about a person. I'm supposed to store the data in a hash table and create a function to look up data based on the surname. This is my code
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#include <ctype.h>
#define tablesize 27
#define entries 21
unsigned long int collisions = 0;
typedef struct {
char id[20];
char depid[10];
char surname[20];
char forename[20];
char age[2];
char ptype[20];
char gender[6];
char nation[20];
char religion[20];
char occupation[20];
}dict;
dict* hashTable[tablesize]= {NULL};
unsigned long int hash_function(char* s){
unsigned long int hash = 0;
while(*s){
hash = hash + *s;
s++;
}
return hash%tablesize;
}
void print_table(){
for(unsigned long int i=0;i<tablesize;i++){
if(hashTable[i]==NULL){
printf("%d\t---\t---\n",i);
}
else{
printf("%d\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",i,hashTable[i]->id,hashTable[i]->depid,hashTable[i]->surname,hashTable[i]->forename,hashTable[i]->age
,hashTable[i]->ptype,hashTable[i]->gender,hashTable[i]->nation,hashTable[i]->religion,hashTable[i]->occupation);
}
}
}
void insert(dict *d){
unsigned long int ind = hash_function(d->surname);
for(unsigned long int i=0;i<tablesize;i++){
unsigned long int try = (ind+i)%tablesize;
if(hashTable[try]==NULL){
hashTable[try] = d;
return;
}
else{
collisions++;
}
}
}
void printvalues(unsigned long int i){
printf("%d\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",i,hashTable[i]->id,hashTable[i]->depid,hashTable[i]->surname,hashTable[i]->forename,hashTable[i]->age
,hashTable[i]->ptype,hashTable[i]->gender,hashTable[i]->nation,hashTable[i]->religion,hashTable[i]->occupation);
}
void search(char* name){
unsigned long int ind = hash_function(name);
unsigned long int f=1;
for(unsigned long int i=0;i<tablesize;i++){
unsigned long int try = (ind+i)%tablesize;
if(hashTable[try]!=NULL&&strcmp(hashTable[try]->surname,name)==0){
printvalues(try);
f=0;
}
}
if(f==1)
printf("%s not in table\n",name);
return;
}
int main(){
FILE *fp = fopen("truncated.csv","r");
if(!fp){
printf("Error");
return 0;
}
char buff[1024];
unsigned long int row = 0, column = 0;
dict values[entries];
unsigned long int i=0;
while(fgets(buff,1024,fp)){
column=0;
row++;
if(row==1){
continue;
}
char *field = strtok(buff,",");
while(field){
if(column==0){
strcpy(values[i].id,field);
}
if(column==1){
strcpy(values[i].depid,field);
}
if(column==2){
strcpy(values[i].surname,field);
}
if(column==3){
strcpy(values[i].forename,field);
}
if(column==4){
strcpy(values[i].age,field);
}
if(column==5){
strcpy(values[i].ptype,field);
}
if(column==6){
strcpy(values[i].gender,field);
}
if(column==7){
strcpy(values[i].nation,field);
}
if(column==8){
strcpy(values[i].religion,field);
}
if(column==9){
strcpy(values[i].occupation,field);
}
field = strtok(NULL,",");
column++;
}
i++;
}
fclose(fp);
for(unsigned long int i=0;i<entries;i++){
insert(&values[i]);
}
//printvalues(values);
//print_table();
while(1){
printf("Enter term to get frequency or type 'quit' to escape:");
char name[20];
scanf("%s",name);
if(strcmp(name,"quit")==0)
return 0;
search(name);
}
return 0;
}
The problem I'm facing is that i have two csv files, one containing 60000 entries and one containing only 21 entries. When i read the smaller file, the code works just fine. But i am getting no output whatsoever for the bigger file. Any ideas? Thanks in advance.

In your code, you have only space for 21 entries (line #define entries 21)
So you'll parse 22th line and more in the big file, you'll try to write into a forbidden place. From this point, you enter in UB zone.
Solution: make values dynamic.
int count = 0;
dict *values = NULL;
while(fgets(buff,1024,fp)){
++count;
dict * tmp = realloc(values, sizeof (dict) * count);
if (NULL == tmp) {
perror("realloc");
free(values);
exit(1);
} else {
values = tmp;
}
and after the while loop:
free(values);

Related

Getting jargon before actual data when printing char pointer

I'm writing a program that implements the Alberti Cipher, and when testing, the final print always gives a string of jargon before the actual encryption. Right now its printing \x80\x16G\xbf\xfe\x7fKHOORZRUOG, with KHOOR..... being the actual encryption. Any help appreciated :)
#include <stdio.h>
#include <stdlib.h>
int letterToNumber(char letter){
char str[2] = { letter };
int num = strtol( str, NULL, 36 ) - 10;
return num;
}
int getSize (const char * s) {
const char * t;
int size = 0;
for (t = s; *t != '\0'; t++) {
size++;
}
return size;
}
char numToChar(int numInp){
numInp=numInp+65;
char returnChar=(char)numInp;
return returnChar;
}
void encrypt_alberti(const char *message,const char *inner_ring, int initialShift,int periodicShift,int periodLength,char **result){
//sets initial shift
int numArray[25];
int count=0;
int shiftCount=0;
for(int i = 0; i < 26; ++i) {
numArray[i]=(i+initialShift)%26;
}
//encrypts each character and prints
int messageSize=getSize(message);
char encryptedMessage[messageSize];
for(int i=0; i<messageSize;i++){
count++;
if(periodicShift!=0){
if(count%periodicShift==0){
shiftCount++;
}
}
else{
periodLength=0;
}
char toBeEncrypted=message[i];
int charNumber=letterToNumber(toBeEncrypted);
int encryptedNum=numArray[(charNumber+(shiftCount*periodLength))%26];
char encryptedChar=numToChar(encryptedNum);
strncat(encryptedMessage, &encryptedChar, 1);
}
char* p1=malloc(sizeof(encryptedMessage));
strcpy(p1,encryptedMessage);
*result=p1;
}
void main(void) {
const char *example_message = "HELLOWORLD";
const char *example_inner = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char *encrypted_message = NULL;
encrypt_alberti(example_message, example_inner, 3, 0, 1, &encrypted_message);
printf("message is %s\n", encrypted_message);
printf("-----------------");
free(encrypted_message);
}
}

Problem while reading structure from binary file

As I was trying to write code which is supposed to sort some structures in a file by a specific field (key), I noticed that my function won't read the key correctly. I don't have any idea what I am doing wrong. The code is not complete.
The constr function is supposed to read one structure at a time from the binary file, then only save the varsta array. However, if I try to see what value I obtained, the values are not the ones I gave.
This is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
char nume[20];
char prenume[20];
float varsta;
} PERS;
typedef struct
{
float key;
int nr;
}INDEX;
int constr(FILE *f, INDEX tabl[])
{
int n;
n = ftell(f) / sizeof(PERS);
int i, depl = 0;
PERS p;
for (i = 0; i < n; i++)
{
fseek(f, depl, 0);
fread(&p, sizeof(p), 1, f);
tabl[i].key = p.varsta;
tabl[i].nr = i;
depl += sizeof(PERS);
}
return n;
}
int main()
{
FILE *f;
PERS pers[3];
if ((f = fopen("fis.txt", "wb+")) == NULL)
{
printf("Not ok");
exit(1);
}
int i;
for (i = 0; i < 3; i++)
{
scanf("%s%s%f", &pers[i].nume, &pers[i].prenume, &pers[i].varsta);
fwrite(&pers[i], sizeof(PERS), 1, f);
}
INDEX tabl[3];
int n = constr(f, tabl);
printf("%d", tabl[2].key); //only to check if the key is correct
fclose(f);
}
The key field is a float, but you are trying to print an integer.
Change the penultimate line in your code to
printf("%.2f\n", tabl[2].key);

Incompatible pointer type when making structure of function pointers

I'm trying to make a array of structures which contain a string and a function pointer, however when I compile I get a warning that I've initialized from an incompatible pointer type.
I have no idea why (sorry if I sound ignorant, I'm fairly new to C programming).
typedef struct
{
char Player1[2], Player[2], **gameGrid;
int height,width;
int moveNum, player1Num, player2Num;
bool player1Win, player2Win;
}Game;
typedef int (*pointer_func)(Game *);
typedef struct
{
char *funcName;
pointer_func *f;
}userFunc;
int save(Game *struc);
int load(Game *struc);
int move(Game *struc);
int quit(Game *struc);
void free_grid(Game *struc);
int main(){
//initialised variables
userFunc Name_arr[] = {
{"save",save},
{"load",load},
{"quit",quit},
{"move",move}
};
The four functions being referenced are as follows:
int save(Game *struc)
{
char *str, *inputString, *writeString;
FILE *fp;
int nextPlayer;
int maxRead = 20;
bool DIRresponse;
while(true)
{
printf("Please provide a file name (20 characters max): ");
inputString = input_String(inputString, maxRead, stdin);
if((DIRresponse = check_Directory(inputString)) == true){
printf("That name already exists, choose another\n");
continue;
}
else
break;
}
if(struc->moveNum % 2 == 0)
nextPlayer = struc->player1Num;
else
nextPlayer = struc->player2Num;
sprintf(str,"%s.txt",inputString);
fp = fopen(str,"w");
sprintf(writeString, "%d %d %d %d %d", nextPlayer, struc->height,
struc->width, struc->moveNum, struc->moveNum);
fprintf(fp,writeString);
fclose(fp);
return 0;
}
int move(Game *struc)
{
return 1;
}
int load(Game *struc)
{
return 1;
}
int quit(Game *struc)
{
free_grid(struc);
exit(EXIT_SUCCESS);
}
You have a mismatch in levels of pointers:
typedef int (*pointer_func)(Game *); << Pointer type
typedef struct
{
char *funcName;
pointer_func *f; << Pointer to a pointer type.... OOPS
}userFunc;
Make *f -> f and it should work.

Hash Table - Sort Structure with qsort

Alright sorry for creating another question but the last one got overwhelmed and chaotic.
So I'm making a hash table which inserts words from a file (tokens) and after I have inserted them I need to sort them. The program template was given, the only functions that weren't complete were : insert_ht() , clear_ht() and compare. Even though I've done tons of search about qsort with compare, the program doesn't sort the frequencies (number of times each word was inserted) . I want em sorted from the highest to lowest.
Here is the code : "note that i shouldn't change any function except insert_ht() , clear_ht() and compare
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define HTABLE_SIZ 1001
#define MAX_LINE_SIZ 1024
/* Hash Table */
typedef struct node* link;
struct node { char *token; int freq; link next; };
link htable[HTABLE_SIZ] = { NULL }; /* Table of lists (#buckets) */
int size = 0; /* Size (number of elements) of hash table */
unsigned int hash (char *tok );
void insert_ht (char *data);
void clear_ht ( );
void print_ht ( );
void Process(FILE *fp);
int main(int argc, char *argv[])
{
int i;
FILE *fp;
printf("prin tin for \n");
for (i=1; i < argc; i++)
{
printf("prin tin fopen \n");
fp = fopen(argv[i],"r");
if (NULL == fp)
{
fprintf(stderr,"Problem opening file: %s\n",argv[i]);
continue;
}
printf("prin tin process \n");
Process(fp);
fclose(fp);
}
print_ht();
//clear_ht();
return 0;
}
void Process(FILE *fp)
{
const char *seperators = " ?!'\";,.:+-*&%(){}[]<>\\\t\n";
char line[MAX_LINE_SIZ];
char *s;
while((fgets(line,MAX_LINE_SIZ, fp)) != NULL)
{
for (s=strtok(line,seperators); s; s=strtok(NULL,seperators)){
printf("prin tin insert %s \n",s);
insert_ht(s);
}
}
}
/* Hash Function */
unsigned int hash(char *tok)
{
printf("bike stin hash \n");
unsigned int hv = 0;
while (*tok)
hv = (hv << 4) | toupper(*tok++);
printf("VGAINEIIIIIIIIIIIIII %d \n",hv);
return hv % HTABLE_SIZ;
}
void insert_ht(char *token)
{
printf("bike stin insert %s \n",token);
unsigned int hashval = hash(token);
struct node *new_list;
if (htable[hashval]==NULL){
printf("mesa stin prwti if %u %s \n",hashval,token);
//token = strdup(token);
new_list = malloc(sizeof(link));
new_list->token = strdup(token) ;
new_list->freq = 1;
new_list->next = htable[hashval];
htable[hashval] = new_list;
size++;
}else {
htable[hashval]->freq++;
}
printf("ta evale epitixws \n");
}
void clear_ht()
{
int i;
for(i=0; i<HTABLE_SIZ; i++) {
while(htable[i]->token!=NULL) {
htable[i]->token=NULL;
htable[i]->freq=NULL;
free(htable[i]);
}
}
}
int compare(const void *elem1, const void *elem2)
{
const struct node *p1 = elem1;
const struct node *p2 = elem2;
if (p1->freq > p2->freq)
return(+1);
else if (p1->freq < p2->freq)
return(-1);
else
return(0);
}
void print_ht()
{
int i, j=0;
link l, *vector = (link*) malloc(sizeof(link)*size);
for (i=0; i < HTABLE_SIZ; i++)
for (l=htable[i]; l; l=l->next)
vector[j++] = l;
qsort(vector,size,sizeof(link),compare);
for (i=0; i < size; i++)
printf("%-50s\t%7d\n",vector[i]->token,vector[i]->freq);
free(vector);
}
Ι found the solution. Apparently for some reason my compare function was wrong.
I still haven't figured out why but here is the correct one, hopefully someone else will find this post helpful!
int compare(const void *elem1, const void *elem2)
{
return (*(link*)elem2)->freq - (*(link*)elem1)->freq;
}

getting fscanf to store in structs in C

I have an assignment where I need to get Values of RLC circuits from a file and calculate the resonant frequency however my issue is when I use the fscanf function it reads only the first line of the file and the rest comes out as zeros .
#include <stdio.h>
data
int h;
typedef struct cct
{
int code[50];
float R[50];
float L[50];
float C[50];
} CCT;
int read(CCT cct[], int n_p, FILE* fp){
char temp;
if(fp==NULL){
printf("Error\n");
return -1;
}
fscanf(fp,"%d,%f,%e,%e\n", cct[n_p].code, cct[n_p].R,cct[n_p].L, &cct[n_p].C);
}
int main()
{
FILE* fp = fopen("U://datafile.txt", "rt");
int i = 0;
CCT cct[50];
int size;
while (!feof(fp)) {
read(cct, i, fp);
i++;
}
size = i;
for (i = 0; i < size; ++i)
printf("%d,%0.2f,%0.2f,%0.2f\n", cct[i].code[i], cct[i].R[i],
cct[i].L[i], cct[i].C[i]);
scanf("%d",&h);
fclose(fp);
}
and this is the data file
1,4.36,2.23e-2,4.65e-8
2,4.57,2.01e-2,5.00e-8
3,3.99,2.46e-2,4.82e-8
4,4.09,2.60e-2,4.70e-8
I would appreciate if someone could point put why it only gets the first line. Thanks
CCT is composed of multiple arrays (you have arrays of arrays, which is wrong for the exercise, but that's not the point) and you always write to the element zero of the arrays. For example, cct[n_p].code in fscanf() is the address of the array, which is identical to the address of cct[n_p].code[0]. Then you print code[i] in the output loop, which is blank except for i == 0.
fscanf(fp,"%d,%f,%e,%e", cct[n_p].code, cct[n_p].R,cct[n_p].L, cct[n_p].C);
...
printf("%d,%0.2f,%0.2f,%0.2f\n", cct[i].code[0], cct[i].R[0], cct[i].L[0], cct[i].C[0]);
Something like the following, perhaps
#include <stdio.h>
typedef struct cct {
int code;
float R;
float L;
float C;
} CCT;
int h;
int read(CCT cct[], int n_p, FILE* fp){
char temp;
if(fp==NULL){
printf("Error\n");
return -1;
}
fscanf(fp,"%d,%f,%e,%e\n", &cct[n_p].code, &cct[n_p].R, &cct[n_p].L, &cct[n_p].C);
}
int main(){
FILE* fp = fopen("U://datafile.txt", "rt");
int i = 0;
CCT cct[50];
int size;
while (!feof(fp)) {
read(cct, i, fp);
i++;
}
size = i;
for (i = 0; i < size; ++i)
printf("%d,%0.2f,%0.2f,%0.2f\n", cct[i].code, cct[i].R, cct[i].L, cct[i].C);
scanf("%d",&h);
fclose(fp);
}

Resources