file read line by line in c resetting value to last entry - c

I have a text file and each line contains person name and gender in comma separated value. I am trying to read line by line and create the array of person. Not sure what went wrong with my code all the elements of the array is set to the last line of text file. (If the last line has Sam, Male, all the elements of the person array is set to Name=Sam)
struct Person{
char* Name;
char* Gender;
};
struct Person person[100];
void readAllFromFile(){
FILE * fp;
char currentLine[256];
int fd;
if((fp = fopen ("test.txt", "r"))==NULL){
perror("Can not open");
fclose(fp);
return;
}
int currentLineNo=0;
char *items;
while (fgets(currentLine, sizeof(currentLine), fp)) {
items=strtok(currentLine,",");
struct Person tempPerson;
int iter=0;
while(items != NULL)
{
if(iter==0){
tempPerson.Name=items;
}
else {
tempPerson.Gender=items;
}
iter++;
items=strtok(NULL,",");
}
person[currentLineNo]=tempPerson;
currentLineNo++;
}
/*Printing element of the array*/
int i;
for(i=0;i<currentLineNo;i++){
printf("%s\n",person[i].Name);
}
fclose(fp);
}
int main() {
readAllFromFile();
return 0;
}

The name of each person is located in the same place in memory: currentLine. You assign that address to every Persons Name, so every name will be displayed the same. Similar thing for each Gender.
Note that, because currentLine is local to readAllFromFile, once that function returns, that space may be used for other things, trashing the one Name you managed to retain.
Each Person needs its own allocation of space for its Name and Gender.

Related

A way to know if element in array of struct is empty/NULL in C

I would really appreciate help with this piece of code.
So I have defined a structure, and then an array of structures:
#define MAX_ITEMS 30
struct item{
char itemName[30];
int identification;
float sale;
};
struct item itemArray[MAX_ITEMS];
Then I have a function which takes the index of the array structure and is supposed to delete that element, and update the new array without the deleted element to the local .txt file
printf("item's index please: ");
char input[30];
gets(input);
for (int i=input; i<MAX_ITEMS;i++){
itemArray[i] = itemArray[i + 1];
}
FILE *fp
fp = fopen ("file.txt", "w");
int index = 0;
while(itemArray[index].itemName != ""){
fprintf(fp,"%s\n",itemArray[index].itemName);
fprintf(fp,"%d\n",itemArray[index].identification);
fprintf(fp,"%.2f\n",itemArray[index].sale);
index++;
}
fclose(fp);
So what I am expecting:
Instead, I get
Finishing after thousands of lines, like this:
I would appreciate any help!

change all the list values to the last value

so i have a code that a little bit confused, so i build a struct :
typedef struct{
char *team_name;
}Team;
and other struct :
typedef struct{
Team** teams;
int num_teams;
}League;
and a function that create the struct Team:
Team* TeamCreate(char* team_n)
{
Team* t=(Team*)malloc(sizeof(Team));
t->team_name =team_n;
return t;
}
also for League struct:
League* LeagueCreate()
{
League* l=(League*)malloc(sizeof(League));
return l;
}
and the worst part is this function that should insert a words of text file into 'Team** teams'
so in every value of teams there is Team value that contain this word as char *team_name.
and the function make all teams list value equal to the last value of teams list.
the function:
void read_teams(League* l,char* text)
{
FILE *fp=fopen(text,"r");
char* tname=NULL;
size_t tname_size=0;
l->num_teams=0;
l->teams=NULL;
while(getline(&tname,&tname_size,fp)!=EOF)
{
char *p= strchr(tname,'\n');
if (p)
tname[p-tname]='\0';
l->teams=(Team**)realloc(l->teams,sizeof(Team*)*(l->num_teams+1));
l->teams[l->num_teams]=TeamCreate(tname);
l->num_teams++;
}
fclose(fp);
}
so for example my text file is :
Napoli
Salzburg
Liverpool
Genk
and when i write :
printf("\n%s\n",l->teams[0]->team_name);
printf("\n%s\n",l->teams[1]->team_name);
printf("\n%s\n",l->teams[2]->team_name);
printf("\n%s\n",l->teams[3]->team_name);
it print this:
Genk
Genk
Genk
Genk
and thanks for your time :).
The first time you call getline, sufficient space to hold the line will be allocated for you. Unless subsequent calls realloc the memory, you're passing the same exact pointer TeamCreate every time. Therefore, all of your Teams have the same char* and therefore the same team_name. Every time you update the string via getline, all of the team_names will change since they reference the same string.
What you need to do in TeamCreate is use the strdup function from string.h so that each Team gets its own string. I.e.,
t->team_name = strdup(team_n);
Read a .txt file line by line.
#define MAXCHAR 1000
char* filename = "G:\\test.txt";
fp = fopen(filename, "r");
if (fp == NULL){
printf("Could not open file %s",filename);
return 1;
}
while (fgets(str, MAXCHAR, fp) != NULL)
printf("%s", str);
fclose(fp);

Strcpy doesn't work in user defined array

I am trying to assign element hash table[TABLE_SIZE] with input text file. So I used strcpy function. But it didn't copy into the array.
I've tried malloc to make the array in order to write in it. But it didn't work so I made a element* type variable pointing the hash_table array.But still didn't work.
//this is the header file
typedef struct {
char key[100];
char data[100];
} element;
element hash_table[TABLE_SIZE];
// For caomparison count
int num_comparison;
// 파일에서 단어들을 읽어 해시테이블 구성
int build_dictionary(char *fname);
int build_dictionary(char *fname) {
int i = 0; // num of data
char key[100], data[200];
FILE *ifp;
//pointing to the hash_table array
element* hash_table_p = hash_table;
hash_table_p = (element*)malloc(sizeof(element));
//file opening error
if ((ifp = fopen(fname, "r")) == NULL) {
printf("No such file ! \n");
exit(1);
}
while (fscanf(ifp, "%s %s", key, data) == 2) {
// (key data) assigning to array
//i've tried this because hash_table[i].data didn't work
strcpy(hash_table_p->data, data);
strcpy(hash_table_p->key, key);
strcpy(hash_table[i].data, hash_table_p->data);
strcpy(hash_table[i].key, hash_table_p->key);
i++;
//checking if it is well done
printf(" %s %s \n", hash_table_p->key, hash_table_p->data);
printf(" %d %s %s \n",i , hash_table[i].data, hash_table[i].key );
}
fclose(ifp);
return(i);
}
//the input text file went as below
one 하나
two 둘
three 셋
four 넷
five 다섯
When i executed the build_dictionary function, only one with the hash_table_p strcpy was assigned well and the hash_table had nothing in it.
element* hash_table_p = hash_table;
hash_table_p = (element*)malloc(sizeof(element));
You are overwritting the first assignment (getting new room for hash_table_p when you call malloc), as far as I can see you already define the size for the table, so you don't need to reserve more space (delete the line with malloc) and just increment the position of the pointer on each iteration (as you are already doing).

Void pointer as struct array in C

I was trying to use void pointer as Struct array to keep a few struct object together on disk.I want to write records to disk with using void pointer(think as a cluster consist of records).
void addRecordToDataPage(City record)
{
void* data = malloc(sizeof(City)*RECORD_COUNT);
FILE* fp;
fp=fopen("sampledata2.dat", "rb");
City pageofCity [RECORD_COUNT]; //City is my Struct.
if(!fp) //if it is first access, put the record to pageofCity[0]..
{
pageofCity[0]=record;
data=pageofCity;
writeDataPageToDisk(data); ..and call the write func.
return;
}
fread(&data, sizeof(City)*RECORD_COUNT, 1, fp);
int i=0;
while( (City *)data )
{
pageofCity[i] = ((City *)data)[i];
i++;
}
pageofCity[i]=record;
}
//and this is my writer function.
void writeDataPageToDisk(void* dataPage)
{
FILE* fp;
fp=fopen("sampledata2.dat", "a");
if(!fp)
{
fp=fopen("sampledata2.dat", "wb");
writeDataPageToDisk(dataPage);
}
fwrite(dataPage, sizeof(City)*RECORD_COUNT,1,fp);
fclose(fp);
}
in the line of pageofCity[i] = ((City *)data)[i]; I got an memory error.
This is my first question in this website, please forgive me about my errors :).
There are multiple issues with your code.
The most likely cause for your error looks like:
while( (City *)data )
The value of data never changes and you are continuously reading a memory a byte ahead each time in the loop.
if (!fp)
{
int recordsRead = fread(&data, sizeof(City), READ_COUNT, fp);
int i=0;
while( i < recordsRead)
{
}
}
pageOfCity[recordsRead] = record;
Also since you are appending one extra element to your array you will need to declare the extra space for that record.
City pageofCity [RECORD_COUNT + 1]; //City is my Struct.

Sorting name of books by alphabetical order

I'm developing an application and one of the functions is the function sort_books_file which basically has to sort the name of the books in the file fp by alphabetical order and then prints them in the file fp2.
At the moment, the only thing the function does is printing the name of the books from file fp into file fp2.
I would like to know how it is possible to sort the name of the books by alphabetical order into the file fp2.
I'm a C beginner and I don't have a lot of experience in C programming...somebody helps?
#include <stdio.h>
FILE *fp;
FILE *fp2;
struct book{
int key;
char name[50];
int price;
};
sort_books_file(){
struct book b;
//r: open the file for reading (read-only)
if ((fp=fopen("books.dat","r"))==NULL){
printf("Error\n");
exit(1);
}
//w: open the file for writing (write-only).
//the file is created if it doesn't exist
if ((fp2=fopen("books_sorted.dat","w"))==NULL){
printf("Error: not possible to open the file. \n");
exit(1);
}
//while end of file has not been reached
while (!feof(fp)){
fread(&b,sizeof(b),1,fp);
if(feof(fp))
{
break;
}
fwrite(&b.name,sizeof(b.name),1,fp2);
}
fclose(fp);
fclose(fp2);
}
The easiest way is to use strcmp() on book.name to sort.
strcmp() works as follows :
syntax : int strcmp(const char *str1, const char *str2)
st1 and str2 are the strings to be compared
The function returns -1 if str1 is less than str2 and 0 if the strings are equal and 1 if str1 is greater than str2.
strcmp() uses lexicographic ordering, which means it sorts the words as it appears on the dictionary. Here's a question that discusses it.
Examples
strcmp("hello", "world")returns -1
strcmp("world", "hello") returns 1
stcmp("boo", "boo") returns 0
And here's a sorting function that does what you want (I haven't tested it) :
void sort_books_file(){
//Assume you have only maximum 10 books
struct book books[10];
strct book b;
//open files for reading and writing
//..
//..
int i = 0;
while (!feof(fp)){
fread(&b,sizeof(b),1,fp);
books[i] = b;
i++;
if(feof(fp))
{
break;
}
}
//number of books
int len = i;
//bubble sort;
int j = 0;
//Bubble sort. Google for "bubble sort"
for(i=0; i<len; i++)
{
for(j=0; j<len-1; j++)
{
//If the first book should come after the next book in the array
if(strcmp(books[j].name, books[j+1].name) > 0)
{
//swap the books
struct book temp;
temp = books[j];
books[j] = books[j+1];
books[j+1] = temp;
}
}
}
//now write each book in the array "books" into the file one by one
}
I hope this will help:
void sort(struct book* books, int n)
{
int j,i;
for(i=1;i<n;i++)
{
for(j=0;j<n-i;j++)
{
if(books[j].name < books[j+1].name)
{
struct book temp = books[j];
books[j] = books[j+1];
books[j+1] = temp;
}
}
}
}
Store Book info into an array of book structure. Then pass this array to sort function. This will do your job.
struct book LIST[n];
sort(LIST, n);

Resources