WC in C with different child processes [duplicate] - c

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Here is the final result i got so far for a simulator of wc linux command. I have to accomplish an output like this
This is child process 0, the number of lines is x
This is child process 1, the number of words is y
This is child process 2, the number of lines is z
The code i wrote is this one:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
char* concat(char *s1, char *s2)
{
char *result = malloc(strlen(s1)+strlen(s2)+1);
strcpy(result, s1);
strcat(result, s2);
return result;
}
int countLines(FILE *f){
int count = 0;
char ch;
while ((ch = fgetc(f)) != EOF){
if (ch == '\n')
count++;
}
return count;
}
int countWords(FILE *f){
int countW = 0;
char ch;
while ((ch = fgetc(f)) != EOF){
if (ch == ' ')
countW++;
}
return countW;
}
int countChars(FILE *f){
int chars = 0;
char ch;
while ((ch = fgetc(f)) != EOF){
chars++;
}
return chars;
}
int main(int argc, char** argv)
{
int lineCount = 0;
int wordCount = 0;
int charCount = 0;
int n = 3;
int i,status;
int pids[3];
char *theprogram = argv[0];
char *thefile = argv[1];
if ( argc !=2 )
{
printf( "Help: %s filename\n", argv[0]);
}
else{
FILE *file = fopen( argv[1], "r");
if(file == 0){
char *sub = concat(theprogram, ": ");
char *middle = concat(sub, thefile);
perror(middle);
}
else{
for (i = 0; i < n; i++) {
pids[i] = fork();
if ( pids[i] < 0) {
perror("fork");
exit(-1);
} else if (pids[i] == 0) {
if (i==0){
lineCount += countLines(file);
printf("This is child proccess %d, and the number of lines is %d\n", i+1, lineCount);
exit(0);
}
else if (i==1){
wordCount += countWords(file);
printf("This is child proccess %d, and the number of words is %d\n", i+1, wordCount);
exit(0);
}
else {
charCount += countChars(file);
printf("This is child proccess %d, and the number of characters is %d\n", i+1, charCount);
exit(0);
}
}
}
return 0;
}
}
}
This is the actual output i am getting:
% ./a.out mywc.c
This is child proccess 2, and the number of words is 0
This is child proccess 1, and the number of lines is 64
This is child proccess 3, and the number of characters is 0
This is child proccess 3, and the number of characters is 0
This is child proccess 2, and the number of words is 0
This is child proccess 3, and the number of characters is 0
This is child proccess 3, and the number of characters is 0
What am I doing Wrong here? I am very new to C programming so not sure what i am missing.
Thanks.
EDIT
Exited the exit codes but can not get the word count and the character count right now.

The right code for my problem is here:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
char* concat(char *s1, char *s2)
{
char *result = malloc(strlen(s1)+strlen(s2)+1);
strcpy(result, s1);
strcat(result, s2);
return result;
}
int countLines(char *f){
FILE *file = fopen(f, "r");
int count = 0;
char ch;
while ((ch = fgetc(file)) != EOF){
if (ch == '\n')
count++;
}
return count;
}
int countWords(char *f){
char buffer[1];
FILE *file = fopen(f, "r");
int countW = 0;
enum states { WSP, WRD };
int state = WSP;
char last = ' ';
while (read(fileno(file),buffer,1) == 1 )
{
if ( buffer[0]== ' ' || buffer[0] == '\t' || buffer[0]=='\n' )
{
state = WSP;
}
else
{
if ( state == WSP )
{
countW++;
}
state = WRD;
}
last = buffer[0];
}
return countW;
}
int countChars(char *f){
FILE *file = fopen(f, "r");
int chars = 0;
char ch;
while ((ch = fgetc(file))){
if (ch == EOF) break;
chars++;
}
return chars;
}
int main(int argc, char** argv)
{
int lineCount = 0;
int wordCount = 0;
int charCount = 0;
int n = 3;
int i,status;
int pids[3];
char *theprogram = argv[0];
char *thefile = argv[1];
if ( argc !=2 )
{
printf( "Help: %s filename\n", argv[0]);
}
else{
FILE *file = fopen( argv[1], "r");
if(file == 0){
char *sub = concat(theprogram, ": ");
char *middle = concat(sub, thefile);
perror(middle);
}
else{
for (i = 0; i < n; i++) {
pids[i] = fork();
if ( pids[i] < 0) {
perror("fork");
exit(-1);
} else if (pids[i] == 0) {
if (i==0){
lineCount = countLines(argv[1]);
printf("This is child proccess %d, and the number of lines is %d\n", i+1, lineCount);
exit(0);
}
else if (i==1){
wordCount = countWords(argv[1]);
printf("This is child proccess %d, and the number of words is %d\n", i+1, wordCount);
exit(0);
}
else {
charCount += countChars(argv[1]);
printf("This is child proccess %d, and the number of characters is %d\n", i+1, charCount);
exit(0);
}
}
}
return 0;
}
}
}

Related

C forever Loop after return from a sub function

I have a function parse, which I am calling in the main,
it reads the 2D array expense row one by one, if the total columns in any Row of expense are not equal to 5, it returns 1 and prints an error. but it's stuck in a forever loop. Since I am very new to c, I am unable to figure it out.
int parse (char* exp, char* exp_str) {
char d[] = " ";
char *cpyexp;
strcpy(cpyexp, exp);
printf("cpyexp %s \n", cpyexp);
printf("strlen(cpyexp) %lu \n", strlen(cpyexp));
if(strlen(cpyexp) != 9)
{
fprintf(stderr, "error1: parse() failed\n");
return 1;
}
return 0;
}
int main(int argc, char** argv) {
char* file = NULL ;
char expenses [ROWS][COLS] = {{"CAR,14,10"},{"INS,10,12"}} ;
char expenses_str [ROWS][17] ;
int i = 0;
while(expenses[i][0] != '\0' ){
if(parse (expenses[i], expenses_str[i]) == 1) {
fprintf(stderr, "error3: parse_instruction() failed\n");
return 1;
}
if (expenses[i]== NULL || expenses[i] == '\0'){
break;
}
i++;
}
}
int parse (char* exp, char* exp_str) {
char d[] = " ";
char *cpyexp =malloc(strlen(exp)+1)* sizeof(char)) \\this is initialized as NULL and hats why getting an error
strcpy(cpyexp, exp);
printf("cpyexp %s \n", cpyexp);
printf("strlen(cpyexp) %lu \n", strlen(cpyexp));
if(strlen(cpyexp) != 9)
{
fprintf(stderr, "error1: parse() failed\n");
return 1;
}
return 0;
}
int main(int argc, char** argv) {
char* file = NULL ;
char expenses [ROWS][COLS] = {{"CAR,14,10"},{"INS,10,12"}} ;
char expenses_str [ROWS][17] ;
int i = 0;
while(expenses[i][0] != '\0' ){
if(parse (expenses[i], expenses_str[i]) == 1) {
fprintf(stderr, "error3: parse_instruction() failed\n");
return 1;
}
if (expenses[i]== NULL || expenses[i] == '\0'){
break;
}
i++;
}
}

How can i print the contents of stdin or file without adjacent empty lines?

I want to replicate the -s option of the cat linux command. It basically removes every empty line adjacent to another making the output equally spaced. How can i approach this without making a temporary file?
Here's my cat command:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <getopt.h>
#define BUF_SIZE 1024
void formattedLineout(int *index, char buffer[]){
printf (" %d\t%s", *index, buffer);
(*index)++;
}
void bprint(int *index, char buffer[]){
if (strcmp(buffer,"\n") == 0){
printf (" %s", buffer);
}
else {
formattedLineout(index, buffer);
}
}
void outputLine(int *index, char buffer[], int bflag, int nflag){
if (nflag){
formattedLineout(index, buffer);
}
else if (bflag){
bprint(index, buffer);
}
else{
printf("%s", buffer);
}
}
int readStdin(int index, int bflag, int nflag){
char buffer[BUF_SIZE];
while(fgets(buffer, BUF_SIZE, stdin)){ //reads from the standard input and prints the input
outputLine(&index, buffer, bflag, nflag);
}
return index; //returns the incremented index to perpetuate its use
}
int readFile(char* filename, FILE* fp, int index, int bflag, int nflag){
char s[BUF_SIZE];
if (fp==NULL){ //in case the file doesn't exist
printf("%s: No such file or directory\n", filename);
exit(1);
}
while ((fgets(s, BUF_SIZE, fp))){ //printing loop
outputLine(&index, s, bflag, nflag);
}
return index;
}
void readArgs(int argc, char* argv[], int bflag, int nflag){
FILE* fp;
int index = 1; //line index. to be used in case -b or -n is passed as an argument
if (bflag == 1 && nflag == 1){ //if -b and -n are passed as argument, b overrides n
nflag = 0;
}
for (int i=optind; i<argc; i++){
if (*argv[i] == '-'){ //in case of '-' in argv[i], reads from stdin and prints
index = readStdin(index, bflag, nflag);
clearerr(stdin);
}
else { //prints the contents of the file in *argv[i]
fp = fopen(argv[i], "r");
index = readFile(argv[i], fp, index, bflag, nflag);
fclose(fp);
}
}
}
int main(int argc, char* argv[]){
int option; //option passed as argument
int bflag = 0; //-b option deactivated by default
int nflag = 0; //-n option deactivated by default
opterr = 0; //deactivates getopt's default error messages
//checks if there are options passed as argument and updates their flags
while ((option = getopt(argc, argv, "bn")) != -1){
switch (option){
case 'b':
bflag = 1;
break;
case 'n':
nflag = 1;
break;
case '?': //in case there was some problem
exit(1);
}
}
if (argc<2 || optind == argc){ //if there are no arguments or if there are only options
readStdin(1,0,0);
return 0;
}
readArgs(argc, argv, bflag, nflag); //otherwise
return 0;
}
I want to be able to mix this functionality with the other options i implemented (like -n and -b).
Any suggestion?
Parameters:
linux LF not linux CRLF
skip whitespace to skip whitepsace in the empty lines
void skip(int skipw, int linux)
{
int count = 0;
int ch;
while((ch = fgetc(stdin)) != EOF)
{
if((ch == '\r' && !linux) || ch == '\n')
{
if(count <= (!linux * 2))
{
count++;
printf("%c", ch);
}
}
else
{
if(skipw && isspace(ch)) continue;
count = 0;
printf("%c", ch);
}
}
}

executing commands in own shell - C

I have troubles with creating my own shell in C. Here is the code I have so far
#include "interpreter.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <syslog.h>
void readconfig(int *timeout, char *file){
FILE * fp;
char * line = NULL;
size_t len = 0;
char * token;
fp = fopen(CONFIG, "r");
if (fp == NULL)
{
*timeout = DEFAULTTIME;
}
else
{
while ((getline(&line, &len, fp)) != -1){
token = strtok(line, TOKEN);
if ((strcmp(token,TIME_PERIOD) == 0)){
*timeout = atoi(strtok(NULL, TOKEN));
}
if ((strcmp(token,HISTORY)==0)){
strcpy(file,trim_command(strtok(NULL, TOKEN)));
}
}
}
}
int waitPeriod(pid_t pid){
if(pid) {
int stat_val;
pid_t child_pid;
int time = 0;
while(time < TIME_PERIOD){
child_pid = waitpid(pid, &stat_val, WNOHANG);
if (child_pid == pid){
break;
} else if (child_pid == 0) {
time++;
sleep(1);
}
}
if (time == TIME_PERIOD){
printf("Process ended. Execution time was over. \n");
kill(pid, SIGINT);
if (kill(pid, 0) == 0){
kill(pid, SIGKILL);
}
}
if(WIFEXITED(stat_val)) {
return WEXITSTATUS(stat_val);
}
return 0;
} else {
return -1;
}
}
void splitCommand(char ** parameters, char * command, int count){
char * cm = strtok(command, " ");
int i = 0;
while (cm != NULL){
parameters[i] = malloc(strlen(cm) * sizeof(char *));
parameters[i] = cm;
i++;
cm = strtok (NULL, " ");
}
i++;
parameters[i] = NULL;
}
int getParamsCount(char command[]){
int i;
int count = 1;
int com_length = strlen(command);
for(i=0; i<com_length; i++){
if (command[i] == ' '){
count++;
}
}
return count;
}
void getHistory(FILE * history_file, char ** history_commands){
char line[MAX_INPUT];
int i = 0;
int j;
rewind(history_file);
while (fgets(line, MAX_INPUT, history_file)!= NULL){
history_commands[i] = malloc(strlen(line) * sizeof(char *));
history_commands[i] = strdup(line);
for(j=0; j<MAX_INPUT; j++){
if (history_commands[i][j] == '\n'){
history_commands[i][j] = '\0';
break;
}
}
i++;
}
}
int getNumberOfRows(FILE * history_file){
rewind(history_file);
int lines = 0;
char ch;
while(!feof(history_file)){
ch = fgetc(history_file);
if(ch == '\n'){
lines++;
}
}
return lines;
}
void printCommands(char ** history_commands, int lines){
int i = 0;
int j = 0;
for(j = i; j < lines; j++){
printf("[%d] %s\n", j, history_commands[j]);
}
}
int runCommand(pid_t pid, char * command, char ** parameters, int child){
int count = 0;
switch(pid) {
case -1 :
return -1;
case 0 :
count = getParamsCount(command);
parameters = malloc((count+1) * sizeof(char *));
splitCommand(parameters, command, count);
if (strncmp("cd", parameters[0], 2) == 0){
chdir(parameters[1]);
} else {
execvp(parameters[0], parameters[0]);
}
free(parameters);
return 0;
default :
child = waitPeriod(pid);
printf("Child status: %d\n", child);
command[0] = 0;
free(command);
return 0;
}
}
char * trim_command(char * string){
int l = strlen(string);
int i;
for (i = 0; i<l; i++){
if (string[i] == '\n'){
string[i] = '\0';
}
}
return string;
}
int main(){
char * command;
FILE * history;
char cwd[MAX_INPUT];
pid_t pid = 0;
int child = 0;
int number_of_rows = 0;
int count = 0;
char ** history_commands;
char ** parameters[10];
printf(" Safe comand line interpreter \n");
printf(" Type \"quit\" to cancel interpreter or command \n");
printf(" Type \"history\" to show full command history \n");
printf(" Type \"history number\" to execute command from history \n");
printf("________________________________________________________________________________________\n");
sleep(1);
history = fopen(HISTORY, "a+");
if (history == NULL){
printf("Could not open history file\n");
return -1;
}
while(1){
getcwd(cwd, sizeof(cwd));
printf("Command: [%d]%s : ", child, cwd);
command = malloc(MAX_INPUT * sizeof(char *));
fgets(command, MAX_INPUT, stdin);
trim_command(command);
if (strncmp(QUIT, command, 4) == 0) {
fclose(history);
return EXIT_SUCCESS;
} else if (strncmp("history", command, 7) == 0) {
number_of_rows = getNumberOfRows(history);
history_commands = malloc(number_of_rows * sizeof(char *));
getHistory(history, history_commands);
count = getParamsCount(command);
if (strcmp("history", command) == 0){
printf("HISTORY OF COMMANDS\n");
printCommands(history_commands, number_of_rows);
} else {
char * cm = strtok(command, " ");
cm = strtok(NULL, " ");
int x;
x = atoi(cm);
if (x >= number_of_rows){
printf("Command does not exist\n");
continue;
}
command = strdup(history_commands[x]);
count = getParamsCount(command);
trim_command(command);
fprintf(history, "%s\n", command);
pid = fork();
runCommand(pid, command, parameters, child);
}
} else if (command[0] != 0){
fprintf(history, "%s\n", command);
pid = fork();
runCommand(pid, command, parameters, child);
}
}
fclose(history);
return 0;
}
The problem is, it doesn't execute cd command. When I comment malloc and free lines in runCommand method, cd command starts working, but every other command without parameter is not working...
could somebody help me with this?

How to empty Char Array and reuse the same in C?

I am trying to read a file. I want to read each line from the file and check if there are any spelling error in that line.
For that I have added condition that data from file will store in buffer until it gets a new line characher '\n'. And after getting this line I want to empty the buffer and re insert the values in that.
Code I am using for the same is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define W_COUNT 23800
#define MAX_LEN 100
char *dict[W_COUNT];
char buffer[MAX_LEN];
int num_words; //No of Words
char *statement[W_COUNT];
char buffer1[MAX_LEN];
void read_dictionary();
void file_read(char *);
void spell_check();
int word_search(char*);
int main(int argc, char*argv[]){
int i;
if(argc < 2){
printf("Expected Filename.\n");
exit(0);
}
read_dictionary();
file_read(argv[1]);
// spell_check();
}
void read_dictionary(){
FILE *fd;
int i = 0;
fd = fopen("dictionary", "r");
while ( fscanf(fd,"%s",buffer) != EOF)
dict[i++] = strdup(buffer);
num_words = i;
fclose(fd);
}
void file_read(char *filename){
FILE *fd;
int i = 0;
char c;
fd = fopen(filename,"r");
/*while ( fscanf(fd,"%s",buffer1) != EOF)
{
word[i++] = strdup(buffer1);
printf("File : %s\n", buffer1);
}*/
while ( ( c = fgetc(fd)) != EOF )
{
buffer1[i++] = tolower(c);
if ( c == '\n')
{
//printf("New Line\n");
spell_check();
buffer1[i] = 0;
}
//buffer1[i] = 0;
}
printf("Statement : %s\n", buffer1);
fclose(fd);
}
void spell_check(){
char *str;
str = strtok(buffer1," .?,!-");
while( str != NULL){
if(!word_search(str))
printf("%s Not found.\n",str);
str = strtok(0," .?,!-");
}
}
int word_search(char *word){
int high, low, mid;
high = num_words - 1;
low = 0;
int found = 0;
while (found == 0){
mid = (low + high) / 2;
if(strcmp(word, dict[mid]) == 0)
return 1;
else if(strcmp(word,dict[mid]) < 0)
high = mid - 1;
else
low = mid + 1;
if ( low > high)
return 0;
}
}
Any suggestions will be appreciated.
Thank you in advance.
while ( ( c = fgetc(fd)) != EOF )
{
buffer1[i++] = tolower(c);
if ( c == '\n')
{
//printf("New Line\n");
spell_check();
i = 0;
buffer1[i] = 0;
}
//buffer1[i] = 0;
}
For each line reading you have to assign the 0 to the i. After that you have to assign the null to the 0th position in the buffer.
You can try the above code for loop it will work.

Write a WC simulator in C with different Child Processes [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Here is the final result i got so far for a simulator of wc linux command. I have to accomplish an output like this
This is child process 0, the number of lines is x
This is child process 1, the number of words is y
This is child process 2, the number of lines is z
The code i wrote is this one:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
char* concat(char *s1, char *s2)
{
char *result = malloc(strlen(s1)+strlen(s2)+1);
strcpy(result, s1);
strcat(result, s2);
return result;
}
int countLines(FILE *f){
int count = 0;
char ch;
while ((ch = fgetc(f)) != EOF){
if (ch == '\n')
count++;
}
return count;
}
int countWords(FILE *f){
int countW = 0;
char ch;
while ((ch = fgetc(f)) != EOF){
if (ch == ' ')
countW++;
}
return countW;
}
int countChars(FILE *f){
int chars = 0;
char ch;
while ((ch = fgetc(f)) != EOF){
chars++;
}
return chars;
}
int main(int argc, char** argv)
{
int lineCount = 0;
int wordCount = 0;
int charCount = 0;
int n = 3;
int i,status;
int pids[3];
char *theprogram = argv[0];
char *thefile = argv[1];
if ( argc !=2 )
{
printf( "Help: %s filename\n", argv[0]);
}
else{
FILE *file = fopen( argv[1], "r");
if(file == 0){
char *sub = concat(theprogram, ": ");
char *middle = concat(sub, thefile);
perror(middle);
}
else{
for (i = 0; i < n; i++) {
pids[i] = fork();
if ( pids[i] < 0) {
perror("fork");
exit(-1);
} else if (pids[i] == 0) {
if (i==0){
lineCount += countLines(file);
printf("This is child proccess %d, and the number of lines is %d\n", i+1, lineCount);
exit(0);
}
else if (i==1){
wordCount += countWords(file);
printf("This is child proccess %d, and the number of words is %d\n", i+1, wordCount);
exit(0);
}
else {
charCount += countChars(file);
printf("This is child proccess %d, and the number of characters is %d\n", i+1, charCount);
exit(0);
}
}
}
return 0;
}
}
}
This is the actual output i am getting:
% ./a.out mywc.c
This is child proccess 2, and the number of words is 0
This is child proccess 1, and the number of lines is 64
This is child proccess 3, and the number of characters is 0
This is child proccess 3, and the number of characters is 0
This is child proccess 2, and the number of words is 0
This is child proccess 3, and the number of characters is 0
This is child proccess 3, and the number of characters is 0
What am I doing Wrong here? I am very new to C programming so not sure what i am missing.
Thanks.
EDIT
Exited the exit codes but can not get the word count and the character count right now.
The right code for my problem is here:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
char* concat(char *s1, char *s2)
{
char *result = malloc(strlen(s1)+strlen(s2)+1);
strcpy(result, s1);
strcat(result, s2);
return result;
}
int countLines(char *f){
FILE *file = fopen(f, "r");
int count = 0;
char ch;
while ((ch = fgetc(file)) != EOF){
if (ch == '\n')
count++;
}
return count;
}
int countWords(char *f){
char buffer[1];
FILE *file = fopen(f, "r");
int countW = 0;
enum states { WSP, WRD };
int state = WSP;
char last = ' ';
while (read(fileno(file),buffer,1) == 1 )
{
if ( buffer[0]== ' ' || buffer[0] == '\t' || buffer[0]=='\n' )
{
state = WSP;
}
else
{
if ( state == WSP )
{
countW++;
}
state = WRD;
}
last = buffer[0];
}
return countW;
}
int countChars(char *f){
FILE *file = fopen(f, "r");
int chars = 0;
char ch;
while ((ch = fgetc(file))){
if (ch == EOF) break;
chars++;
}
return chars;
}
int main(int argc, char** argv)
{
int lineCount = 0;
int wordCount = 0;
int charCount = 0;
int n = 3;
int i,status;
int pids[3];
char *theprogram = argv[0];
char *thefile = argv[1];
if ( argc !=2 )
{
printf( "Help: %s filename\n", argv[0]);
}
else{
FILE *file = fopen( argv[1], "r");
if(file == 0){
char *sub = concat(theprogram, ": ");
char *middle = concat(sub, thefile);
perror(middle);
}
else{
for (i = 0; i < n; i++) {
pids[i] = fork();
if ( pids[i] < 0) {
perror("fork");
exit(-1);
} else if (pids[i] == 0) {
if (i==0){
lineCount = countLines(argv[1]);
printf("This is child proccess %d, and the number of lines is %d\n", i+1, lineCount);
exit(0);
}
else if (i==1){
wordCount = countWords(argv[1]);
printf("This is child proccess %d, and the number of words is %d\n", i+1, wordCount);
exit(0);
}
else {
charCount += countChars(argv[1]);
printf("This is child proccess %d, and the number of characters is %d\n", i+1, charCount);
exit(0);
}
}
}
return 0;
}
}
}

Resources