Reading a line and removing Spaces from matrix in a file - c

OK so I manage to write to the file char by char but it writes twice the numbers and it it still write it with spaces. Any advice and solution?
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#include <ctype.h>
#include <fcntl.h>
extern int errno;
#define MAX_LEN 18
int main(int argc, char *argv[]) {
int fd[2], des, bytes, target;
char buffer[161];
int fdr, fdw; // file descriptors
char c;
fdr = open(argv[1], O_RDONLY); // open files
fdw = open("gg.txt", O_WRONLY | O_CREAT);
if (fdr < 0 || fdw < 0) {
perror("failed to open input or output files");
exit(EXIT_FAILURE);
}
while (read(fdr, &c, 1)) { // read/write a single char from/to the files
if (c != ' ' && c != EOF) {
if (write(fdw, &c, 1) != 1) {
perror("write() failed");
exit(EXIT_FAILURE);
}
} // echo char to stdout
}
close(fdr); // close the files
close(fdw);
exit(EXIT_SUCCESS);
}
EDIT SECTION
hey again,
i managed to read the file and write it to new one without spaces but i'm trying to insert the values to matrix but im getting an error trying to open the new file.
i have changed the permissions
fdw = open("gg.txt", O_RDWR | O_CREAT | O_TRUNC, 0644);
the function
void removeSpaces(int matrix[SIZE][SIZE],int fdr, int fdw) {
char c;
char matBuffer={0};
while (read(fdr, &c, 1)) // read/write a single char
{ // from/to the files
if (c != ' ') {
if (write(fdw, &c, 1) != 1) {
perror("write() failed");
exit(EXIT_FAILURE);
}
}
}
int i;
int j;
int k=0;
while(read(fdw, &matBuffer, 1))
{
for(i=0;i<SIZE;i++)
{
for(j=0;j<SIZE;j++)
{
matrix[i][j]=matBuffer-'0';
k++;
}
k=0;
}
}
}
The whole program
// C program to illustrate
// open system call
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#include <ctype.h>
#include <fcntl.h>
#define MAX_LEN 18
#define SIZE 9
void removeSpaces(int matrix[SIZE][SIZE],int fdr, int fdw) {
char c;
char matBuffer={0};
while (read(fdr, &c, 1)) // read/write a single char
{ // from/to the files
if (c != ' ') {
if (write(fdw, &c, 1) != 1) {
perror("write() failed");
exit(EXIT_FAILURE);
}
}
}
int i;
int j;
int k=0;
while(read(fdw, &matBuffer, 1))
{
for(i=0;i<SIZE;i++)
{
for(j=0;j<SIZE;j++)
{
matrix[i][j]=matBuffer-'0';
k++;
}
k=0;
}
}
}
int is_safe(int matrix[9][9],int n, int r, int c)
{
int i,j;
//checking in row
for(i=0;i<9;i++)
{
//there is a cell with same value
if(matrix[r][i] == n)
return 0;
}
//checking column
for(i=0;i<SIZE;i++)
{
//there is a cell with the value equal to i
if(matrix[i][c] == n)
return 0;
}
//checking sub matrix
int row_start = (r/3)*3;
int col_start = (c/3)*3;
for(i=row_start;i<row_start+3;i++)
{
for(j=col_start;j<col_start+3;j++)
{
if(matrix[i][j]==n)
return 0;
}
}
return 1;
}
int main(int argc, char * argv[]) {
int pipe_descs[2];
int matrix[SIZE][SIZE];
int fdr, fdw; // file descriptors
int i,j;
/* if (pipe(pipe_descs) == -1) {
fprintf(stderr, "cannot open");
exit(1);
}
pid_t status = fork();
if(status ==0 )
{
}*/
fdr = open(argv[1], O_RDONLY); // open files
fdw = open("gg.txt", O_RDWR | O_CREAT | O_TRUNC, 0644);
if (fdr < 0 || fdw < 0) { //validation for error
perror("failed to open input or output files");
exit(EXIT_FAILURE);
}
removeSpaces(matrix,fdr, fdw);
for(i=0; i<9; i++){ /* Iterate of each row */
for(j=0; j<9; j++){ /* In each row, go over each col element */
printf("%c ",matrix[i][j]); /* Print each row element */
}
printf("\n"); /* Finish a row, start a new line */
}
close(fdr); // close the files
close(fdw);
exit(EXIT_SUCCESS);
}

There are multiple problems in the code:
you do not test for read errors, read can return -1 for error, which would not stop the while loop.
testing c != EOF is meaningless. EOF is returned by getc() to indicate end of stream or input error, read indicates these conditions in its return value, c is always a byte value if read succeeded and returned 1.
gg.txt is not truncated by open with the given flags. Chances are you are overwriting the beginning of the file and for some reason the file is longer from previous attempts and still contains previously written data. You must also pass the mode bits for the file creation as the third argument to open. Use this:
// open the file for writing, truncate if it exists or create with
// read/write permission for user, read permission for group and others
fdw = open("gg.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
the comment // echo char to stdout does not seem to refer to any code.
Here is a corrected version:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
int fdr, fdw; // file descriptors
char c;
fdr = open(argv[1], O_RDONLY); // open files
if (fdr < 0) {
fprintf(stderr, "failed to open input file %s: %s\n", argv[1], strerror(errno));
return EXIT_FAILURE;
}
// open the output file for writing, truncate if it exists or create with
// read/write permission for user, read permission for group and others
fdw = open("gg.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fdw < 0) {
fprintf(stderr, "failed to open output file %s: %s\n", "gg.txt", strerror(errno));
return EXIT_FAILURE;
}
// read/write a single char from/to the files
while (read(fdr, &c, 1) == 1) {
if (c != ' ') {
if (write(fdw, &c, 1) != 1) {
perror("write() failed");
return EXIT_FAILURE;
}
}
}
close(fdr); // close the files
close(fdw);
return EXIT_SUCCESS;
}

Related

pipe() data is not transferred to child process

I'm trying writing to the pipe and read the content of it when exec to another file but, For some reason I can't make it work.
Here is the main.c file
int main(int argc, char * argv[]) {
int pipe_descs[2];
int matrix[SIZE][SIZE];
int fdr, fdw; // file descriptors
int i;
pid_t status=0;
if (pipe(pipe_descs) == -1) {
fprintf(stderr, "cannot open");
exit(1);
}
fdr = open(argv[1], O_RDONLY); // open files
fdw = open("gg.txt", O_RDWR | O_CREAT | O_TRUNC, 0644);
if (fdr < 0 || fdw < 0) { //validation for error
perror("failed to open input or output files");
exit(EXIT_FAILURE);
}
removeSpaces(matrix, fdr, fdw);
status=fork();
if (status < 0) {
fputs("error in fork", stderr);
exit(EXIT_FAILURE);
}
close(pipe_descs[0]);
close(STDOUT_FILENO);
dup(pipe_descs[1]);
write(pipe_descs[1],matrix,sizeof(matrix));
if(status == 0) {
execl("rowsValidation", "rowsValidation", NULL);
/*dup2(pipe_descs[IN],0);
dup2(pipe_descs[OUT],4);
close(STDOUT_FILENO);*/
}
…
This is the other file which trying to read the data from the buffer but nothing happened.
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char * argv[]){
int pipe_descs[2];
int mat[9][9];
int fdr, fdw; // file descriptors
char ans='9';
int i, j;
printf("%s","got here");
close(pipe_descs[1]);
close(STDIN_FILENO);
dup(pipe_descs[0]);
read(pipe_descs[0],mat,sizeof(mat));
for (i = 0; i < 9; i++) { /* Iterate of each row */
for (j = 0; j < 9; j++) { /* In each row, go over each col element */
printf("%d ", mat[i][j]); /* Print each row element */
}
printf("\n"); /* Finish a row, start a new line */
}
exit(0);
}
After reading the comments and reading more in the net i have changed it to this
i tried to check it with a char but i still cant manage it to work.
the father writes the char to the pipe and the son do the exec to the new process and then it reads from the pipe but it still doesnt work.
please help me fix it
int main(int argc, char * argv[]) {
int pipe_descs[2];
int matrix[SIZE][SIZE];
int fdr, fdw; // file descriptors
int i;
char a='10';
pid_t status=0;
if (pipe(pipe_descs) == -1) {
fprintf(stderr, "cannot open");
exit(1);
}
fdr = open(argv[1], O_RDONLY); // open files
fdw = open("gg.txt", O_RDWR | O_CREAT | O_TRUNC, 0644);
if (fdr < 0 || fdw < 0) { //validation for error
perror("failed to open input or output files");
exit(EXIT_FAILURE);
}
removeSpaces(matrix, fdr, fdw);
status=fork();
if (status < 0) {
fputs("error in fork", stderr);
exit(EXIT_FAILURE);
}
if(status == 0) {
dup2(pipe_descs[0], 0); // read the matrix from pipe1 to 0
close(pipe_descs[0]);
dup2(pipe_descs[1], 4);
printf("Execl1 start\n");
// write to 4 instead of pipe1[1]
execl("rowsValidation", "rowsValidation", NULL);
}
else{
write(pipe_descs[1],&a,sizeof(char));
close(pipe_descs[1]);
/*char buffer[10];
close(pipe_descs[1]);
close(STDIN_FILENO);
dup(pipe_descs[0]);
read(pipe_descs[0],buffer,sizeof(buffer));
printf("%s",buffer);
close(pipe_descs[0]);*/
}
close(fdr); // close the files
close(fdw);
exit(EXIT_SUCCESS);
}
int main(int argc, char * argv[]){
int pipe_descs[2];
int mat[9][9];
int fdr, fdw; // file descriptors
char ans;
int i, j;
read(0,&ans,sizeof(char));
printf("%c ", ans);
for (i = 0; i < 9; i++) { /* Iterate of each row */
for (j = 0; j < 9; j++) { /* In each row, go over each col element */
printf("%d ", mat[i][j]); /* Print each row element */
}
printf("\n"); /* Finish a row, start a new line */
}
/* if (pipe(pipe_descs) == -1) {
fprintf(stderr, "cannot open");
exit(1);
}*/
//write(4,1,sizeof(char));
exit(0);
}
I think you have a slight understanding of what you want and how to do it, but you're not 100% there.
If you want to create a pipe, write information there and have another program read it: you start by creating the pipe, create a new process via a fork(), for example, (some people advise against the use of fork: https://www.microsoft.com/en-us/research/publication/a-fork-in-the-road/) and change the file descriptors around via dup2() (and dup()) calls. The process of creating a pipe, forking and doing an exec can be easly done via a popen() call, and I advise that you look into it.
Here's an example that might help you:
char* generate_hash(char* password, char* salt)
{
char password_plus_salt[MAX_PASSWORD_LEN + SALT_LEN];
strcpy(password_plus_salt, password);
strcat(password_plus_salt, salt);
int fd[2];
pipe(fd);
int stdout_save = dup(STDOUT_FILENO);
dup2(fd[WRITE], STDOUT_FILENO);
FILE* input = popen("sha256sum", "w");
fprintf(input, password_plus_salt, "%s");
FILE* output = fdopen(fd[READ], "r");
pclose(input);
char* hash = (char*)malloc(sizeof(char) * (HASH_LEN + 1));
memset(hash, '\0', (HASH_LEN + 1) * sizeof(char));
for (int i = 0; i < HASH_LEN; i++) {
hash[i] = (char)fgetc(output);
}
dup2(stdout_save, STDOUT_FILENO);
return hash;
}
I also advise you to switch your error checking around and change stuff like:
if (fdr < 0 || fdw < 0) { //validation for error
perror("failed to open input or output files");
exit(EXIT_FAILURE);
}
for:
if (fdr < 0)
{
perror("fdr");
exit(EXIT_FAILURE);
}
if (fdw < 0)
{
perror("fdw");
exit(EXIT_FAILURE);
}
So you can be certain of the origin of the error.

Reading and searching files using systemcalls in C

I tried reading from the file "hello.txt" but it doesn't enter the while loop at all. The read function returns 0 on EOF and -1 on error. I'm trying to search for the word in w if it exists in the file or not. I'm reading characters from the file and comparing them to w[].
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main()
{
int fd;
char c;
int i=0;
int bytesread;
int flag=1;
char w[]={'h','e','l','l','o'};
if((fd=open("hello.txt",O_RDONLY,0))!=-1){ //if 1
bytesread = read(fd,&c,0);
if(bytesread!=-1){ //if 2
while(bytesread!=0)
{ //while
if(c==w[i])
{ //if 3
i++;
flag=0;
} //end of f3
else if(flag==0&&i!=0)
{ // else 3
i=0;
flag=1;
} // end of else 3
bytesread = read(fd,&c,0);
} //end of while
}else //end of if 2
printf("couldn't read file.\n");
}else //end of if 1
printf("Couldn't open file for read.\n");
} //end of main
ssize_t read(int fd, void *buf, size_t count);
read reads count bytes from the file. You're asking it to read zero bytes when doing bytesread = read(fd,&c,0);. Change it to bytesread = read(fd,&c,1);
Try this:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(void)
{
int fd;
char c;
int bytesread;
if ((fd = open("hello.txt", O_RDONLY, 0)) != -1) {
while ((bytesread = read(fd, &c, 1)) == 1)
printf("read %d bytes [%c]\n", bytesread, c);
} else
printf("Couldn't open file for read.\n");
return 0;
}
read(fd,&c,0) asks the system to read zero bytes, and it shouldn't be what you want to do.
You should ask the system to read one byte by read(fd,&c,1).

Contents of file not being printed in terminal

Hi I am trying to read from a file and print it on terminal. But fwrite() does not print anything. Can anyone please help! I cannot see the output from the file on the terminal. After debugging all I can see is program is not entering into while loop used before fwrite().
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#define BUF_SIZE 128
int main(int argc, char* argv[])
{
int BATT_fd, ret_write, ret_read, i;
char buffer[BUF_SIZE];
if(argc != 2)
{
printf ("\nUsage: cp file1 file2\n");
return 1;
}
BATT_fd = open (argv [1], O_RDWR | O_CREAT, S_IRWXU);
if (BATT_fd == -1)
{
perror ("open");
return 2;
}
printf("\n file opened successfully with file desc %d\n", BATT_fd);
printf("enter data into file\n");
scanf("%[^\n]", buffer);
if((ret_write = write (BATT_fd, &buffer, BUF_SIZE)) == 0)
{
printf("nothing is write");
}
else if((ret_write = write (BATT_fd, &buffer, BUF_SIZE)) == -1)
{
printf("write error");
}
else
{
printf("wrote %d characters to file\n", ret_write);
printf("address writeen is %x\n", buffer[i]);
}
if((ret_read = read(BATT_fd, &buffer, BUF_SIZE)) > 0)
{
perror("read");
return 4;
}
else
{
while((ret_read = read (BATT_fd, &buffer, BUF_SIZE)) > 0)
{
fwrite(buffer, 1, ret_read, stdout);
}
}
close (BATT_fd);
return 0;
}
output:
Before reading data from file, you need to move current position in file to the begining. That's because your write operations have moved current position to the end of file, so there is nothing left for reading ;).
see fseek
EDIT:
lseek would be better in your case (see comments)

How to send a file through a named pipe in C?

I have two programs, server and client. Server should read a file and then send its content through a named pipe to client. But my server reads only two chars from file, and then exits. What is wrong with this code?
server.c:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define FIFO_NAME "american_maid"
int main(void)
{
char line[300];
int num, fd;
FILE *fp;
fp = fopen("out.txt","r");
mknod(FIFO_NAME, S_IFIFO | 0666, 0);
printf("waiting for readers...\n");
fd = open(FIFO_NAME, O_WRONLY);
printf("got a reader--type some stuff\n");
while (fgets(line, sizeof(line), fp)) {
if ((num = write(fd, line, strlen(line))) == -1)
perror("write");
else
printf("speak: wrote %d bytes\n", num);
}
fclose(fp);
return 0;
}
client.c:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define FIFO_NAME "american_maid"
int main(void)
{
char s[300];
int num, fd;
mknod(FIFO_NAME, S_IFIFO | 0666, 0);
printf("waiting for writers...\n");
fd = open(FIFO_NAME, O_RDONLY);
printf("got a writer\n");
do {
if ((num = read(fd, s, 300)) == -1)
perror("read");
else {
s[num] = '\0';
printf("tick: read %d bytes: \"%s\"\n", num, s);
}
} while (num > 0);
return 0;
}
When I run the code shown below using the command sequence:
$ ln -s server.c out.txt
$ ./client &
$ ./server
$
I get a copy of the source code printed by the client program. Similarly when I run the commands using:
$ ./server &
$ ./client
$
The revised code is not modified all that significantly. It avoids do { } while(...) loops — they're so seldom really beneficial — and is very careful about not overflowing buffers. The code also has superfluous headers removed.
server.c
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define FIFO_NAME "american_maid"
int main(void)
{
const char infile[] = "out.txt";
FILE *fp = fopen(infile, "r");
if (fp == 0)
{
fprintf(stderr, "Failed to open %s for reading", infile);
return(1);
}
mknod(FIFO_NAME, S_IFIFO | 0666, 0);
printf("waiting for readers...\n");
int fd = open(FIFO_NAME, O_WRONLY);
if (fd > 0)
{
char line[300];
printf("got a reader--type some stuff\n");
while (fgets(line, sizeof(line), fp))
{
int len = strlen(line);
int num = write(fd, line, len);
if (num != len)
perror("write");
else
printf("speak: wrote %d bytes\n", num);
}
close(fd);
}
fclose(fp);
return 0;
}
client.c
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#define FIFO_NAME "american_maid"
int main(void)
{
const char outfile[] = "client.out";
FILE *fp = fopen(outfile, "w");
if (fp == 0)
{
fprintf(stderr, "Failed to open %s for writing\n", outfile);
return 1;
}
printf("waiting for writers...\n");
mknod(FIFO_NAME, S_IFIFO | 0666, 0);
int fd = open(FIFO_NAME, O_RDONLY);
if (fd > 0)
{
int num;
char s[300];
printf("got a writer\n");
while ((num = read(fd, s, sizeof(s))) > 0)
{
printf("tick: read %d bytes: \"%.*s\"\n", num, num, s);
fprintf(fp, "%.*s", num, s);
}
close(fd);
}
fclose(fp);
return 0;
}
Note that this version writes its output to file client.out; even when given a file with some very long lines to process (2049 bytes including the newline at the end), the output in client.out exactly matches the input in out.txt.
Remove the line mknod(FIFO_NAME, S_IFIFO | 0666, 0); from the file client.c. Then the program will work as expected. Server will create a file and sent the content of the file to fifo.

working with pipes

I am trying to make this work but no luck, basically i need to write to the pipe and then make the pipe return back with the text i sent. I have a server.c and client.c , so i make the server.c run..., open a new terminal and then run the client.. the problem is that the client doesnt do anything when i run it.. I am sure i am missing something.. like closing the pipe. i am not sure.. I would really appreciate some guidance
server.c
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#define PIPE1 "PIPE1"
#define PIPE5 "PIPE5"
#define MAX_BUF_SIZE 255
int main(int argc, char *argv[])
{
int rdfd1,rdfd2,rdfd3,rdfd4, wrfd1,wrfd2,wrfd3,wrfd4,ret_val, count, numread1,numread2,numread3,numread4;
char buf1[MAX_BUF_SIZE];
char buf2[MAX_BUF_SIZE];
char buf3[MAX_BUF_SIZE];
char buf4[MAX_BUF_SIZE];
/* Create the first named - pipe */
ret_val = mkfifo(PIPE1, 0666);
if ((ret_val == -1) && (errno != EEXIST)) {
perror("Error creating the named pipe");
return 1;
}
ret_val = mkfifo(PIPE5, 0666);
if ((ret_val == -1) && (errno != EEXIST)) {
perror("Error creating the named pipe");
return 1;
}
/* Open the first named pipe for reading */
rdfd1 = open(PIPE1, O_RDONLY);
/* Open the first named pipe for writing */
wrfd1 = open(PIPE5, O_WRONLY);
/* Read from the pipes */
numread1 = read(rdfd1, buf1, MAX_BUF_SIZE);
buf1[numread1] = '0';
printf("Server : Read From the pipe : %sn", buf1);
/*
* Write the converted content to
* pipe
*/
write(wrfd1, buf1, strlen(buf1));
}
client.c
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define PIPE1 "PIPE1"
#define PIPE5 "PIPE5"
#define MAX_BUF_SIZE 255
int main(int argc, char *argv[ ]) {
pid_t childpid;
int error;
int i;
int nprocs;
/* check command line for a valid number of processes to generate */
int wrfd1, rdfd1, numread;
char rdbuf[MAX_BUF_SIZE];
if ( (argc != 2) || ((nprocs = atoi (argv[1])) <= 0) ) {
fprintf (stderr, "Usage: %s nprocs\n", argv[0]);
return 1;
}
for (i = 1; i < nprocs; i++) {
/* create the remaining processes */
if ((childpid = fork()) == -1) {
fprintf(stderr, "[%ld]:failed to create child %d: %s\n", (long)getpid(), i, strerror(errno));
return 1;
}
/* Open the first named pipe for writing */
wrfd1 = open(PIPE5, O_WRONLY);
/* Open the second named pipe for reading */
rdfd1 = open(PIPE1, O_RDONLY);
if (childpid)
break;
char string1[100];
if(sprintf(string1, "This is process %d with ID %ld and parent id %ld\n", i, (long)getpid(), (long)getppid())) {
write(wrfd1,string1, strlen(string1));
}
/* Read from the pipe */
numread = read(rdfd1, rdbuf, MAX_BUF_SIZE);
rdbuf[numread] = '0';
printf("Full Duplex Client : Read From the Pipe : %sn", rdbuf);
}
return 0;
}
It seems like both server and client read from PIPE1 and write to PIPE5. Shouldn't one of them write to PIPE1 so that the other can read it from the other end?
Also, if you're testing with ./client 1, your for (i = 1; i < nprocs; i++) loop will never execute.
One last thing, see this question. I'm not entirely sure it applies to your code, but it's worth keeping in mind.
Shouldn't this line be '\0' ?
buf1[numread1] = '0';

Resources