I'm writing a c program to simulate FCFS scheduling algorithm. It will accept a command line argument as a file and calculate turnaround time and wait time for every process. However it can not read values from text file into variables successfully.
Here is the code
#include <stdio.h>
#define N 50
int main(int argc, char** argv)
{
int i = 0;
char line[20];
int n=0;
typedef struct
{
char name; //process name
int at; //arrive time
int pt; //process time
int ft; //finish time
int rt; //round time
int wt; //wait time
} Process;
Process pcs[N];
FILE* file = fopen( argv[1], "r");
while (fgets(line,sizeof(line),file) != NULL)
{
sscanf(line, "%s %d %d", pcs[i].name, pcs[i].at, pcs[i].pt);
line[strlen(line)-1] = '\0';
printf("%s %d %d\n",pcs[i].name, pcs[i].at, pcs[i].pt);
i++;
}
fclose(file);
pcs[0].ft=pcs[0].at+pcs[0].pt;
pcs[0].rt=pcs[0].ft-pcs[0].at;
pcs[0].wt=0;
for (n;n<4;n++)
{
if (pcs[n].at<pcs[n-1].ft)
{
pcs[n].ft=pcs[n-1].ft+pcs[n].pt;
pcs[n].rt=pcs[n].ft-pcs[n].at;
pcs[n].wt=pcs[n-1].ft-pcs[n].at;
}
else
{
pcs[n].ft=pcs[n].at+pcs[n].pt;
pcs[n].rt=pcs[n].ft-pcs[n].at;
pcs[n].wt=pcs[n-1].ft-pcs[n].at;
}
}
int x = 0;
for (x;x<n;x++)
{
printf("process name: %s", pcs[x].name);
printf("Turnaround Time: %d", pcs[x].rt);
printf("Wait Time: %d\n", pcs[x].wt);
}
return(0);
}
Here is the input file
And the output is
Thanks for any help and advice.
As pointed by alk, you're doing some mistakes:
In your struct declaration you have declared name as a single character, but in your file reading code(while loop containing fgets) you're passing %s which is for strings, so better change your declaration to a char name[SIZE] rather than char name. Bdw you should read the compiler warning and try to understand it, since that's what is creating problem.
You are supposed to pass address of variables in sscanf and it's variants, so change line 26 to:
sscanf(line, "%s %d %d", pcs[i].name, &pcs[i].at, &pcs[i].pt);
Related
I'm having problems using a fscanf function. It never reads it correctly and always results in blanks.
fscanf(f, " %[^;];%[^;];%d;%d;%d;%d;%[^;];%d;%[^\n]",
arr[i].loc1, arr[i].loc2, &arr[i].price, &arr[i].rooms,
&arr[i].bathroom, &arr[i].carpark, arr[i].type, &arr[i].area, arr[i].furnish);
The code above always outputs " 0 0 0 0 0". But when I try using a scanf and manually input one of the lines, it works perfectly.
The file it's reading from is a .csv file. Here is the contents:
Mont-Kiara;Kuala-Lumpur;1000000;2;2;0;Built-up;1000;Partly
Cheras;Kuala-Lumpur;310000;3;2;0;Built-up;1000;Partly
Kepong;Kuala-Lumpur;358000;3;3;0;Built-up;1000;Partly
Taman-Desa;Kuala-Lumpur;455000;2;2;0;Built-up;1000;Partly
Kepong;Kuala-Lumpur;358000;3;3;0;Built-up;1000;Partly
Kepong;Kuala-Lumpur;358000;3;3;0;Built-up;1000;Partly
And here is the full code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct houseData {
char loc1[101];
char loc2[101];
int price[101];
int rooms[101];
int bathroom[101];
int carpark[101];
char type[101];
int area[101];
char furnish[101];
} arr[1001];
int read() {
int i = 0;
struct houseData arr[800];
char temp1[100];
FILE *f = fopen("file.csv", "r");
while(!feof(f)){
fscanf(f, " %[^;];%[^;];%d;%d;%d;%d;%[^;];%d;%[^\n]"
, &arr[i].loc1, &arr[i].loc2, &arr[i].price, &arr[i].rooms,
&arr[i].bathroom, &arr[i].carpark, &arr[i].type, &arr[i].area, &arr[i].furnish);
i++;
}
fclose(f);
}
int main() {
read();
printf("%s %s %d %d %d %d %s %d %s", arr[i].loc1, arr[i].loc2, *arr[i].price, *arr[i].rooms, *arr[i].bathroom, *arr[i].carpark, arr[i].type, *arr[i].area, arr[i].furnish);
return 0;
}
There are a lot of issues in your code. Here's a version that may help. The error messages in this version are far from ideal (this does not distinguish between an input format error and a error reading data, for example, nor does it provide much detail on the location of the error), and there is still the possibility of undefined behavior on certain inputs, (see Is `scanf("%d", ...)` as bad as `gets`?) but this should point you in the right direction. Well, at least it may help to improve your use of scanf, but a very reasonable argument can the be made that the "right direction" is to stop using scanf completely. It is very difficult to get things right with scanf, and attempting to do so winds up being much more complex that just using fgets. But for simple use cases it is ... still pointless to use scanf. See http://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html and many other resources that explain why scanf is a terrible choice.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct houseData{
char loc1[101];
char loc2[101];
int price;
int rooms;
int bathroom;
int carpark;
char type[101];
int area;
char furnish[101];
};
int
read(FILE * f, struct houseData *h)
{
return 9 == fscanf(f, " %100[^;]; %100[^;]; %d; %d; %d; %d; "
"%100[^;]; %d; %100[^\n]", h->loc1, h->loc2, &h->price,
&h->rooms, &h->bathroom, &h->carpark, h->type, &h->area,
h->furnish);
}
int
main(int argc, char **argv)
{
int rv;
FILE *f = argc > 1 ? fopen(argv[1], "r") : stdin;
if( f == NULL ){
perror(argv[1]);
return EXIT_FAILURE;
}
struct houseData h;
int i = 0;
while( read(f, &h) ){
printf("%d: %s %s %d %d %d %d %s %d %s\n", ++i,
h.loc1, h.loc2, h.price, h.rooms, h.bathroom,
h.carpark, h.type, h.area, h.furnish);
}
if( ! feof(f) ){
fprintf(stderr, "Error near line %d\n", i);
}
fclose(f);
}
I'm working on a task where I need to read a long .txt file. The first line contains the number of lines the .txt file has, the rest of the lines follow the same structure, "int int int char:char".
How do I read the first line separately from the rest?
I wrote the following code:
FILE *fajl;
falj = ("musor.txt", "r");
while (!feof(fajl) && fajl > 1)
{
fscanf_s(fajl, "%d %d %d %[^:]c:%c\n", &tomb[i].ado, &tomb[i].perc, &tomb[i].masodperc, &tomb[i].eloado, &tomb[i].cim);
i++;
}
Sorry for the unknown words, the variable names are in Hungarian.
So this is basically just the collection of all the comments from the question.
//-------------------------
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct Tomb
{
int masodperc, eloado, ado, perc;
char cim;
};
typedef struct Tomb Tomb;
//-------------------------
int main(int argc, char *argv[])
{
char linesLength[10], stringFajl[100];
FILE *fajl;
fajl = fopen("musor.txt", "r");
if(fgets(linesLength, 100, fajl)==NULL || fajl == NULL) //first line read
{
printf("error\n");
return -1;
}
int length = atoi(linesLength), i=1;
Tomb tomb[length];
while (fgets(stringFajl, 100 ,fajl )!=NULL || i<=length)
{
sscanf(stringFajl, "%d %d %d %d [^:]c:%c", &tomb[i].ado, &tomb[i].perc, &tomb[i].masodperc, &tomb[i].eloado, tomb[i].cim);
i++;
}
fclose(fajl);
return 0;
}
#define max 5
typedef struct
{
char tar[20];
int trab[31];
}data;
int main()
{
int i,j, aux;
char fname[25];
data inf[max];
/*for(i=0;i<max;i++)
{
strcpy(inf[i].tar,inf[i-1].tar);
}*/
printf("File name?");
scanf(" %s", fname);
FILE *f=fopen("fname","r");
if(f== NULL)
{
printf("Cannot find\n");
return 1;
}
I try to read a file I'm very certain is in the same dir, however each time the FILE pointer returns NULL.
I would appreciate any help :(
Although you've tagged this as C++, your code looks more like C, so I'm using a C signature for main. The main problem you have is quotes around fname. Your code is ignoring the path that was entered and trying to open a file with the literal name fname.
int main(void)
{
int i,j, aux;
char fname[25];
printf("File name? ");
scanf(" %24s", fname); /* Always use width specifier on %s */
FILE *f=fopen(fname, "r"); /* No quotes around fname */
if( f == NULL ){
perror(fname);
return 1;
}
...
I've been racking my brain against this program for a couple months now. This was an assignment of a class I took last semester and while I passed, I could never make this one assignment work correctly (Seg Fault). I welcome any help or tips but I greatly appreciate explanations with answers to follow along.
This program is supposed to receive a filename that contains a list of filenames (240 for my example). Those files are located in a folder within the same directory as the list and the program. This program is supposed to take this list and parse it for 4 threads, splitting the filenames evenly for each thread (60 per thread for my example). Each thread then takes this list of 60 file names and opens each file one by one performing a WordCount function on each file. Once the threads complete their tasks, they are supposed to print the results for each file in order with each thread in its own block(i.e. Thread1 Results | Thread2 Results | Thread 3 Results, etc...).
I've debugged quite a bit and know that up until the threads are created everything works as it is supposed to. My problem seems to be during thread launch/execution. I've tried adding mutex to the mix but sadly it hasn't helped. I seem to be missing something or over thinking something as some of my class mates have shown me their much more compact code. Please assist. Thanks!
Here is the Main:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define MaxLine 200
#define NUMTHREADS 4
char Line[MaxLine];
pthread_mutex_t Lock = PTHREAD_MUTEX_INITIALIZER;
typedef struct thread {
int id;
char file;
}ThreadData;
/* ThreadFunction will give each thread its processes to execute */
void *threadFunc (void *td) {
ThreadData *data = (ThreadData*)td;
int thread_num=data->id;
char filename=data->file;
printf("thread debug tid: %d and file: %c",thread_num, filename);
pthread_mutex_trylock(&Lock);
FILE *fn = fopen(filename, "r");
if (fn == NULL) {
error("ERROR: Opening file");
return 1;
}
while (fgets(Line, sizeof(Line), fn) != NULL) {
CountWord(thread_num, Line);
}
fclose(fn);
free(data);
pthread_mutex_unlock(&Lock);
pthread_exit(NULL);
}
int main(int argc, char *argv[]){
char buf[20];
int c, i, t, tnum, QUEUETOTAL;
pthread_t thread[NUMTHREADS];
ThreadData td[NUMTHREADS];
if (argc != 2){
fprintf(stderr,"ERROR: Usage must be Countfile filename\n", argv[0]);
exit(0);
}
char const* const filename = argv[1];
FILE* file = fopen(filename, "r");
if ( file == 0 ){
printf( "Could not open file!\n" );
exit(0);
}
/* Count iterations of while loop to divide files among threads. */
while (fgets(Line, sizeof(Line), file)){
QUEUETOTAL++;
}
/* Divide work for threads. */
int thread2taskstart=(QUEUETOTAL/NUMTHREADS); //60
int thread3taskstart=(QUEUETOTAL/NUMTHREADS)*2; //120
int thread4taskstart=(QUEUETOTAL/NUMTHREADS)*3; //180
// QUEUETOTAL = 240
rewind(file);
FILE *tempfile1 = fopen("temp1.txt","w");
for (i=0; i<thread2taskstart; i++) {
// populate tempfile1 with entries 1-60
if(fgets(Line,sizeof(Line),file)!=NULL) {
fputs(Line,tempfile1);
//printf("Debug temp1: %s",Line);
}
}
fclose(tempfile1);
FILE *tempfile2 = fopen("temp2.txt","w");
for (i=thread2taskstart; i<thread3taskstart; i++) {
// populate tempfile2 with entries 60-120
if(fgets(Line,sizeof(Line),file)!=NULL) {
fputs(Line,tempfile2);
//printf("Debug temp2: %s",Line);
}
}
fclose(tempfile2);
FILE *tempfile3 = fopen("temp3.txt","w");
for (i=thread3taskstart; i<thread4taskstart; i++) {
// populate tempfile3 with entries 120-180
if(fgets(Line,sizeof(Line),file)!=NULL) {
fputs(Line,tempfile3);
//printf("Debug temp3: %s",Line);
}
}
fclose(tempfile3);
FILE *tempfile4 = fopen("temp4.txt","w");
for (i=thread4taskstart; i<=QUEUETOTAL; i++) {
// populate tempfile3 with entries 180-240
if(fgets(Line,sizeof(Line),file)!=NULL) {
fputs(Line,tempfile4);
//printf("Debug temp4: %s",Line);
}
}
fclose(tempfile4);
fclose(file);
/* Prepare parameters & launch (4) threads. Wait for threads
to finish & print out results as specified in assignment. */
printf("Counting files …\n");
for(t=0;t<NUMTHREADS;t++){
tnum=t+1;
snprintf(buf, "temp%d.txt", tnum);
printf("debug tnum and array: %d and %s\n",tnum, buf);
td[t].id = tnum;
td[t].file = buf;
// Creates a new thread for each temp file.
pthread_create(&thread[t], NULL, threadFunc, td);
}
// Joins threads.
printf("debug: printing threads \n");
for(t=0;t<NUMTHREADS;t++){
pthread_join(thread[t], NULL);
printf("------------------------- Processes finished for Thread %d ----------------------- \n",t+1);
}
return 0;
}
Here is the Count Function:
#include <stdio.h>
int CountWord(int tinfo, char cfile){
int i;
int ccount = 0;
int wcount = 0;
int lcount = 0;
FILE *fname;
char fn[strlen(cfile) + 18];
sprintf(fn, "./CountingFolder/%s", cfile);
printf("Debug: %s\n", fn);
fname = fopen(fn, "r");
if (fname == NULL) {
error("ERROR: Opening file");
}
while ((i = fgetc(fname)) != EOF){
if (i == '\n') {
lcount++;
}
if (i == '\t' || i == ' '){
wcount++;
}
ccount++;
}
printf("Threadid %d processes %s which has %d characters, %d words and %d lines\n", tinfo, cfile, ccount, wcount, lcount);
fclose(fname);
return 0;
}
1) Probably a typo. But
int CountWord(int tinfo, char cfile){ .. }
should be
int CountWord(int tinfo, char *cfile){ .. }
2) You are passing the same buf to all threads from main(). Data race and undefined behaviour.
3) None of the snprintf() calls take the size argument. Undefined behaviour.
4) Since all threads work on different data, you don't need a lock at all.
5) You didn't allocate td array. So you can't call free(data); in the thread function. Undefined behaviour.
There may be more issues with the code but the segfault is likely because of (3) or (5).
In your code here
snprintf(buf, "temp%d.txt", tnum);
printf("debug tnum and array: %d and %s\n",tnum, buf);
td[t].id = tnum;
td[t].file = buf;
the last line assigns a pointer into the file field of this struct
typedef struct thread {
int id;
char file;
}ThreadData;
Shouldn't it be char *file; ? I don't have thread.h in MSVC so I can't compile it. Surely you have all warnings enabled??
I am trying to write a program in C that reads from an input file ("input0") which follows the format:
John Doe 1230 4.0
I am trying to read from the document using fscanf and enter those values into a struct. Currently, though, after compiling and once I run my code, I run into the enigmatic "Segmentation Fault (Core Dumped)."
The line in my code currently giving off this error the line with fscanf statement. I can't find the solution to this.
Additionally, strcpy gives an error once its uncommented. I get a warning when I run the code, which I believe has to be with a discrepancy with what is a pointer and what's the string, another problem I can't fix. Any help would be appreciated.
typedef struct {
char fname[1000];
char lname[1000];
long int id;
double gpa;
} student_t;
int main(int argc, char *argv[]) {
FILE *db;
student_t students[1000];
char* fname[1000];
char* lname[1000];
long int id[1000];
double gpa[1000];
long int i, j;
i = 0;
db = fopen("input0", "r");
while(fscanf(db, "%s %s %d %lf", fname[i], lname[i], id[i], gpa[i]) != EOF) {
//strcpy(students[i].fname, fname[i]);
//strcpy(students[i].lname, lname[i]);
students[i].id = id[i];
students[i].gpa = gpa[i];
i++;
}
for(j = 0; j <= i; j++) {
//printf("%s %s %d %f\n", _SJ.fname, _SJ.lname, _SJ.id, _ST.gpa);
}
fclose(db);
}
When you declare e.g.
char* fname[1000];
you have an array of 1000 uninitialized pointers. Trying to use one of those pointers will lead to undefined behavior. You need to either allocate memory for the pointers, or point them to some other (already allocated) memory.
Actually, I think what you really meant to do is
fscanf(db, "%s %s %d %lf",
students[i].fname, students[i].lname, &students[i].id, &students[i].gpa)
I also suggest you read e.g. this fscanf reference, as fscanf can return other values that means there are errors in the input (for example if the input file is malformed).
You forgot to use & for long int and double in fscanf
while(fscanf(db, "%s %s %d %lf", fname[i], lname[i], &id[i], &gpa[i]) != EOF)
Change this line
while(fscanf(db, "%s %s %d %lf", fname[i], lname[i], id[i], gpa[i]) != EOF)
to
while(fscanf(db, "%s %s %d %lf", students[i].fname, students[i].lname, &students[i].id, &students[i].gpa) != EOF)
Then probably you do not need any strcpy or copy back int and double to the stucture.
char *fname[1000] will allocate 1000 pointers of char
I fixed some problems:
typedef struct {
char fname[1000];
char lname[1000];
long int id;
double gpa;
} student_t;
student_t students[1000];
int main(int argc, char *argv[]) {
FILE *db;
long int i=0, j;
db = fopen("input0.txt", "r");
if (db == NULL)
{
perror("Error opening file input0");
return -1;
}
while (fscanf(db, "%s %s %d %lf", students[i].fname, students[i].lname,
&students[i].id, &students[i].gpa) != EOF)
{
i++;
}
for (j = 0; j < i; j++) {
printf("%s %s %d %f\n", students[j].fname, students[j].lname, students[j].id, students[j].gpa);
}
fclose(db);
}
You can read directly to the students array, avoiding having to play with strcpy. The missing & were added too.
Please note that I moved students[1000] outside the main function, as with the standard stack size of VS2013 the code generated a stack overflow. When opening file, always check if you managed to open them... this will save many hours of debug pain in the future. The j<=i condition was changed to j
In your original code:
char* fname[1000];
You used 1000 char*, but this line only allocates the space for the pointers itself. I think you were trying to write something like:
char fname[1000];
In this case, frame would have 1000 chars you could use to store the name read from the input file. It is very important to note the diference between these two lines before going further studying C. In the case of fname[1000], you could read to fname, i.e., no indexes. Then strcpy(students[i].fname, fname). I hope it helps.