c program will not read user input - c

I am writing a client/server and after I am done getting information from the clients they close. Now I am trying to ask the user (server side) if they would like to continue but my program jumps straight to the end of the program.
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
main (void)
{
int to_server; // to read from client
int from_server; // to write to client
int finish; // lets me know that client is done
int i,j,k,m,l,p; // because C needs this defined as int
int numClient;// number of clients
char temp[14];
int page_size = 128;
int pages_left;
int max_frames=10;
int used_frames = 0;
int frameUpdate=0;
int freeframe[10] = {3,0,9,8,7,5,1,4,2,6};
int numpage=0;
int frames;
int client1[5];
int client2[5];
int client3[5];
int check;
int option;
int byte;
int search;
int getPage;
int getOffset;
int physical_Addr;
int offset;
int req[3];
int dummy = 0;
int again;
struct values{
char privFifo[14];
int memoryreq;
}cinput;
/* Create the fifos and open them */
if ((mkfifo("FIFO1",0666)<0 && errno != EEXIST))
{
perror("cant create FIFO1");
exit(-1);
}
if((to_server=open("FIFO1", O_RDONLY))<0){
printf("cant open fifo to write");
}
//get number of clients
printf("\nHow many clients?\n");
scanf("%d", &numClient);
for(j =1; j <= numClient; j++){
read(to_server, &cinput, sizeof(cinput));
printf("\n\nFifo_%d \nMemory request %d", cinput.privFifo, cinput.memoryreq);
req[j-1] = cinput.memoryreq;
if(cinput.memoryreq > 1280){
printf("\nERROR! Insufficient memory for request!");
exit(-1);
}
if((mkfifo(cinput.privFifo,0666)<0 && errno != EEXIST))
{
perror("cant create privFifo");
exit(-1);
}
if((from_server=open(cinput.privFifo, O_WRONLY)<0)){
printf("cant open fifo to write");
}
// find number of pages need for request
numpage = cinput.memoryreq/page_size;
if((numpage * page_size) < cinput.memoryreq){
numpage++;
}
sleep(1);
printf("\nPages needed %d", numpage);
write(from_server, &numpage, sizeof(numpage));
printf("\n******Main Memory******");
for(m = 0; m < numpage; m++){
if(j==1){
printf("\n* client: %d\tframe: %d", j, freeframe[m]);
frames = freeframe[m];
client1[m] = frames;
// write(from_server, &frames, sizeof(frames));
used_frames++;
}
else if (j == 2){
printf("\n* client: %d\tframe: %d", j, freeframe[dummy]);
frames = freeframe[dummy];
write(from_server, &frames, sizeof(frames));
used_frames++;
dummy++;
}
else if (j == 3){
printf("\n* client: %d\tframe: %d", j, freeframe[dummy]);
frames = freeframe[dummy];
write(from_server, &frames, sizeof(frames));
used_frames++;
dummy++;
}
}
dummy = used_frames;
used_frames = max_frames - used_frames;
if(j==1){
pages_left = max_frames - numpage;
}
else {
pages_left = dummy;
}
printf("\n Frames available:");
for(l = pages_left; l!= 0; l--){
check = max_frames - l;
printf(" %d", freeframe[check]);
}
pages_left = check;
close(from_server);
unlink(cinput.privFifo);
}
printf("\nDONE!!!");
close(to_server);
unlink("FIFO1");
}
Here is my problem area (sorry for my messy code ):
printf("press 1 to find Physical address of a byte?");
scanf("%d\n", &again);
while(again == 1){
printf("\nWhich client are we accessing? ");
scanf("%d", &option);
printf("\nWhat byte would you like to find? ");
scanf("%d", &byte);
if(option == 1){
for(p = 0; p < sizeof(client1); p++){
search = p*page_size;
if(search <= byte)
getPage= client1[p];
}
getOffset=byte%page_size;
physical_Addr = (getPage * page_size) + offset;
printf("Physical Address is %d", physical_Addr);
}
else if(option == 2){
for(p = 0; p < sizeof(client1); p++){
search = p*page_size;
if(search <= byte)
getPage= client1[p];
}
getOffset=byte%page_size;
physical_Addr = (getPage * page_size) + offset;
printf("Physical Address is %d", physical_Addr);
}
else if(option == 3){
for(p = 0; p < sizeof(client1); p++){
search = p*page_size;
if(search <= byte)
getPage= client1[p];
}
getOffset=byte%page_size;
physical_Addr = (getPage * page_size) + offset;
printf("Physical Address is %d", physical_Addr);
}
else{
printf("ERROR!");
}
printf("Press 1 to choose another client.");
scanf("%d", &again);
}

Related

Why do I get different results depending on how many child processes I use?

I am working on a simple C program that recursively creates children and uses them to sum all the numbers in a file, depending on user input. There are three predetermined file sizes that the user can chose from, as well as three set amounts of children that can be generated. In theory, there could be any number of children or any size file, but for the sake of simplicity there are only 3 here.
The problem I'm running into is, no matter which file I use, the only time the sum is correct is when the program uses only 1 child. With other amounts of children, such as 4, the number is close, but not quite right. Can someone offer me any insight as to what is causing this issue?
Here is the section of code I think is problematic:
// C program to demonstrate use of fork() with pipe()
// By: Maxwell Wendlandt
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#include <sys/wait.h>
#include <unistd.h>
int main()
{
FILE *file;
int numForks;
// initialize pipes for up to 4 children
int fd[4][2];
// initialize up to 4 processes
pid_t pid[4];
int total = 0;
int finalResult = 0;
char fileName[10] = "";
int fileNum;
int numLines;
// ask which file to scan
printf("Enter file number 1 (1000 nums), 2 (10000 nums) or 3 (100000 nums):\n");
scanf("%i", &fileNum);
// chose the file
switch(fileNum)
{
case 1 :
printf("File 1 selected.\n");
strcpy(fileName, "file1.dat");
numLines = 1000;
break;
case 2 :
printf("File 2 selected.\n");
strcpy(fileName, "file2.dat");
numLines = 10000;
break;
case 3 :
printf("File 3 selected.\n");
strcpy(fileName, "file3.dat");
numLines = 100000;
break;
default :
printf("Enter a valid file number next time.\n");
return 0;
}
// ask how many children (forks)
printf("Do you want 1, 2 or 4 child processes?\n");
scanf("%i", &numForks);
for (int i = 0; i < numForks + 1; i++)
{
if (pipe(fd[i]) == -1)
{
printf("Error with creating pipe.\n");
return 1;
}
}
for(int i = 0; i < numForks; i++)
{
pid[i] = fork();
if(pid[i] == -1)
{
printf("Error creating child.\n");
return 1;
}
if(pid[i] == 0)
{
// children
int sum = 0, num = 0;
int start, end;
file = fopen(fileName, "r");
start = i * (numLines / numForks);
printf("start: %i\n", start);
end = ((i + 1) * (numLines / numForks));
printf("end: %i\n", end);
fseek(file, (start * 4), SEEK_SET);
for(int i = start; i < end; i++)
{
fscanf(file, "%d", &num);
printf("num on line %d is: %d\n", i + 1, num);
sum += num;
}
printf("sum in child: %d\n", sum);
write(fd[i][1], &sum, sizeof(sum));
close(fd[i][1]);
return 0;
}
}
// parent
for(int i = 0; i < numForks; i++)
{
read(fd[i][0], &total, sizeof(total));
close(fd[i][0]);
finalResult += total;
}
printf("The grand total: %i\n", finalResult);
for(int i = 0; i < numForks; i++)
{
wait(NULL);
}
return 0;
}
Thanks in advance!
each line of the file has one 3 digit number on it. So a 1000 number file has 1000 lines.
This means each line consists of four five bytes - the three digits, the carriage return, and the newline character. e.g., 123\r\n. The off-by-two error here
fseek(file, (start * 3), SEEK_SET);
will cause each seek to drift, and each child will read from an earlier position than they should. If each line is five bytes, this should be start * 5.
Aside: I would hazard a guess the numbers in your files are padded with zeroes (see the generation example below).
If so, the fscanf specifier %i may not be desirable, as it acts as strtol with a base of 0, meaning the numbers base is determined by its first characters.
This may lead to confusing results when zero padded numbers are parsed as octal. For example:
004 - octal, value 4.
040 - octal, value 32.
400 - decimal, value 400.
009 - octal, invalid value (0).
011 - octal, value 9.
%d will parse the inputs as base-10 numbers.
This has a few problems.
printf("Do you want 1, 2 or 4 child processes?\n");
scanf("%i", &numForks);
for (int i = 0; i < numForks + 1; i++) {
if (pipe(fd[i]) == -1)
/* ... */
i < numForks + 1 is an off-by-one error. The user can also enter an arbitrary number.This will invoke Undefined Behaviour if fd is accessed via an out-of-bounds index.
In general, you should be checking the return values of more functions, such as scanf, fscanf, fseek, write, and read, to ensure you are working with valid data.
Prefer perror and fprintf(stderr, ...) to print useful error messages to the correct stream.
A very cursory refactoring:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <wait.h>
int main(void)
{
int numForks;
// initialize pipes for up to 4 children
int fd[4][2];
// initialize up to 4 processes
pid_t pid[4];
int total = 0;
int finalResult = 0;
char fileName[10] = "";
int fileNum;
int numLines;
printf("Enter file number 1 (1000 nums), 2 (10000 nums) or 3 (100000 nums):\n");
if (1 != scanf("%d", &fileNum)) {
fprintf(stderr, "Invalid number of files.\n");
return 1;
}
switch (fileNum) {
case 1:
printf("File 1 selected.\n");
strcpy(fileName, "file1.dat");
numLines = 1000;
break;
case 2:
printf("File 2 selected.\n");
strcpy(fileName, "file2.dat");
numLines = 10000;
break;
case 3:
printf("File 3 selected.\n");
strcpy(fileName, "file3.dat");
numLines = 100000;
break;
default:
printf("Enter a valid file number next time.\n");
return 0;
}
printf("Do you want 1, 2 or 4 child processes?\n");
if (1 != scanf("%d", &numForks) || 1 > numForks || numForks > 4 || numForks == 3) {
fprintf(stderr, "Invalid number of child processes.\n");
return 1;
}
for (int i = 0; i < numForks; i++) {
if (pipe(fd[i]) == -1) {
perror("pipe");
return 1;
}
}
for (int i = 0; i < numForks; i++) {
pid[i] = fork();
if (pid[i] == -1) {
perror("fork");
return 1;
}
// children
if (pid[i] == 0) {
int sum = 0, num = 0;
int start, end;
FILE *file = fopen(fileName, "r");
if (!file) {
fprintf(stderr, "Child %d failed to open ", i + 1);
perror(fileName);
return 1;
}
start = i * (numLines / numForks);
end = ((i + 1) * (numLines / numForks));
printf("start: %d\nend: %d\n", start, end);
if (-1 == fseek(file, (start * 4), SEEK_SET)) {
perror("fseek");
return 1;
}
for (int i = start; i < end; i++)
if (1 == fscanf(file, "%d", &num))
sum += num;
printf("sum in child: %d\n", sum);
write(fd[i][1], &sum, sizeof sum);
close(fd[i][1]);
return 0;
}
}
// parent
for (int i = 0; i < numForks; i++) {
if (sizeof total == read(fd[i][0], &total, sizeof total))
finalResult += total;
close(fd[i][0]);
}
for (int i = 0; i < numForks; i++)
wait(NULL);
printf("The grand total: %d\n", finalResult);
}
The code used to generate files to test with (./gen 1000 > file1.dat):
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char **argv)
{
int i = 0;
if (argc > 1)
i = atoi(argv[1]);
srand((unsigned) time(NULL));
while (i-- > 0)
printf("%03d\n", rand() % 1000);
}
And a sanity checker (./sanity-check < file1.dat):
#include <stdio.h>
int main(void)
{
int sum = 0, num;
while (1 == scanf("%d", &num))
sum += num;
printf("%d\n", sum);
}

How to detect duplicate string using strcmp()

#include<stdio.h>
#include<stdio.h>
#include<string.h>
struct stud
{
char nam[20];
int num;
char letter[5];
};
int main()
{
struct stud s[5];
int i, j;
for(i = 0; i < 5; i++){
printf("Enter the name of student #%d: ", i+1);
scanf("%s", s[i].nam);
printf("Enter the number grade of student #%d: ", i+1);
scanf("%d", &s[i].num);
}
for (j = 0; j < i; j++) {
if (strcmp(s[i].nam, s[j].nam) == 0)
printf("Error. Duplicate name detected.");
}
for(i = 0; i < 5; i++){
if(s[i].num >= 90 )
strcpy(s[i].letter, "A");
else if(s[i].num >= 80)
strcpy(s[i].letter, "B");
else if(s[i].num >= 70)
strcpy(s[i].letter, "C");
else if(s[i].num >= 60)
strcpy(s[i].letter, "D");
else
strcpy(s[i].letter, "F");
}
for(i = 0; i < 5; i++)
printf("\n%s has a %s ", s[i].nam, s[i].letter);
return 0;
}
This program has the user enter 5 names and 5 numeric grades, which will then result in the output of their respective letter grades for that student. I'm trying to make it so if the user enters a duplicate name, and message will print saying they can't do that. My attempt in trying to do this is as follows:
for (j = 0; j < i; j++) {
if (strcmp(s[i].nam, s[j].nam) == 0)
printf("Error. Duplicate name detected.");
}
Where I believe that s[j] is the previous string, and compare to see if it equals 0(duplicate) and prints a message. This obviously doesn't work however so I would like to know how to fix this so it can correctly detect duplicate names. Thank you.
Also I have posted this question before but the person that provided an explanation deleted their response before I could provide further questions and ask for clarification. So I am posting this again with an attempt in seeking further aid in what I did wrong in my code.
At the start of the detection loop, i is already 5, so using s[i] is undefined behavior
In your detection loop, i is invariant. you are just comparing a name against the last one [except for the UB, of course].
You need two loops to compare all names against one another.
Also, using 5 everywhere is a "magic number". Better to use a #define (e.g. SMAX)
In the code below, I use cpp conditionals to denote old vs. new code:
#if 0
// old code
#else
// new code
#endif
#if 1
// new code
#endif
Here is the corrected code. It is annotated with the bugs and fixes:
#include <stdio.h>
#include <stdio.h>
#include <string.h>
struct stud {
char nam[20];
int num;
char letter[5];
};
#define SMAX 5 // maximum number of students
int
main()
{
struct stud s[SMAX];
int i, j;
for (i = 0; i < SMAX; i++) {
printf("Enter the name of student #%d: ", i + 1);
scanf("%s", s[i].nam);
printf("Enter the number grade of student #%d: ", i + 1);
scanf("%d", &s[i].num);
}
// NOTE/BUG: i is already SMAX, so using s[i] is UB (undefined behavior)
// NOTE/BUG: i never changes
#if 0
for (j = 0; j < i; j++) {
if (strcmp(s[i].nam, s[j].nam) == 0)
printf("Error. Duplicate name detected.");
}
#else
for (i = 0; i < (SMAX - 1); i++) {
for (j = i + 1; j < SMAX; j++) {
if (strcmp(s[i].nam, s[j].nam) == 0)
printf("Error. Duplicate name detected -- %s\n",s[j].nam);
}
}
#endif
for (i = 0; i < SMAX; i++) {
if (s[i].num >= 90)
strcpy(s[i].letter, "A");
else if (s[i].num >= 80)
strcpy(s[i].letter, "B");
else if (s[i].num >= 70)
strcpy(s[i].letter, "C");
else if (s[i].num >= 60)
strcpy(s[i].letter, "D");
else
strcpy(s[i].letter, "F");
}
// NOTE/BUG: newline should go at the end of the printf to prevent a hanging
// last line
#if 0
for (i = 0; i < SMAX; i++)
printf("\n%s has a %s ", s[i].nam, s[i].letter);
#else
for (i = 0; i < SMAX; i++)
printf("%s has a %s\n", s[i].nam, s[i].letter);
#endif
return 0;
}
UPDATE:
Thanks for the tip! On a side note, how would I make it so while the user is entering the duplicate names, the error message appears and the program ends right there.For example: Enter the name of student 1: dan Enter grade: 87 Enter the name of student 2: dan Enter the grade: 78 Error. No duplicate names allowed. And then the program ends there. –
User234567
Easy enough. I put the duplication detection code into functions.
But, I've added a few more enhancements so this may help you with your learning ;-)
I added reprompting the user if they enter a duplicate.
I hate scanf ;-) I reworked the prompting code by putting it into two functions. It will work better if input is a file. This is useful during testing
I changed the conversion from grade number to grade letter to use a table.
Anyway, here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
struct stud {
char nam[20];
int num;
char letter[5];
};
struct letter {
int num;
const char *letter;
};
#define LET(_num,_let) \
{ .num = _num, .letter = _let }
struct letter letters[] = {
LET(90,"A"),
LET(80,"B"),
LET(70,"C"),
LET(60,"D"),
LET(0,"F"),
LET(0,NULL)
};
#define SMAX 5 // maximum number of students
// chkall -- check entire array for duplicates
int
chkall(const struct stud *s,int smax)
{
int i;
int j;
int dup = 0;
for (i = 0; i < (smax - 1); i++) {
for (j = i + 1; j < smax; j++) {
if (strcmp(s[i].nam, s[j].nam) == 0) {
printf("Error. Duplicate name detected -- %s\n",s[j].nam);
dup += 1;
}
}
}
return dup;
}
// chkone -- check a given entry for duplicate (as they are added)
int
chkone(const struct stud *s,int i)
{
int j;
int dup = 0;
for (j = 0; j < i; j++) {
if (strcmp(s[i].nam, s[j].nam) == 0) {
printf("Error. Duplicate name detected -- %s\n",s[j].nam);
dup += 1;
}
}
return dup;
}
// prompt_string -- prompt user for a string
char *
prompt_string(const char *what,int i,char *buf,size_t siz)
{
static int tty = -1;
// decide if our input is tty or file
if (tty < 0) {
struct winsize ws;
tty = ioctl(0,TIOCGWINSZ,&ws);
tty = (tty >= 0);
}
printf("Enter the %s of student #%d: ", what, i + 1);
fflush(stdout);
char *cp = fgets(buf,siz,stdin);
do {
// handle EOF
if (cp == NULL)
break;
buf[strcspn(buf,"\n")] = 0;
// echo the data if input is _not_ a tty
if (! tty)
printf("%s\n",buf);
} while (0);
return cp;
}
// prompt_number -- prompt user for a number
long long
prompt_number(const char *what,int i)
{
char *cp;
char buf[100];
long long val;
while (1) {
cp = prompt_string(what,i,buf,sizeof(buf));
// handle EOF
if (cp == NULL) {
val = -1;
break;
}
// decode the number
val = strtoll(buf,&cp,10);
if (*cp == 0)
break;
printf("invalid number syntax -- '%s'\n",cp);
}
return val;
}
int
main(void)
{
struct stud s[SMAX];
int i;
for (i = 0; i < SMAX; i++) {
while (1) {
prompt_string("name",i,s[i].nam,sizeof(s[i].nam));
if (! chkone(s,i))
break;
}
s[i].num = prompt_number("number grade",i);
}
// recheck all entries
// this will _never_ report a duplicate because of the chkone above
chkall(s,SMAX);
for (i = 0; i < SMAX; i++) {
for (struct letter *let = letters; let->letter != NULL; ++let) {
if (s[i].num >= let->num) {
strcpy(s[i].letter,let->letter);
break;
}
}
}
for (i = 0; i < SMAX; i++)
printf("%s has a %s\n", s[i].nam, s[i].letter);
return 0;
}

library of books , struct and malloc

I'm trying to do a library
the books is the objectives
the user can enter a book and then I check if the book is my book menu:
if the book in the menu:
if the book is available so I print a message and return 1
if it doesn't available so I change the book to available and print that I added the book
if the book is not in the menu :
I do malloc and then check I the malloc succeed
if the malloc succeed :I do strcp to the object
if the malloc didn't succeed : I do free to the object and the print a message and return 1
The problem: when the user enter the book for the second time it shouldn't add the book as a new book! it should check if the book is available or not and then return a message but my code is not doing this and I don't know where is bug!
#define _CRT_SECURE_NO_WARNINGS
#define BOOK_NUM 4
#define NAME_LENGTH 200
#define AVAILABLE 10
#define NOT_AVAILABLE 20
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct book
{
char name[NAME_LENGTH]; char author[NAME_LENGTH]; int available; int times_borrowed;
}Book;
int main()
{
Book *books[BOOK_NUM] = { 0 };
char book_name[NAME_LENGTH];
char author_name[NAME_LENGTH];
int opreation = 0;
int i;
int j = 0;
int m = 0;
char tav;
scanf("%d", &opreation);
if (opreation == 1) {
printf("please enter the name:");
scanf("%c", &tav);
do {// kelet of the book_name
scanf("%c", &tav);
if (tav == '\n')
break;
book_name[m] = tav;
m++;
} while (m < NAME_LENGTH);
book_name[m] = '\0';
for (i = 0; i < BOOK_NUM && *(books+i)!=NULL ; i++) {
if (strcmp(*books[i]->name, book_name) == 0)
{
if (books[i]->available = NOT_AVAILABLE)
{
books[i]->available = AVAILABLE;
printf("This book is already in the library");
return 0;
}
else
{
printf("There is no enough space in the library");
return 0;
}
}
}
//befot bs eza 3ml sreka ghad 3la kolshe w ma tghyr eshe
for (j; j < BOOK_NUM; j++) {
if (books[j] == NULL)
{
books[j] = (Book*)malloc(sizeof(Book));
if (books[j] != NULL)
{
strcpy(books[j]->name, book_name);
printf("Please enter author name:");
m = 0;
do {// kelet of the book_name
scanf("%c", &tav);
if (tav == '\n')
break;
author_name[m] = tav;
m++;
} while (m < NAME_LENGTH);
author_name[m] = '\0';
strcpy(books[j]->author, author_name);
books[j]->available = AVAILABLE;
books[j]->times_borrowed = 0;
printf("The book %s was successfully added!", book_name);
return 0;
}
else
{
for (int k = 0; k < BOOK_NUM && books[k]!=NULL; k++) {
free(books[k]);
}
printf("NO MEMORY");
return 1;
}
}
}
}
}
MAYBE now is better:
#define _CRT_SECURE_NO_WARNINGS
#define BOOK_NUM 4
#define NAME_LENGTH 200
#define AVAILABLE 10
#define NOT_AVAILABLE 20
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct book
{
char name[NAME_LENGTH]; char author[NAME_LENGTH]; int available; int times_borrowed;
}Book;
int main()
{
Book *books[BOOK_NUM] = { 0 };
char book_name[NAME_LENGTH];
char author_name[NAME_LENGTH];
int opreation = 0;
int i;
int j = 0;
int m = 0;
char tav;
scanf("%d", &opreation);
if (opreation == 1) {
printf("please enter the name:");
scanf("%c", &tav);
do {// kelet of the book_name
scanf("%c", &tav);
if (tav == '\n')
break;
book_name[m] = tav;
m++;
} while (m < NAME_LENGTH);
book_name[m] = '\0';
for (i = 0; i < BOOK_NUM && *(books+i)!=NULL ; i++) {
if (strcmp(books[i]->name, book_name) == 0)
{
if (books[i]->available == NOT_AVAILABLE)
{
books[i]->available = AVAILABLE;
printf("This book is already in the library");
return 0;
}
else
{
printf("There is no enough space in the library");
return 0;
}
}
}
//befot bs eza 3ml sreka ghad 3la kolshe w ma tghyr eshe
if (books[j] == NULL)
{
books[j] = (Book*)malloc(sizeof(Book));
if (books[j] != NULL)
{
strcpy(books[j]->name, book_name);
printf("Please enter author name:");
m = 0;
do {// kelet of the book_name
scanf("%c", &tav);
if (tav == '\n')
break;
author_name[m] = tav;
m++;
} while (m < NAME_LENGTH);
author_name[m] = '\0';
strcpy(books[j]->author, author_name);
books[j]->available = AVAILABLE;
books[j]->times_borrowed = 0;
printf("The book %s was successfully added!", book_name);
return 0;
}
else
{
for (int k = 0; k < BOOK_NUM && books[k]!=NULL; k++) {
free(books[k]);
}
printf("NO MEMORY");
return 1;
}
}
}
}
by the way, you should listen to compiler warnings.

C fork and pipe add numbers from a file

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

Replacing elements in an array

I have a problem thats giving me a huge ache.
This piece of code purpose is to fill up an array with integer values and at the same time defend against strings and etc....but it doesn't defend against duplicates, but tried I got to far as replacing the number with a new number for example
Enter 6 integers
1, 2, 2, 3, 4, 5
my code will let me replace that 2 at position 1 with another number. What I want it to do is not to repeat the same number again, for example please replace 2 at position 1. I dont want the user to enter 2 again... and I want to make it to double check the work the array if any repeating numbers exists thank you.
system("clear");
printf("\nEntering Winning Tickets....\n");
nanosleep((struct timespec[]){{1, 0}}, NULL);
system("clear");
char userInput[256];
char c;
int duplicationArray[6] = {-1, -1, -1, -1, -1, -1};
for (i = 0; i < 6; i++)
{
printf("\nPlease enter the %d winning ticket number!(#'s must be between 1-49): ", i+1);
fgets(userInput, 256, stdin);
if ((sscanf(userInput, "%d %c", &winningNumbers[i], &c) != 1 || (winningNumbers[i] <= 0) || winningNumbers[i] >= 50))
{
printf("\nInvalid Input.\n") ;
nanosleep((struct timespec[]){{0, 350000000}}, NULL);
system("clear");
i = i - 1;
}
}
for (i = 0; i < 6 - 1; ++i)
{
min = i;
for (j = i+1; j < 6; ++j)
{
if (winningNumbers[j] < winningNumbers[min])
min = j;
}
temp = winningNumbers[i];
winningNumbers[i] = winningNumbers[min];
winningNumbers[min] = temp;
}
for (i = 0; i < 6; i++)
{
if (winningNumbers[i] == winningNumbers[i+1])
{
duplicationArray[i] = i;
duplicationCounter++;
}
else
{
duplicationCounter--;
}
}
if (duplicationCounter > -6)
{
for (i = 0; i < 6; i++)
{
int j, min, temp;
min = i;
for (j = i+1; j < 6; ++j)
{
if (duplicationArray[j] > duplicationArray[min])
min = j;
}
temp = duplicationArray[i];
duplicationArray[i] = duplicationArray[min];
duplicationArray[min] = temp;
}
for (i = 0; i < 6; i++)
{
if (duplicationArray[i] == -1)
{
zeroCounter++;
}
}
int resize = (6 - zeroCounter)+1;
for (i = 0; i <= resize; i++)
{
if (duplicationArray[i] == -1)
{
i++;
}
else if (duplicationArray[i] != -1)
{
system("clear");
printf("\nDuplicated numbers has been dected in your array. ");
printf("\nPlease replace the number %d at postion %d with another number: ", winningNumbers[duplicationArray[i]], duplicationArray[i]);
fgets(userInput, 256, stdin);
if ((sscanf(userInput, "%d %c", &winningNumbers[duplicationArray[i]], &c) != 1 || (winningNumbers[i] <= 0) || winningNumbers[i] >= 50))
{
printf("\nInvalid Input.\n") ;
nanosleep((struct timespec[]){{0, 350000000}}, NULL);
system("clear");
i = i - 1;
}
}
}
duplicationCounter = 0;
for (i = 0; i < 6; i++)
{
if (winningNumbers[i] == winningNumbers[i+1])
{
duplicationArray[i] = i;
duplicationCounter++;
}
else
{
duplicationCounter--;
}
}
printf("%d, ", duplicationCounter);
}
#include <stdio.h>
#include <stdint.h>
#define DATA_SIZE 6
int main(void){
char userInput[256];
int inputNum, winningNumbers[DATA_SIZE];
uint64_t table = 0;
int i=0;
while(i<DATA_SIZE){
printf("\nPlease enter the %d winning ticket number!(#'s must be between 1-49): ", i+1);
fgets(userInput, sizeof(userInput), stdin);
if(sscanf(userInput, "%d", &inputNum) != 1 || inputNum <= 0 || inputNum >= 50)
continue;
uint64_t bit = 1 << inputNum;
if(table & bit)
continue;
table |= bit;
winningNumbers[i++] = inputNum;
}
for(i=0;i<DATA_SIZE;++i)
printf("%d ", winningNumbers[i]);
printf("\n");
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#define DATA_SIZE 6
int inputNumberWithRangeCheck(const char *msg, const char *errMsg, int rangeStart, int rangeEnd){
char inputLine[256];
int n;
for(;;){
printf("%s", msg);
fgets(inputLine, sizeof(inputLine), stdin);
if(sscanf(inputLine, "%d", &n) != 1 || n < rangeStart || n > rangeEnd)
fprintf(stderr, "%s", errMsg);
else
return n;
}
}
int inputNumber(void){
return inputNumberWithRangeCheck(
"\nPlease enter the winning ticket number!(#'s must be between 1-49): ",
"Invalid Input.\n",
1,49);
}
int *inputArray(int *array, size_t size){
int i;
for(i=0;i<size;++i){
printf("\nInput for No.%d\n", i+1);
array[i] = inputNumber();
}
return array;
}
int **duplicateCheck(int *array, size_t size){
int **check, count;
int i, j;
check = malloc(size*sizeof(int*));
if(!check){
perror("memory allocate\n");
exit(-1);
}
//There is no need to sort the case of a small amount of data
//(Cost of this loop because about bubble sort)
for(count=i=0;i<size -1;++i){
for(j=i+1;j<size;++j){
if(array[i] == array[j]){
check[count++] = &array[i];
break;
}
}
}
check[count] = NULL;
if(count)
return check;
else {
free(check);
return NULL;
}
}
int main(void){
int winningNumbers[DATA_SIZE];
int **duplication;
int i, j;
inputArray(winningNumbers, DATA_SIZE);
while(NULL!=(duplication = duplicateCheck(winningNumbers, DATA_SIZE))){
for(i=0;i<DATA_SIZE;++i){
if(duplication[i]){
printf("\nyour input numbers : ");
for(j=0;j<DATA_SIZE;++j)
printf("%d ", winningNumbers[j]);
fprintf(stderr, "\nThere is duplicate. Please re-enter.\n");
*duplication[i] = inputNumber();
} else
break;
}
free(duplication);
}
for(i=0;i<DATA_SIZE;++i)
printf("%d ", winningNumbers[i]);
printf("\n");
return 0;
}

Resources