C, Code:Block, yet another sigsegv, lists - c

Good Day everyone,
Got this exercize from my prof webspace. I have this kind of text file:
Simon Phillips 30
Neil Peart 45
Vinnie Colaiuta 50
I want to store this into a list so here is my code:
struct listplot {
char name[25];
char sur[25];
int age;
struct listplot *next;
};
typedef struct listplot EL;
EL *list;
int filescan(EL *current)
{
FILE *in;
int count=0;
in=fopen("persone.txt", "r");
if (ferror(in))
{
printf("File Error\n");
return count;
}
do
{
current=malloc(sizeof(EL));
fscanf(in,"%s%s%d", current->name, current->sur, &current->age);
current->next=NULL;
if (!feof(in)) count=count+filescan(current->next);
}
while (!feof(in));
return count;
}
In main i have:
int count=filescan(list);
This code won't work.
In debug it seems that the 'do' loop goes infinite, but eventually the program crashes with segmentation fault.
Can anybody help me with this?
Thank you a lot.

Many improvents to make it more robust:
Initialize this element properly:
EL* list_header = NULL; /* Points to first element */
Increase level of indirection here:
int filescan(EL** current)
{
In the main function you have to pass the address of the list_header:
count = filescan(&list_header)
Move this section into a single function whose only concern is to open the file.
FILE *in;
int count=0;
in=fopen("persone.txt", "r");
if (ferror(in))
{
printf("File Error\n");
return count;
}
And return 0 if in is NULL or in error.
do
{
First do the scan and check if it fills 3 parameters by
EL els = {0}; /* element for scanning */
if (fscanf(in,"%s%s%d", els.name, els.sur, &els.age) == 3)
{
Move this in to a function that creates/fills/copies a new EL for a successfully filled els
current->next = create_duplicate_EL_for(els);
/* the duplicator should malloc and fill, and set next to NULL */
current=malloc(sizeof(EL));
// some strcpys //
current->next=NULL;
Apparently you want count so increase it.
And for looping, set
current = current->next;
Complete your scanf branch with an else if we don't find exactly 3 elements:
else
{
/* debug/error log code here */
}
}
while (!feof(in));
return count;

Related

Storing several string with struct in C

with following code I can store one string only.
Main problem is how to store several. If i want to enter another string after the first one it wont do it.
I didnt write it in code but when I type("KRAJ") it should get out of while loop.
typedef struct{
char Objekat[20+1];
char Mjesto[20+1];
char velicina [20];
int cijena;
char kn[3];
char stanje[20];
}Apartmani;
int main()
{
Apartmani *apartmani=(Apartmani*)malloc(sizeof(Apartmani)*50);
while(scanf("%[^,\n],%[^,],%[^,],%d%[^,],%[^\n]", &apartmani[i].Objekat,&apartmani[i].Mjesto,&apartmani[i].velicina,
&apartmani[i].cijena,&apartmani[i].kn, &apartmani[i].stanje )==6)
{
i++;
}
for(p=0;p<i;p++)
{
printf("%s %s %s %d %s %s",apartmani[p].Objekat,apartmani[p].Mjesto,apartmani[p].velicina,apartmani[p].cijena,
apartmani[p].kn, apartmani[p].stanje);
}
}
For example:
string 1: Apartman, Novalja, 100.00 m2, 750000kn, dobro ocuvano.
string 2: Kuca, Ivanbregovia, 20m2, Imtoski, 21252RH, vrijednost-neprocjenjiva.
You should use fgets() plus sscanf().
You should not cast malloc[Do I cast the result of malloc?][1]. Remember to check the return value of malloc, since it can be failed.
change the line of allocating apartmani to:
Apartmani *apartmani= malloc(sizeof(Apartmani)*50);
if(!apartmani) {return -1;}
Do not use & for the input of string.
Check the value of i because its value is limited to 50.
Your code is missing the declaration of i (should be: int i = 0), and the declaration of p also.
Your while loop can be as below:
int i = 0;
char line[100];
while(i < 50 && fgets(line,sizeof(line),stdin))
{
line[strcspn (line, "\n" )] = '\0'; // trip the enter character at the end of line.
int err = sscanf(line,"%20[^,],%20[^,],%19[^,],%d,%2[^,],%19[^\n]", apartmani[i].Objekat,apartmani[i].Mjesto,apartmani[i].velicina,&apartmani[i].cijena,
apartmani[i].kn, apartmani[i].stanje);
if(err != 6)
break;
i++;
}
If I understand you correctly, you want to store several 'Apartmani' structures.
In this case, you have 2 main possibilites :
Using array of structures (Fastest to write but less efficient)
Use linked-list (More efficient but more complex to use)
Examples
1: Using array of structures
#define MAX_APARTMANI 50
int main(void) {
int i = 0;
/* Create Apartmani array */
Apartmani *apartmani_tab[MAX_APARTMANI];
do {
/* loop by using malloc on a single element */
apartmani_tab[i] = (Apartmani *) malloc(sizeof(Apartmani));
/* While check using scanf */
} while (scanf("%[^,\n],%[^,],%[^,],%d%[^,],%[^\n]", apartmani_tab[i]->Objekat, apartmani_tab[i]->Mjesto, apartmani_tab[i]->velicina,
apartmani_tab[i]->cijena, apartmani_tab[i]->kn, apartmani_tab[i]->stanje) == 6 && ++i < MAX_APARTMANI)
/* good pratice: don't forget to free memory ! */
while (--i > 0) {
free(apartmani_tab[i]);
}
return (0);
}
2: Using linked-list
typedef struct Apartmani {
char Objekat[20+1];
char Mjesto[20+1];
char velicina [20];
int cijena;
char kn[3];
char stanje[20];
struct Apartmani *next;/* add pointer to next item in the list */
} Apartmani_t;
Apartmani_t *new_item(void) {
Apartmani_t *new_element = NULL;
new_element = (Apartmani_t *) malloc(sizeof(Apartmani));
if (!new_element)
return (NULL);
memset(new_element, 0, sizeof(*new_element));
new_element->next = NULL;
return (new_element);
}
int main(void) {
/* Initialize Apartmani list*/
Apartmani *apartmani_list = NULL, *current = NULL;
do {
if (!apartmani_list) { /* if empty list */
apartmani_list = new_item(); /* add first item */
if (!apartmani_list) /* prevent malloc errors */
break;
current = apartmani_list; /* link current pointer to list */
} else {
current->next = new_item();
if (!current->next) /* if malloc fails */
break;
current = current->next; /* update current pointer */
}
} while (scanf("%[^,\n],%[^,],%[^,],%d%[^,],%[^\n]", current->Objekat, current->Mjesto, current->velicina, current->cijena, current->kn, current->stanje) == 6) /* While check using scanf */
/* good pratice: don't forget to free memory ! */
while (apartmani_list) {
current = apartmani_list->next;
free(apartmani_list);
apartmani_list = current;
}
}
NB: I have not tried this code but the final version is probably very close to that.

Problem reading a stdin as file in a structured list in C

Basicaly what i want is to read a file in these case im using the stdin as my file FILE *f=stdin;
the files contains something like these
2019 - Frog and Mouse
1982 - Water and gelly
3025 - Sugar
...
I want to be able to read and print the names and the total number of characters of the names
so far i have created a structure and a list
typedef struct struct_data_uc{
int *uc_number;
char *uc_name;
} S_data_uc;
typedef struct List_uc_data{
S_data_uc uc_data;
struct List_uc_data *next;
} L_uc_data;
L_uc_data* UC_add(L_uc_data *list, L_uc_data data_uc){
L_uc_data *new;
new=(L_uc_data*)malloc(sizeof(L_uc_data));
if(new!=NULL){
(*new)=data_uc;
new->next=list;
return new;
}
return list;
}
then i created the functions to read the list and show the results and also ree the list
void UC_free(L_uc_data *list){
L_uc_data *aux;
while(list!=NULL){
aux=list->next;
free(list);
list=aux;
}
}
void UC_read(L_uc_data *data_uc, FILE *fin, FILE *fout){
char str[MAXSTR];
if(fout!=NULL)
fscanf(fin,"%d - %c",&data_uc->uc_data.uc_number,&data_uc->uc_data.uc_name);
void UC_Show(L_uc_data *data_uc, FILE *fout, int prompt){
if(prompt==0){
fprintf(fout,"%d - %c\n",
data_uc->uc_data.uc_number,
data_uc->uc_data.uc_name);
}else{
fprintf(fout,"%d - %c\n",
data_uc->uc_data.uc_number,
data_uc->uc_data.uc_name);
}
}
than my main
int main(){
FILE *f=stdin;
L_uc_data *list=NULL, *i, data_uc;
UC_read(&data_uc, stdin, stdout);
list=UC_add(list,data_uc);
for(i=list;i!=NULL;i=i->next)
UC_Show(i,f,0);
return 0;
}
but the program wont seems to work, any help?
There are quite a few errors in your code. I've tried to fix without modifying the original code too much. See the comments for details.
typedef struct struct_data_uc{
int uc_number; // Changed from int *
char *uc_name;
} S_data_uc;
typedef struct List_uc_data{
S_data_uc uc_data;
struct List_uc_data *next;
} L_uc_data;
// Allocate a new L_uc_data and insert into list
L_uc_data* UC_add(L_uc_data *list, int number, const char *name)
{
L_uc_data *new = malloc(sizeof(L_uc_data));
if (new != NULL) {
new->uc_data.uc_number = number;
// Need strdup here to alloc mem and copy
new->uc_data.uc_name = strdup(name);
new->next = list;
return new;
}
return list;
}
// Free the entire list
void UC_free(L_uc_data *list)
{
while (list) {
L_uc_data *aux = list->next;
// Free the mem from strdup
free(list->uc_data.uc_name);
free(list);
list = aux;
}
}
// Reads the entire file and returns a new list
L_uc_data * UC_read(FILE *f)
{
char line[MAXSTR];
L_uc_data *the_list = NULL;
// Using fgets to get the entire line, then sscanf to parse
while (fgets(line, MAXSTR, f)) {
int number;
char name[MAXSTR];
// Remember to check the return from sscanf
if (2 == sscanf(line, "%d - %[^\n]", &number, name)) {
// Add to list
the_list = UC_add(the_list, number, name);
}
}
return the_list;
}
// Print the entire list
void UC_show(L_uc_data *list, FILE *fout)
{
while (list) {
fprintf(fout, "%d - %s\n", list->uc_data.uc_number, list->uc_data.uc_name);
list = list->next;
}
}
int main()
{
L_uc_data *list = UC_read(stdin);
UC_show(list, stdout);
UC_free(list);
return 0;
}
You're making (at least) 2 mistakes. First, you are passing stdin as the argument to UC_Show, where an attempt is made to write to it. 2nd, you are not checking the value returned by printf, which is almost certainly going to indicate an error and set errno to EBADF to tell you exactly what the error is. You cannot write to stdin.

Passing a stack in C while using Threads

I am trying to make a C program to count the number of frequency of words in a document and to split the document up into N parts with each part being counted by a different thread. Everytime I run the program, I get back nonsensical data, but if I run it without the threads I get back the data that I expect.
Here is the Struct named BinarySearchTree.h
typedef struct {
char *num; /*! The contents of the <tt>Item</tt>.<br>Type: <tt>int</tt>*/
int count;
} Item; /*! \typedef Item
* \struct A struct represent one item.
*/
typedef struct node {
Item info; /*! A struct with a one <tt>int</tt> on it. */
struct node * left;
struct node * right;
} Tree;
typedef struct passargs {
char *File;
Tree *t;
int splitStart;
int splitEnd;
int i;
int a;
char words[512][512];
} pass;
Here is the main code named **BinarySearchTree.c*:
#include "BinarySearchTree.h"
#include <pthread.h>
#include <string.h>
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
// Code for integer based BST from: https://gist.github.com/ArnonEilat/4611213
Tree * add(Tree* nod, char *number) {
if (nod == NULL) {
printf("Thread number %ld\n", pthread_self());
printf("\nMaking new node for %s\n", number);
nod = (Tree*) malloc(sizeof (Tree));
if (nod == NULL) {
return NULL;
}
nod->info.num = number;
nod->info.count=1; //Increment the value if the same word is found
nod->left = NULL;
nod->right = NULL;
return nod;
}
if (strcmp(nod->info.num, number)==0) {
printf("%s==%s ",nod->info.num,number);
printf("\t%s:%d ",nod->info.num,nod->info.count);
// ++nod->info.count;
nod->info.count++;
printf("->%d\n ",nod->info.count);
return nod;
}
if (strcmp(nod->info.num, number)>0){
printf("%s>%s ",nod->info.num,number);
nod->left = add(nod->left, number);
} else {
printf("%s<=%s ",nod->info.num,number);
nod->right = add(nod->right, number);
}
return nod;
}
void printInorder(Tree* nod) {
if (nod == NULL) {
return;
}
printInorder(nod->left);
printf(" %s: %d ", nod->info.num, nod->info.count);
printInorder(nod->right);
}
void freeTree(Tree *root) {
if (root == NULL) {
return;
}
freeTree(root->left);
freeTree(root->right);
free(root);
}
int newLines(char* File){ //Count the number of new lines in the file. Split based on those not word count
int newLines=0;
char buffTemp[5120];
FILE *fp1 = fopen(File, "r");
while(1)
{
if(fgets(buffTemp, 512, fp1) ==NULL)
break;
else{
newLines++;
}
}
fclose(fp1);
return newLines;
}
//This function reads the file and adds each entry to the tree, or increments if same word is present
Tree* read(pass* info){
const char *delims = " \n"; //Deliminate by newlines and spaces
char *token;
int splitCounter=0;
FILE *fp = fopen(info->File, "r");
char buff[512];
int aT=info->a; //Putting variables into local ones
int iT=info->i;
int splitEnd = info->splitEnd;
int splitStart = info->splitStart;
char words[512][512];
memcpy(words, info->words, 512);
Tree* nod=info->t;
while(1 && splitCounter<splitEnd) //While the file does not end and we have not reached the end of the split
{
fgets(buff, 512, fp);
splitCounter++;
if(buff == NULL)
break;
else if (splitCounter>splitStart){
printf("\t %s\n", buff);
token = strtok(buff, delims); //Split via the tokens and put them into buff
while (token!=0) {
strcpy(words[iT], token);
iT += 1;
token = strtok(NULL, delims);
}
}
}
for (;aT<iT;aT++){
nod=add(nod, (char *)words[aT]); //Add each word to the tree
}
printf("\n");
fclose(fp);
info->t=nod;
memcpy(info->words,words,512);
info->i=iT;
info->a=aT;
return nod;
}
int main() {
Tree* t = NULL;
pass args;
args.t=t;
args.i=0;
args.a=0;
args.splitStart=0; //These splits are used to tell each thread where to look in the file
args.splitEnd=0;
args.File="/home/dib/CLionProjects/deleteme/readFile"; //Address of the file to be read
int numLines=newLines(args.File);
printf("\nnewLines %d\n",numLines);
int split;
printf("How many splits/threads would you like to create?\n");
scanf("%d", &split);
int iterator=numLines/split;
printf("iterator %d:", iterator);
const int NUMTHREADS= numLines/iterator + (numLines % iterator != 0);
unsigned int p;
// This for loop shows how I hope the threads would work. Uncomment the below block to see it work
for (p=0; p<NUMTHREADS; p++){
args.splitStart=args.splitEnd;
if (args.splitEnd+iterator>numLines) args.splitEnd=numLines;
else args.splitEnd+=iterator;
read(&args);
}
pthread_t th[NUMTHREADS];
int threads[NUMTHREADS];
//This is my attempt at using threads to solve the same problem as the above for loop
// for(p=0; p< NUMTHREADS; p++){
// threads[p] = p;
// args.splitStart=args.splitEnd;
// if (args.splitEnd+iterator>numLines) args.splitEnd=numLines;
// else args.splitEnd+=iterator;
// printf("split end: %d",args.splitEnd);
// pthread_create(&th[p], NULL, &read, &args);
// }
printInorder(args.t);
freeTree(args.t);
exit(0);
}
And finally the document I have been using as a test case named readFile:
five five five one two
two three three four four
three six seven six six
four six five seven seven
seven seven seven seven six
five four six
I tried implementing the solution found here : passing struct to pthread as an argument
but did not know what thread_handles was, and could not get it to work though the problem faced in that link is similar. So am I also just having a problem with memory allocation or is it something completely different?

Searchin in a stack

This is my code for the searching part and it's not working. Can you give me a little help on this? I'm newbie on programming and I really just suck at pointers. Thanks.
typedef struct Dictionary_Entry{
int index;
char character[100];
struct Dictionary_Entry *link;
}Dictionary_Entry;
typedef struct Dictionary{
Dictionary_Entry *top;
}Dictionary;
int check_in_dictionary(Dictionary *dictionary, char string[100], char file_char[100]){
Dictionary_Entry *runner = dictionary->top;
strcat(string, file_char);
while(runner != NULL){
if((strcmp(string, runner->character)) == 0){
break;
return runner->index;
}
}
return -1;
}
The break keyword leaves the loop, so your return runner->index line doesn't get executed. Swap the two lines (or remove break, since return will also leave the loop, in its way), and you should be fine.
Here is the corrected version with my comments starting with ////
int check_in_dictionary(Dictionary *dictionary, char string[100], char file_char[100]){
Dictionary_Entry *runner = dictionary->top;
strcat(string, file_char);
while(runner != NULL){
if((strcmp(string, runner->character)) == 0){
return runner->index; // found
//// break not neccessary here as return returns anyway
}
runner = runner->link ; //// goto next entry
}
return -1;
}
BTW strcat(string, file_char); is not necessary, you could compare directy to file_char like this strcmp(file_char, runner->character)
You need to scan the Dictionay in while loop.
something like this:
while(runner != NULL){
if((strcmp(string, runner->character)) == 0){
return runner->index;
}
runner = runner->next; /* go to next element in dictionary */
}

Implementing LRU page replacement algorithm

Edited to include short description of what is expected from the code.
#include <sys/file.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define MAX_PAGE 0xFF+1
/* page table entry you may need to add your own fields to it*/
typedef struct
{
unsigned short frame;/*location*/
unsigned int valid:1;
unsigned int in_mem:1;
unsigned int dirty:1;
unsigned int last_frame;
} pt_entry;
/* list entry for physical frames*/
struct list_item
{
unsigned short frame;
struct list_item *next;
struct list_item *prev;
int page_num;
};
typedef struct list_item *list;
void start_simulation(FILE *);
void resolve(int);
unsigned short find_frame(void);
unsigned short find_victim(void);
void display_stats(void);
void to_resident_set(list);
void free_mem(list);
void invalidate(unsigned short);
/*============================ header ends here ============================== *
/*#include "lru.h"*/
pt_entry pte[MAX_PAGE]; /* page table */
int mem_size; /* physical memory size in page frames */
list free_list_head; /* free list */
list res_set_head; /* resident set */
int total_fault = 0; /* total number of page faults */
int total_ref = 0; /* total number of memory references */
/* main program:
** read in paramters, and open the input file start the simulation */
int main(int argc, char *argv[])
{
FILE *stream;
if (argc != 3)
{
printf("The format is: pager file_name memory_size.\n");
exit(1);
}
printf("File used %s, resident set size %d\n", argv[1], atoi(argv[2]));
if ((stream = fopen(argv[1], "r")) == NULL)
{
perror("File open failed");
exit(1);
}
mem_size = atoi(argv[2]);
start_simulation(stream);
fclose(stream);
}
/*initialise the page table
** initialise the resident set, and the free list
** in the simulation loop
**16-bit memory addresses representing the program trace are read from the input
**file one by one the virtual address is resolved ie. physical frame for the
**virtual page identified
**the loop exits when it encounters the end of file
** free memory allocated for lists
** display statistics
*/
void start_simulation(FILE * stream)
{
char *addr_buf;
int address;
int i, n;
list new_entry, current;
/* initialise the page table */
for(i=0; i<MAX_PAGE;i++)
{
pte[i].frame = -1;
pte[i].valid = 0;
pte[i].dirty = 0;
pte[i].in_mem = 0;
}
/* initialise the resident set - empty*/
res_set_head = (list)malloc(sizeof(struct list_item));
res_set_head->next = res_set_head;
res_set_head->prev = res_set_head;
/* initialise free list - all physical pages*/
free_list_head = (list)malloc(sizeof(struct list_item));
free_list_head->next = free_list_head;
free_list_head->prev = free_list_head;
current = free_list_head;
for(i=0; i<mem_size;i++)
{
new_entry = (list)malloc(sizeof(struct list_item));
current->next = new_entry;
new_entry->prev = current;
new_entry->next = free_list_head;
new_entry->frame = i;
current = new_entry;
free_list_head->prev = current;
}
/* main simulation loop */
while( (n = fscanf(stream, "%x", &address)) != -1)
{
resolve(address);
total_ref++;
}
free_mem(free_list_head);
free_mem(res_set_head);
display_stats();
return;
}
/* resolve address reference
** if page table entry valid - do nothing
** if page table entry invalid - find a physical frame for this page
**and update pte for the page
*/
void resolve(int address)
{
unsigned short frame_alloc;
int virt_page;
static int disp_counter = 0;
virt_page = address >> 8;
if (pte[virt_page].valid == 1)
{
/*Was trying to implement */
//pte[virt_page].frame = pte[0];
}
else
{
frame_alloc = find_frame();
pte[virt_page].valid = 1;
pte[virt_page].frame = frame_alloc;
total_fault++;
}
}
/* find_frame:
** if free list is empty find a victim frame
** else detach the last frame of the free list and attach it
** to the resident set
** return frame number
*/
unsigned short find_frame()
{
unsigned short frame;
list current, new_tail;
if (free_list_head == free_list_head->prev) /* free list empty */
frame = find_victim();
else
{
new_tail = free_list_head->prev->prev;
new_tail->next = free_list_head;
current = free_list_head->prev;
free_list_head->prev = new_tail;
to_resident_set(current);
frame = current->frame;
}
return frame;
}
/* to_resident_set:
** attach a list entry at the end of resident set
*/
void to_resident_set(list current)
{
list tail;
tail = res_set_head->prev;
tail->next = current;
current->next = res_set_head;
current->prev = tail;
res_set_head->prev = current;
}
/* find_victim:
** As you can see I simply take the first page frame from the resident set list.
** This implements the FIFO replacement strategy. Your task is to replace it with
** a more efficient strategy.
*/
unsigned short find_victim()
{
int i;
unsigned short frame=0;
list current;
for(i=0;i<MAX_PAGE;i++)
{
if (pte[i].frame == frame && pte[i].valid == 1)
{
frame = res_set_head->next->frame;
invalidate(frame);
current = res_set_head->next;
res_set_head->next = current->next;
res_set_head->next->prev = res_set_head;
to_resident_set(current);
break;
}
}
return frame;
}
/* invalidate:
** invalidate the page table entry for the victim page */
void invalidate(unsigned short frame)
{
int i;
for(i=0;i<MAX_PAGE;i++)
{
if (pte[i].frame == frame && pte[i].valid == 1)
{
pte[i].valid = 0;
pte[i].frame = -1;
break;
}
}
}
/* display_stats:
** This is very basic, you may want to make it more sophisticated,
** for example save the data from multiple runs into a file for
** comparison etc
*/
void display_stats()
{
printf("\nProcess issued %d memory references\n", total_ref);
printf("Process triggered %d page faults\n", total_fault);
printf("Pafe fault rate is %d percent\n",((total_fault*100)/total_ref));
}
/* free memory allocated to the list */
void free_mem(list head)
{
list current,tail;
tail = head->prev;
current = head;
while (current->prev != tail)
{
current = current->next;
free(current->prev);
}
}
The most obvious problem lies in the input to your algorithm.
The restpage array is a global array and will thus be initialised to contain only the value 0. You then use these array elements as the page-numbers you are requesting, which means that your algorithm processes only requests for page 0 if mem_size < 100.
And if mem_size >= 100, you are overrunning the array bounds and land squarely in the land of undefined behaviour.
There are two fixes you need to make:
Just as you are checking for a valid file in the command-line arguments, you must also check that mem_size is not too large
Write an additional loop to give each element in restpage a random value, to ensure not all page requests are for the same page.
You have dimensioned restpage to [100] but mem_size seems freely configurable, is this the intent?
mem_size = atoi(argv[2]);
fclose(stream);
..
for(i=0;i<mem_size;i++)
{
totalabsence+=find_victim(&pt,restpage[i]);
}
EDIT:
I see one bug in your new code, in your find_victim you don't initialize the local variable 'frame'
EDITx2:
When you read from the file you may just want to put one hex address on each line
and use instead fgets() to read the file line by line (or load the whole file and
go through it line by line).

Resources