C fork and pipe add numbers from a file - c

Totals different for same file when executed.
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_FILE_NAME 100
#define RUNS 1
int main() {
int num,i;
FILE *fp;
char*s, buf[1024];
int count =0;
char c;
char filename[MAX_FILE_NAME];
printf("Enter filename: ");
scanf ("%s",filename);
if ((fp =fopen(filename, "r")) == NULL) {
printf("Error");
exit(1);
}
fscanf(fp,"%d",&num);
for (c = getc(fp); c!= EOF; c = getc(fp))
{
if (c == '\n'){
count = count+1;
}
}
printf("%s has %d numbers \n", filename, count);
int f;
printf("Choose from the options how many processes you want to use [1,2,4]: ");
scanf("%i", &f);
printf("%i processes \n", f);
int fds[f+1][2];
int numb[count];
int x,k;
time_t start, finish;
start = time(NULL);
for(i = 0; i < RUNS; i++)
{
pipe(fds[f]);
for( x = 0; x<f; x++)
{
pipe(fds[x]);
int ind[2];
ind[0] = ((x)*(count/f));
ind[1] = ((x+1)*(count/f));
write(fds[x][1], &ind, 2* sizeof(int));
if (fork() ==0)
{
int t =0;
int ind2[2];
read(fds[x][0], &ind2, 2*sizeof(int));
for( k = ind2[0]; k<ind2[1]; k++)
{
t += numb[k];
}
write(fds[f][1], &t, sizeof(int));
exit(0);
}
}
int m, tmp, total;
total = 0;
for( m = 0; m < f; m++)
{
for( m = 0; m < f; m++)
{
read(fds[f][0], &tmp, sizeof(int));
sleep(5);
total += tmp;
}
printf("DOne calc \n");
printf("Total: %i \n", total);
}
finish = time(NULL);
float runtime = (float)((finish-start)/RUNS);
printf("runtime: %f \n", runtime);
fclose(fp);
return 0;
}

You get random result for the same input because the calculation based on uninitialized int numb[count]; values.
According to the C99 standard, section 6.7.8.10:
If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate.
Because of it int numb[count]; contains some random junk from memory. To get predictive results use explicit initialization:
#include <string.h> // memset
int numb[count];
memset (numb, 0, sizeof(numb)); // Zero-fills
Use the code bellow to put numbers from filename file into numb:
int i = 0;
char line[1024];
fseek(fp, 0, SEEK_SET);
while(fgets(line, sizeof(line), fp) )
{
if( sscanf(line, "%d", &numb[i]) == 1 ) // One number per line
{
++i;
}
}

Related

Count repeated numbers in a file

So I'm having this file myFile.txt with the following numbers in it: 1 2 3 4 5 6 7 8 9 0 2 3 4 5 6 6 5 4 3 2 1. I'm trying to write a program that calculates how many times a number from 0 to 9 is repeated, so it would be printed out like that Number %d repeats %d times. Right now I'm stuck at printing out the n number of elements of that file, so in example, if I would like to calculate how many times the 15 first numbers repeat themselves, firstly I would print out those 15 numbers, then the number of times each number repeats. But when I'm trying to print out those 15 numbers, it prints me this: 7914880640-10419997104210821064219560-1975428800327666414848.
Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
int main() {
FILE *fp;
fp = fopen("myFile.txt", "r");
char c;
int n, i, count = 0;
for (c = getc(fp); c != EOF; c = getc(fp)) {
if (!(c == ' '|| c == '\n'))
count = count + 1;
}
printf("The amount of numbers is:%d\nTill which element of the list would you like to count the amount of the each element: \n", count);
scanf("%d", &n);
int a[n];
if (n <= count) {
for (i = 0; i < n; i++) {
fscanf(fp, "%d", &a[i]);
}
for (i = 0; i < n; i++) {
printf("%d", a[i]);
}
} else {
printf("Error");
}
fclose(fp);
return 0;
}
That's the final solution.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
int count_occur(int a[], char exist[], int num_elements, int value)
{
int i, count = 0;
for (i = 0; i<num_elements; i++)
{
if (a[i] == value)
{
if (exist[i] != 0)
return 0;
++count;
}
}
return(count);
}
int main()
{
int a[100],track[10];
FILE *fp;
fp = fopen("myFile.txt", "r");
char c,exist[20]= {0};
int n,i,num,count=0,k=0,eval;
for (c = getc(fp); c != EOF; c=getc(fp))
{
if (!(c==' '|| c=='\n'))
count=count+1;
}
rewind(fp);
printf("The amount of numbers is:%d\nTill which element of the list would you like to count the amount of the each element: \n", count);
scanf("%d", &n);
if (n<=count)
{
while(fscanf(fp, "%d", &num) == 1)
{
a[k] = num;
k++;
}
for (i=0; i<n; i++)
{
printf("%d ", a[i]);
}
}
else
{
printf("Error");
}
fclose(fp);
if (n<=count)
{
for (i = 0; i<n; i++)
{
eval = count_occur(a, exist, n, a[i]);
if (eval)
{
exist[i]=1;
printf("\nNumber %d was found %d times\n", a[i], eval);
}
}
}
return 0;
}

Storing numbers as (x, y) cordinates from a file at a specific point

I have an Instance File from which I need to store the NUM_PT and all the respective co-ordinates in the form of a 2D array system (personal choice so I can access them easily). I am able to retrieve the NUM_PT but I am stuck at reading the successive cordinates into my array.
HERE IS WHAT I HAVE DONE
/* Assignment 2 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#define MAXS 256
int main(int argc, char *argv[])
{
int num_pt;
int inputfile = 0, outputfile = 0, i;
for (i = 1; i < argc; i++)
{
if (strcmp (argv[i], "-i") == 0)
inputfile = i+1;
if (strcmp (argv[i], "-o") == 0)
outputfile = i+1;
}
if (inputfile == 0)
{
/* invalid command line options */
printf("\nIncorrect command-line...\n");
printf("> %s [-i inputfile [-o outputfile]]\n\n", argv[0]);
exit(0);
}
FILE *fp;
fp = fopen(argv[inputfile], "r");
int count = 0;
if (fp == 0)
{
printf("\nCould not find %s\n", argv[inputfile]);
exit(0);
}
char line[MAXS];
while (fgets(line, sizeof line, fp) != NULL)
{
if (count == 4)
{
fscanf(fp, "%d", &num_pt);
break;
}
else
count++;
}
int arr[num_pt][1];
while (fgets(line, sizeof line, fp) != NULL)
{
if (count == 5)
{
int k, j, cord;
for (k = 0; k < num_pt; k++)
{
for (j = 0; j < num_pt; j++)
{
while (fscanf(fp, "%d%d", &cord) > 0)
{
arr[k][j] = cord;
j++;
}
}
}
}
}
fclose(fp)
return 0;
}
After retrieving NUM_PT i tried reinitializing the count to 5 because the cordinates start from **LINE 6* in the file.
ERROR FROM COMPILER
Language: c99 ; Compiler: gcc
sample for "Storing numbers as (x, y) cordinates from a file" (It is better not to fix the reading position)
#include <stdio.h>
typedef struct point {
int x, y;
} Point;
int readPoint(FILE *fp, Point *p);
int readInt(FILE *fp, int *n);
int main(void){
FILE *fp = fopen("instance10_001.txt", "r");
Point p;
int MAX_X, MAX_Y;
readPoint(fp, &p);
MAX_X = p.x;
MAX_Y = p.y;
printf("MAX_X:%d, MAX_Y:%d\n", MAX_X, MAX_Y);
int NUM_PT;
readInt(fp, &NUM_PT);
printf("NUM_PT:%d\n", NUM_PT);
Point arr[NUM_PT];
for(int i = 0; i < NUM_PT; ++i){
readPoint(fp, &arr[i]);
printf("Point(%d, %d)\n", arr[i].x, arr[i].y);
}
fclose(fp);
}
int readLine(FILE *fp, char *buff, int buff_size){
while(fgets(buff, buff_size, fp)){
if(*buff == '#' || *buff == '\n')
continue;
return 1;
}
return 0;
}
#define LINE_MAX 128
int readPoint(FILE *fp, Point *p){
char buff[LINE_MAX];
if(readLine(fp, buff, sizeof buff)){
return 2 == sscanf(buff, "%d %d", &p->x, &p->y);
}
return 0;
}
int readInt(FILE *fp, int *n){
char buff[LINE_MAX];
if(readLine(fp, buff, sizeof buff)){
return 1 == sscanf(buff, "%d", n);
}
return 0;
}

fprintf saves wrong data to file

I have an input file a.txt:
1 abc 3
2 efgh 4.5
3 text 3
4 xyz 2
So basically, it has 3 columns, first one is int, second is text, and third is double. I need to read this file by rows (which actually works, I guess), but have some problems with writing only second and third column to another (b.txt) file. fprinft saves something like this:
0.000000
0.000000
0.000000
0.000000
xvæ$ 0.000000
instead of
abc 3
efgh 4.5
text 3
xyz 2
I simply need to save only the second and the third column from a.txt file to b.txt file. Here's my code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct mypair
{
char string[1024];
double number;
} mypair;
void zero_string(char *string, int n)
{
int i;
for(i=0; i<n; i++)
string[i] = '\0';
}
int row(FILE* f, struct mypair *p)
{
int num;
if(!feof(f))
{
if(fscanf(f,"%d %s %lf", &num, p->string, &p->number) == 3)
{
return 0;
}
}
else
{
return 1;
}
}
int main(int argc, char **argv)
{
int n = 5, status = 0, i = 0, j;
struct mypair array[5];
char file_in_name[255];
char file_out_name[255];
FILE *fin;
FILE *fout;
zero_string(file_in_name, 255);
zero_string(file_out_name, 255);
printf("Data file:\n> ");
scanf("%s", file_in_name);
printf("Out file:\n> ");
scanf("%s", file_out_name);
fin = fopen(file_in_name, "r");
fout = fopen(file_out_name, "w");
if( fin == NULL )
{
exit(-1);
}
if( fout == NULL )
{
exit(-1);
}
while(status != 1)
{
status = row(fin, &array[i]);
i ++;
fprintf(fout, "%s %lf\n", array[i].string, array[i].number);
if(i >= n)
break;
}
fclose(fin);
fclose(fout);
for(j=0; j<i; j++)
printf("%s %lf\n", array[i].string, array[i].number);
return 0;
}
I modified the code, now it works, thanks!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct mypair
{
char string[1024];
double number;
} mypair;
void zero_string(char *string, int n)
{
int i;
for(i=0; i<n; i++)
string[i] = '\0';
}
int row(FILE* f, struct mypair *p)
{
int num;
if(!feof(f))
{
if(fscanf(f,"%d %s %lf", &num, p->string, &p->number) == 3)
{
return 0;
}
}
else
{
return 1;
}
}
int main(int argc, char **argv)
{
int n = 5, status = 0, i = 0, j;
struct mypair array[5];
char file_in_name[255];
char file_out_name[255];
FILE *fin;
FILE *fout;
zero_string(file_in_name, 255);
zero_string(file_out_name, 255);
printf("Data file:\n> ");
scanf("%s", file_in_name);
printf("Out file:\n> ");
scanf("%s", file_out_name);
fin = fopen(file_in_name, "r");
fout = fopen(file_out_name, "w");
if( fin == NULL )
{
exit(-1);
}
if( fout == NULL )
{
exit(-1);
}
printf("\n");
while(status != 1)
{
status = row(fin, &array[i]);
if(i >= n)
break;
else
{
if(status != -1)
fprintf(fout, "%s %lf\n", array[i].string, array[i].number);
}
i ++;
}
fclose(fin);
fclose(fout);
for(j=0; j<i; j++)
printf("%s %lf\n", array[j].string, array[j].number);
return 0;
}
In your bottom loop, you want to index your array by j, not i.

Read .CSV file and store it in another file

Have made a program that reads a .csv file and stores the highest number in another file. The problem is that my program can't read comma separated numbers like 1,5,6,7,1,2. Here is the loop I need help to change
int i;
int max = 0;
int min = 0;
while (!feof(fp))
{
fscanf( fp, "%d", &i);
if (i < min)
min = i;
if (i > max)
max = i;
}
And this is what I print out:
fprintf(q,"%d",max);
printf("maximum value is %d \n", max);
fclose(q);
fclose(fp);
#include <stdio.h>
#include <limits.h>
int main(void){
FILE *fp = fopen("input.csv", "r");
FILE *q = fopen("max.txt" , "w");
int i;
int max = INT_MIN;
int min = INT_MAX;
while(1){
int state = fscanf(fp, "%d", &i);
if(state == 1){
if (i < min)
min = i;
if (i > max)
max = i;
} else if(state == EOF){
break;
} else {
char ch;
fscanf(fp, " %c", &ch);
if(ch != ','){
fprintf(stderr, "\nformat error\n");
break;
}
}
}
fprintf(q, "%d", max);
printf("maximum value is %d\n", max);
fclose(q);
fclose(fp);
return 0;
}

Ignoring # comments in the input for a C program

I'm trying to write a program which will read from text files and then output the minimum, maximum and average values. The trouble I am having is ignoring comments in the text files that begin with a hashtag. Here is my working code so far. Can anyone help?
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
char ch, filename[20];
FILE *lun;
int num, min, max, sum, count, first;
printf("Please enter the name of file to load:");
scanf ("%s", filename);
lun=fopen(filename, "r");
if ( lun != NULL)
{
for ( sum= count= first= 0; fscanf( lun, "%d", &num ) == 1; sum += num, ++count )
if ( !first ) { min= max= num; first= 1; }
else if ( num > max ) max= num;
else if ( num < min ) min= num;
fclose( lun );
printf( " Minimum value: %d\n Maximum value: %d\n Average value: %lf\n",
min, max, sum / (double) count );
}
else
printf( "Unable to read file.\n" );
return 0;
}
Read the data in lines (use fgets()).
If the line contains a #, terminate the string there by replacing the '#' with '\0'. Then scan the line for numbers.
See also How to use sscanf() in loops?
And don't forget to check that the file was opened.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char filename[20];
printf("Please enter the name of file to load: ");
if (scanf("%19s", filename) != 1)
{
fprintf(stderr, "Failed to read file name\n");
return 1;
}
FILE *lun = fopen(filename, "r");
if (lun == NULL)
{
fprintf(stderr, "Failed to open file %s for reading\n", filename);
return 1;
}
char line[4096];
int min = 0; // Avoid compilation warnings (may be used uninitialized)
int max = 0; // Ditto
int sum = 0;
int count = 0;
while (fgets(line, sizeof(line), lun) != NULL)
{
char *hash = strchr(line, '#');
if (hash != NULL)
*hash = '\0';
int pos;
int num;
int off = 0;
while (sscanf(line + off, "%d%n", &num, &pos) == 1)
{
if (count == 0)
min = max = num;
if (num > max)
max = num;
if (num < min)
min = num;
sum += num;
count++;
off += pos; // Skip through line
}
}
fclose(lun);
printf("Minimum value: %d\nMaximum value: %d\nAverage value: %lf\n",
min, max, sum / (double)count);
return 0;
}
If your compiler doesn't support C99 or later, you will have to move variable declarations to the start of a block (immediately after a {).
Handling doubles isn't really any harder:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char filename[20];
printf("Please enter the name of file to load: ");
if (scanf("%19s", filename) != 1)
{
fprintf(stderr, "Failed to read file name\n");
return 1;
}
FILE *lun = fopen(filename, "r");
if (lun == NULL)
{
fprintf(stderr, "Failed to open file %s for reading\n", filename);
return 1;
}
char line[4096];
double min = 0.0; // Avoids 'used when uninitialized' warnings
double max = 0.0; // Avoids 'used when uninitialized' warnings
double sum = 0;
int count = 0;
while (fgets(line, sizeof(line), lun) != NULL)
{
char *hash = strchr(line, '#');
if (hash != NULL)
*hash = '\0';
int pos;
double num;
int off = 0;
while (sscanf(line + off, "%lf%n", &num, &pos) == 1)
{
if (count == 0)
min = max = num;
if (num > max)
max = num;
if (num < min)
min = num;
sum += num;
count++;
off += pos; // Skip through line
}
}
fclose(lun);
printf("Minimum value: %f\nMaximum value: %f\nAverage value: %f\n",
min, max, sum / count);
return 0;
}

Resources