C Programming: Read from file and print on screen - c

I am trying to read a file test.txt via fscanf and store it in a array of struct. I have posted the code that I have tried. Looks like problem here is with load function
This is what I have in test.txt:
205,11.20,John Snow
336,23.40,Winter is coming
220,34.20,You know nothing
load function uses loadinput function to read test.txt file into the “item” array and sets the target of the “NoPtr” to the number of Items read from the file (which in this case should be 3).
After reading the file, I am also trying to print it on screen, but it won't work. Nothing is displayed at all.
This program compiles. What is it that I am doing wrong here?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Item {
double value;
int unit;
char name[50];
};
int load(struct Item* item, char Name[], int* NoPtr);
int loadinput(struct Item* item, FILE* data);
void display(struct Item item, int variableA);
int main(void)
{
struct Item FIN[3];
int i, n;
load(FIN, "test.txt", &n);
for (i = 0; i < n; i++)
{
display(FIN[i],0);
}
return 0;
}
int load(struct Item* item, char Name[], int* NoPtr)
{
struct Item ARR[3];
int flagcheck;
FILE* fl;
fl = fopen("Name[]", "r");
while (fl)
{
flagcheck = loadinput(&ARR, fl);
if (flagcheck < 0)
{
fclose(fl);
break;
}
else
{
*NoPtr++;
}
fclose(fl);
}
return 0;
}
int loadinput(struct Item* item, FILE* data)
{
int ret = fscanf(data, "%d,%lf,", &item->unit, &item->value);
if (ret != 2) {
return -1;
}
fgets(item->name, sizeof item->name, data);
item->name[strlen(item->name)-1] = '\0';
return 0;
}
void display(struct Item item, int variableA)
{
printf("|%3d |%12.2lf| %20s |***\n", item.unit, item.value, item.name);
return;
}

see fix demo – BLUEPIXY
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Item {
double value;
int unit;
char name[50];
};
int load(struct Item* item, char Name[], int* NoPtr);
int loadinput(struct Item* item, FILE* data);
void display(struct Item item, int variableA);
int main(void) {
struct Item FIN[3];
int i, n;
load(FIN, "test.txt", &n);
for (i = 0; i < n; i++) {
display(FIN[i],0);
}
return 0;
}
int load(struct Item* item, char Name[], int* NoPtr){
*NoPtr = 0;
int flagcheck;
FILE* fl;
fl = stdin;//fopen(Name, "r");//for ideone
while (fl){
flagcheck = loadinput(&item[*NoPtr], fl);
if (flagcheck < 0){
fclose(fl);
break;
} else {
++*NoPtr;
}
}
return 0;
}
int loadinput(struct Item* item, FILE* data){
int ret = fscanf(data, "%d,%lf,", &item->unit, &item->value);
if (ret != 2) {
return -1;
}
fgets(item->name, sizeof item->name, data);
item->name[strlen(item->name)-1] = '\0';
return 0;
}
void display(struct Item item, int variableA){
printf("|%3d |%12.2lf| %20s |***\n", item.unit, item.value, item.name);
return;
}

Related

Why do I have to do ctrl+z twice to break end of file?

Basically I have a struct
typedef struct {
const char *nome;
const char *apelido;
int numero;
} Aluno;
I want to sort this by numero.
For example, Input:
jonhy_james_123
jack_china_111
Output :
jack_china_111
jonhy_james_123
I have sucessfully done this, but instead of one CTRL+Z to break end of file, I
somehow need to do it twice.
Here is the full code:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <math.h>
#include <string.h>
typedef struct {
const char *nome;
const char *apelido;
int numero;
} Aluno;
Aluno aluno(const char *nome, const char *apelido, int numero)
{
Aluno result;
result.nome = nome;
result.apelido = apelido;
result.numero = numero;
return result;
}
Aluno *Aluno_new (int n)
{
return (Aluno *) malloc (n * sizeof(Aluno));
}
char *str_dup(const char *s)
{
char *result = (char *) malloc(strlen(s) + 1);
strcpy(result, s);
return result;
}
int aluno_read(Aluno *a)
{
int result = 0;
char nome[50];
char apelido[50];
int numero;
while (scanf("%[^_]_%[^_]_%d\n", nome, apelido, &numero) != EOF) {
a[result++] = aluno(str_dup(nome), str_dup(apelido), numero);
}
return result;
}
void aluno_write(Aluno *a, int n)
{
printf("%s_%s_%d\n", a[0].nome, a[0].apelido, a[0].numero);
for (int i = 1; i < n; i++) {
printf("%s_%s_%d\n", a[i].nome, a[i].apelido, a[i].numero);
}
}
int qsort_cmp_numero(Aluno *x, Aluno *y)
{
return (x->numero - y->numero);
}
int cmp_B(Aluno *x, Aluno *y)
{
int result = qsort_cmp_numero(x,y);
return result;
}
int cmp_final2(const void *p, const void *q)
{
return cmp_B((Aluno *) p, (Aluno *) q);
}
void test_sort()
{
Aluno *aluno = Aluno_new(100001);
int n_aluno = aluno_read(aluno);
qsort(aluno, n_aluno, sizeof(Aluno), cmp_final2);
aluno_write(aluno, n_aluno);
}
int main()
{
test_sort();
return 0;
}
While behavior of Ctrl-Z in Windows has some peculiarities, this is secondary at the moment.
The primary problem is that you placed an \n character at the end of your scanf format. By doing so you asked scanf to wait for non-empty input after the "primary" portion of the input is complete.
This by itself will easily result "strange" behaviors of your scanf, like "ignoring" Enter key and such.
What is that \n doing there? Why did you include it in your format string?

Unable to read a structure from a text file in C

#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int id;
char* name;
float weight;
} Person;
int main()
{
Person *person=malloc(10*sizeof(Person));
int i=0;
char row[20];
FILE *input=fopen("input.txt","r+");
while(fscanf( input, "%s", &row)>0) i++;
i/=5;
printf("%d\n", i);
fseek(input,0,SEEK_SET);
int j;
char string[20];
for (j=0;j<i;j++){
fscanf(input,"%s",string);
fscanf(input,"ID:%d",&person[j].id);
fscanf(input,"Name:%s",person[j].name);
fscanf(input,"Weight:%f",&person[j].weight);
fscanf(input,"%s",string);
}
fclose(input);
//Person:{
//ID:1214124141
//Name:Trump
//Weight:101.50
//}
//Person:{
//ID:5235252525
//Name:Obama
//Weight:78.30
//}
return 0;
}
Hello!
I want to read a structure from a file, but my array person contains only 0 even after I read from the file. My input file has the structure shown in the comment lines.
What am I not doing well?
Thanks a lot for the help!
fix like this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
long long int id;//32bit int can't hold like 5235252525
char name[20];//Allocate space
float weight;
} Person;
#define FORMAT "%*s ID:%lld Name:%19[^\n] Weight:%f %*s"
int main(void){
FILE *input=fopen("input.txt", "r+");
if(!input){
perror("fopen");
return -1;
}
int n = 0;
Person p;
while(3==fscanf(input, FORMAT, &p.id, p.name, &p.weight))
++n;
printf("number of record: %d\n", n);
Person *person = malloc(n * sizeof(Person));
if(!person){
perror("malloc");
fclose(input);
return -2;
}
rewind(input);
for (int i = 0; i < n; ++i){
fscanf(input, FORMAT, &person[i].id, person[i].name, &person[i].weight);
}
fclose(input);
//check print
for (int i = 0; i < n; ++i){
printf("ID:%lld, Name:%s, Weight:%.2f\n", person[i].id, person[i].name, person[i].weight);
}
free(person);
return 0;
}

request for member 'x' in something not a structure or union and segmentation fault (lost)

//Goal: Load data from a file into the struct
typedef struct {
int year;
char* make;
char* model;
int miles;
} Car;
void fill_garage(Car** garage, char* cars, int* size);
int main(int argc, char** argv)
{
if(argc<3)
{
printf("Not enough arguments.\n");
return 0;
}
int size;
Car** garage;
fill_garage(garage, argv[1], &size);
return 0;
}
void fill_garage(Car** garage, char* cars, int* size)
{
int i;
FILE* inputF=fopen(cars, "r");
fscanf(inputF, "%d", size);
garage=malloc(sizeof(Car)*(*size));
for(i=0; i<(*size); i++)
{
garage[i].make=malloc(sizeof(char)*MAX_STRING_LEN);
garage[i].model=malloc(sizeof(char)*MAX_STRING_LEN);
//The line below causes a segmentation fault when there are no errors
fscanf(inputF, "%d %s %s %d", &garage[i].year, garage[i].make, garage[i].model, &garage[i].miles);
}
}
//I'm not expecting anyone to just give me the corrected code (though that would be nice) If you could point be to a resource where I could learn about pointers would be great. Here's the assignment sheet if you want to see it. http://pastebin.com/LNeCx70m
You have to pass the address of garage to fill_garage(), so this
Car** garage;
fill_garage(garage, argv[1], &size);
should be
Car *garage;
fill_garage(&garage, argv[1], &size);
/* ^ pass the address of garage */
You don't need malloc() for a fixed size string, just redefine your struct like
typedef struct {
int year;
char make[MAX_STRING_LEN];
char model[MAX_STRING_LEN];
int miles;
} Car;
Check fopen() and malloc() returned values, if they fail both return NULL, if you failed to open the file, then you will cause undefined behavior. Also check the return value of fscanf().
Include stdio.h for printf() and fscanf() and stdlib.h for malloc().
I fixed your code, so it must not have any issues in principle
#include <stdio.h>
#include <stdlib.h>
#define MAX_STRING_LEN 128
typedef struct {
int year;
char make[MAX_STRING_LEN];
char model[MAX_STRING_LEN];
int miles;
} Car;
void fill_garage(Car **garage, char *cars, int *size);
int main(int argc, char** argv)
{
if (argc < 3)
{
printf("Not enough arguments.\n");
return 0;
}
int size;
Car *garage;
fill_garage(&garage, argv[1], &size);
return 0;
}
void fill_garage(Car **output, char *cars, int *size)
{
int i;
FILE *inputF;
Car *garage;
if (output == NULL)
return;
*output = NULL;
inputF = fopen(cars, "r");
if (inputF == NULL)
return;
if (fscanf(inputF, "%d", size) != 1)
{
fclose(inputF);
return;
}
garage = malloc(sizeof(*garage) * *size);
*output = garage;
if (garage == NULL)
{
fclose(inputF);
return;
}
i = 0;
while ((i < *size) && (fscanf(inputF, "%d%127s%127s%d", &garage[i].year, garage[i].make,
garage[i].model, &garage[i].miles) == 4))
{
i += 1;
}
}

Error in printing the stack

I am trying to implement a program using stacks.But the stack is not getting displayed
#include<stdio.h>
int size=0,count=1,test=0;
struct Car
{
int registrationNo;
char *name;
};
struct ParkingLot
{
struct Car C[10];
};
struct stack
{
struct ParkingLot P;
int top;
} st;
int stfull()
{
if(st.top >= size-1)
return 1;
else
return 0;
}
void push(struct Car item) {
st.top++;
st.P.C[st.top] = item;
}
int stempty() {
if (st.top == -1)
return 1;
else
return 0;
}
void display() {
int i;
if (stempty())
printf("\nStack Is Empty!");
else {
//printf("%d\n",st.top);
for (i = 0; i<=st.top; i++)
printf("\n%s", st.P.C[i].name);
}
}
void Enter_ParkingLot()
{
struct Car CC;
int checkFull=stfull();
if(checkFull==1)
printf("Parking Lot is FUll\n");
else
{
CC.registrationNo=count;count++;
char ch[100];
printf("Enter name of owner\n");
scanf("%s",ch);
CC.name=ch;
push(CC);
}
}
int main()
{
printf("Enter size of Parking Lot\n");
st.top=-1;
scanf("%d",&size);
Enter_ParkingLot();
Enter_ParkingLot();
display();
return 0;
}
This was my input on terminal-
Enter size of Parking Lot
2
Enter name of owner
ABCD
Enter name of owner
EFGH
This was my output-
`#
`#
There was a blank line before first # in the output.
If you assign the pointer field in struct Car to a local variable, it will not work, you need to redeclare your struct Car like this
struct Car
{
int registrationNo;
char name[100];
};
and then instead of
CC.name=ch;
do it this way
strcpy(CC.name, ch);
also, it's better to write
scanf("%99s",ch);
to prevent overflowing ch, and in your case it would be even better to do
scanf("%99s", CC.name);
I fixed your code
#include <stdio.h>
#include <string.h>
struct Car
{
int registrationNo;
char name[100];
};
struct ParkingLot
{
struct Car C[10];
};
struct stack
{
struct ParkingLot P;
int top;
} st;
int stfull(int size)
{
if(st.top >= size - 1)
return 1;
return 0;
}
void push(struct Car item)
{
st.P.C[++(st.top)] = item;
}
int stempty()
{
if (st.top == -1)
return 1;
return 0;
}
void display()
{
int i;
if (stempty() != 0)
printf("\nStack Is Empty!");
else {
for (i = 0 ; i <= st.top ; i++)
printf("\n%s", st.P.C[i].name);
}
}
int Enter_ParkingLot(int count, int size)
{
struct Car CC;
if (stfull(size) == 1)
printf("Parking Lot is FUll\n");
else
{
CC.registrationNo = count;
printf("Enter name of owner\n");
scanf("%99s", CC.name);
push(CC);
}
return count + 1;
}
int main()
{
int size = 0, count = 1;
printf("Enter size of Parking Lot\n");
st.top = -1;
scanf("%d", &size);
count = Enter_ParkingLot(count, size);
count = Enter_ParkingLot(count, size);
display();
return 0;
}
I removed global variables, they where not needed.
I fixed some if/else's which made no sense.
I also applied my previously suggested fixes related to your original problem.
The Problem:
You store the name of the car into an array that is allocated on the stack.
You then copy the pointer to that array to your car object.
The original array then goes out of scope.
You then try to print that array, which no longer exists, via the pointer.
Undefined behavior occurs.
The Solution:
You need to allocate memory for the name of the car with malloc() and use strcpy() to copy it to the car object.

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

Resources