I have a problem at my C-lecture skill practice. My exercise is to read a text document (which is in the same directory like the program) char by char and write it reversed (so from the end to the beginning, char by char) at the Terminal (i have to work at Ubuntu).
Unfortunately it doesn't work - "read" only reads newline-chars (\n).
Can you find my mistake?
#include <sys/stat.h> //mode_t: accessing rights for the file
#include <fcntl.h> //for I/O
#include <unistd.h> //for file descriptors
#include <string.h> //for strlen
short const EXIT_FAILURE = 1;
short const EXIT_SUCCESS = 0;
char const* USAGE_CMD = "usage: write_file filename string_to_write\n";
char const* ERR_OPEN = "error in open\n";
char const* ERR_READ = "error in reading\n";
char const* ERR_CLOSE = "error in close\n";
char const* ERR_WRITE = "error in write\n";
int main(int argc, char** argv){
int fd = open(argv[1], O_RDONLY);
if(fd == -1){
write(STDERR_FILENO, ERR_OPEN, strlen(ERR_OPEN));
return EXIT_FAILURE;
}
int two_char_back = (-1)*sizeof(char); //shift-value for char
int one_back = -1; //shift-value for "no shift"
int length = lseek(fd, one_back, SEEK_END);//setting to one before oef
int i = 0; //for the loop
char buffer;
char* pbuffer = &buffer; //buffer for writing
while (i < length){
if (read(fd, pbuffer, sizeof(buffer)) == -1){ //READING
write(STDERR_FILENO, ERR_READ, strlen(ERR_READ));
return EXIT_FAILURE;
}
if(write(STDOUT_FILENO, pbuffer, sizeof(buffer)) == -1){ //WRITING
write(STDERR_FILENO, ERR_WRITE, strlen(ERR_WRITE));
return EXIT_FAILURE;
}
lseek(fd, two_char_back, SEEK_CUR); //STEPPING
i++;
}
if(close(fd) == -1){ //CLOSING
write(STDERR_FILENO, ERR_CLOSE, strlen(ERR_CLOSE));
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
This is wrong:
int two_char_back = (-1)*sizeof(char);
sizeof(char) is 1, you need -2
Haven't tried running it, but looks like two_char_back should be -2. The read advances the cursor, so -1 keeps reading the same one.
Also, just an option, you could make it more efficient by reading the whole file in then reversing it, then writing.
You have a typo in following line:
int two_char_back = (-1)*sizeof(char);
It must be:
int two_char_back = (-2)*sizeof(char);
As read() increments a cursor, you are actually reading the same character all the time e.g:
example text
^
|
After reading:
example text
^
|
After seeking:
example text
^
|
Thanks for your advices a lot!
& Thanks to my colleagues!
Now it works but I created kind of a new version, here it is:
#include <sys/stat.h> //mode_t: accessing rights for the file
#include <fcntl.h> //for I/O
#include <unistd.h> //for file descriptors
#include <string.h> //for strlen
short const EXIT_FAILURE = 1;
short const EXIT_SUCCESS = 0;
char const* USAGE_CMD = "usage: write_file filename string_to_write\n";
char const* ERR_OPEN = "error in open\n";
char const* ERR_READ = "error in reading\n";
char const* ERR_CLOSE = "error in close\n";
char const* ERR_WRITE = "error in write\n";
int main(int argc, char** argv){
int fd = open(argv[1], O_RDONLY); //OPENING
if(fd == -1){
write(STDERR_FILENO, ERR_OPEN, strlen(ERR_OPEN));
return EXIT_FAILURE;
}
int file_size = lseek(fd, 0, SEEK_END); //setting to eof
int i = file_size-1; //for the loop, runs from the end to the start
char buffer;
//the files runs from the end to the back
do{
i--;
lseek(fd, i, SEEK_SET); //STEPPING from the start
if (read(fd, &buffer, sizeof(buffer)) != sizeof(buffer)){ //READING
write(STDERR_FILENO, ERR_READ, strlen(ERR_READ));
return EXIT_FAILURE;
}
if(write(STDOUT_FILENO, &buffer, sizeof(buffer)) != sizeof(buffer)){ //WRITING
write(STDERR_FILENO, ERR_WRITE, strlen(ERR_WRITE));
return EXIT_FAILURE;
}
}while (i != 0);
buffer = '\n';
write(STDOUT_FILENO, &buffer, sizeof(buffer));//no error-det. due to fixed value
if(close(fd) == -1){ //CLOSING
write(STDERR_FILENO, ERR_CLOSE, strlen(ERR_CLOSE));
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Related
I want to make copy/paste with using c FILE but i need to add read/write buffer too and I am not sure how to add it. Is there any function similar to regular read/write..Code is below.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[]) {
FILE* fsource, * fdestination;
printf("enter the name of source file:\n");
char sourceName[20], destinationName[20];
strcpy(sourceName, argv[1]);
strcpy(destinationName, argv[2]);
fsource = fopen(sourceName, "r");
if (fsource == NULL)
printf("read file did not open\n");
else
printf("read file opened sucessfully!\n");
fdestination = fopen(destinationName, "w");
if (fdestination == NULL)
printf("write file did not open\n");
else
printf("write file opened sucessfully!\n");
char pen = fgets(fsource);
while (pen != EOF)
{
fputc(pen, fdestination);
pen = fgets(fsource);
}
fclose(fsource);
fclose(fdestination);
return 0;
}
Here's a reworking of your code (sans some error handling) that reads and writes in 256-byte increments:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
char *sourceName = argv[0];
char destName[256];
snprintf(destName, 256, "%s.copy", sourceName);
printf("Copying %s -> %s\n", sourceName, destName);
FILE *fsource = fopen(sourceName, "rb");
FILE *fdest = fopen(destName, "w");
char buffer[256];
for (;;) {
size_t bytesRead = fread(buffer, 1, 256, fsource);
if (bytesRead == 0) {
break;
}
if (fwrite(buffer, 1, bytesRead, fdest) != bytesRead) {
printf("Failed to write all bytes!");
break;
}
printf("Wrote %ld bytes, position now %ld\n", bytesRead, ftell(fdest));
}
fclose(fsource);
fclose(fdest);
return 0;
}
The output is e.g.
$ ./so64481514
Copying ./so64481514 -> ./so64481514.copy
Wrote 256 bytes, position now 256
Wrote 256 bytes, position now 512
Wrote 256 bytes, position now 768
Wrote 256 bytes, position now 1024
[...]
Wrote 168 bytes, position now 12968
I created two programs, which will communicate via named pipe, one will be reading from it and another one will be writing to it. It works pretty fine now, except for the fact, that it opens and writes to the same fifo exactly 3 times. It's my first time with C and pipes, and I don't understand why is this writing three times. Can you see why is this writing three times?
writing.c
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#define BUFFSIZE 512
#define err(mess) { fprintf(stderr,"Error: %s.", mess); exit(1); }
void writing(char *s)
{
int fd;
ssize_t n;
char buf[BUFFSIZE];
printf("writing to %s\n",s);
if ( (fd = open(s, O_WRONLY)) < 0)
err("open")
while( (n = read(STDIN_FILENO, buf, sizeof buf -1) ) > 0) {
buf[n-1] = '\0';
printf("Received: %s\n", buf);
if ( write(fd, buf, n) != n) {
err("write");
}
if(strcmp(buf,"END")==0){
printf("%s","exit");
break;
}
}
close(fd);
}
char* concat(const char *s1, const char *s2)
{
char *result = malloc(strlen(s1)+strlen(s2)+1);//+1 for the zero-terminator
strcpy(result, s1);
strcat(result, s2);
return result;
}
int file_stat(char *argv){
int isfifo = 0;
struct stat sb;
printf("%s",argv);
if (stat(argv, &sb) == -1) {
perror("stat");
exit(EXIT_FAILURE);
}
printf("File type: ");
if (sb.st_mode & S_IFMT == S_IFIFO) {
printf("FIFO/pipe\n");
isfifo = 1;
}
printf("Ownership: UID=%ld GID=%ld\n",
(long) sb.st_uid, (long) sb.st_gid);
//exit(EXIT_SUCCESS);
return isfifo;
}
int main(int argc, char *argv[])
{
// READ ALL FILES IN DIRECTORY
if (argc != 2) {
fprintf(stderr, "Usage: %s /<pathname>/\n", argv[0]);
exit(EXIT_FAILURE);
}
DIR *d;
struct dirent *dir;
if ((d = opendir (argv[1])) != NULL) {
/* print all the files and directories within directory */
while ((dir = readdir (d)) != NULL) {
printf ("%s\n", dir->d_name);
char* s = concat(argv[1], dir->d_name);
if (file_stat(s) == 1) {
writing(s);
}
else {
mkfifo("fifo_x", 0666);
writing("fifo_x");
}
free(s);
}
closedir (d);
}
else {
/* could not open directory */
perror ("error: ");
return EXIT_FAILURE;
}
}
reading file is the same except for "reading" function and call to reading()
reading
void reading(char *s)
{
int fd;
ssize_t n;
char buf[BUFFSIZE];
printf("%s",s);
if ( (fd = open(s, O_RDONLY)) < 0)
err("open");
while( (n = read(fd, buf, sizeof buf - 1) ) > 0) {
buf[n-1] = '\0';
if(strcmp(buf,"END")==0){
printf("%s\n", "exit");
break;
}
buf[n-1] = '\n';
if ( write(STDOUT_FILENO, buf, n) != n) {
exit(1);
}
}
close(fd);
}
the output
/home/..File type: Ownership: UID=0 GID=0
writing to fifo_x
END
Received: END
exitola
/home/olaFile type: Ownership: UID=1001 GID=1001
writing to fifo_x
END
Received: END
exit.
/home/.File type: Ownership: UID=0 GID=0
writing to fifo_x
END
Received: END
exit
You have three files in the directory with whose pathname you called your program. All three files are not fifo's so for each you write to fifo_x.
The file names are
.
..
olaFile
Maybe you should explicitly exclude the files
.
..
which happen to be in every directory in linux and represent the current directory . and the parent directory ...
I have some problem about to take integer numbers from binary file. My code is:
int main (int argc, char ** argv) {
FILE * fpi, *fpo, *fp;
int i, len;
char buf[50];
if (argc != 3) {
printf ("Syntax: %s filename_input, filename_output", argv[0]);
return (1);
}
len = 0;
if ((fpi = fopen (argv[1], "rt")) == NULL)
perror ("file_input open");
if ((fpo = fopen (argv[2], "wb")) == NULL)
perror ("file_output open %");
while(fscanf(fpi,"%d",&i) != EOF){ //Take the content of file input and put in the file binary
fwrite(&i, sizeof(int), 1, fpo); //I write each number i into file output
}
return (0);
}
Here, given a txt file with for example 5 integer numbers, it generates the corresponding binary file. Then, if I try to fread this binary file is all ok, but if I try to read this binary file with mmap function and I put the content on an array, in the output, as content of array, I have a strange character, a small square with 00 02. The code where I use mmap is:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char **argv) {
int fd;
int i, n, len;
int *vet;
struct stat stat_buf;
char *paddr;
if (argc != 2) {
printf("Syntax: %s filename", argv[0]);
return (1);
}
if ((fd = open(argv[1], O_RDWR)) == -1) {
perror("open");
}
if (fstat(fd, &stat_buf) == -1) {
perror("fstat");
}
len = stat_buf.st_size;
n = len / sizeof(int);
paddr = mmap((caddr_t) 0, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (paddr == (caddr_t) -1) {
perror("mmap");
}
close(fd);
vet = (int *) paddr;
for (i = 0; i < n; i++) {
printf("%d\n", vet[i]);
}
return (0);
}
The output that it gives me is:
Thank you in advance.
I'm not good at C and I'm trying to do something simple. I want to open a binary file, read blocks of 1024 bytes of data and dump into a buffer, process the buffer, read another 1024 byes of data and keep doing this until EOF. I know how / what I want to do with the buffer, but it's the loop part and file I/O I keep getting stuck on.
PSEUDO code:
FILE *file;
unsigned char * buffer[1024];
fopen(myfile, "rb");
while (!EOF)
{
fread(buffer, 1024);
//do my processing with buffer;
//read next 1024 bytes in file, etc.... until end
}
fread() returns the number of bytes read. You can loop until that's 0.
FILE *file = NULL;
unsigned char buffer[1024]; // array of bytes, not pointers-to-bytes
size_t bytesRead = 0;
file = fopen(myfile, "rb");
if (file != NULL)
{
// read up to sizeof(buffer) bytes
while ((bytesRead = fread(buffer, 1, sizeof(buffer), file)) > 0)
{
// process bytesRead worth of data in buffer
}
}
#include <stdio.h>
#include <unistd.h> // For system calls write, read e close
#include <fcntl.h>
#define BUFFER_SIZE 1024
int main(int argc, char* argv[]) {
unsigned char buffer[BUFFER_SIZE] = {0};
ssize_t byte = 0;
int fd = open("example.txt", O_RDONLY);
while ((byte = read(fd, buffer, sizeof(buffer))) != 0) {
printf("%s", buffer);
memset(buffer, 0, BUFFER_SIZE);
}
close(fd);
return 0;
}
Edited code added
#include <stdio.h>
#include <unistd.h> // For system calls write, read e close
#include <fcntl.h>
#define BUFFER_SIZE 1024
int main(int argc, char* argv[]) {
unsigned char buffer[BUFFER_SIZE] = {0};
ssize_t byte = 0;
// open file in read mode
int fd = open("example.txt", O_RDONLY);
// file opening failure
if (fd == -1) {
printf("Failed to open file\n");
return -1;
}
// loop
while (1) {
// read buffer
byte = read(fd, buffer, sizeof(buffer));
// error
if (byte == -1) {
printf("Encountered an error\n");
break;
} else if (byte == 0) {
// file end exit loop
printf("File reading end\n");
break;
}
// printf file data
printf("%s", buffer);
memset(buffer, 0, BUFFER_SIZE);
}
// Close file
close(fd);
return 0;
}
I am trying to read data from 2 named pipe and write it to another named pipe concatenating the content from 2 inputs. But why my output only shows the string from first input?
Here is my code:
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#define MAX_REC_SIZE 1024
int open_fifo(char *name, int mode) {
mode = mode == O_RDONLY ? (O_RDONLY | O_NONBLOCK): mode;
int fd;
if (access(name, F_OK) == -1) {
if(mkfifo(name, 0777) != 0) {
fprintf(stderr, "Could not create fifo %s\n", name);
exit(EXIT_FAILURE);
}
}
fd = open(name, mode);;
return fd;
}
void read_fifo(int fd, char *out_r) {
memset (out_r, '\0', MAX_REC_SIZE);
do {
if(read(fd, out_r, MAX_REC_SIZE) > 0) {
out_r = strtok(out_r, "\n");
return;
}
} while (1);
}
void write_fifo(int fd, char *out_w) {
write(fd, out_w, sizeof(out_w));
}
int main()
{
int pipe_fd[3], i;
char *pipe_nm[] = {"./in_pipe_1", "./in_pipe_2", "./out_pipe_1"};
int read_mode = O_RDONLY;
int write_mode = O_WRONLY;
char out[MAX_REC_SIZE];
char out_store[MAX_REC_SIZE];
for(i=0; i<3; i++) {
pipe_fd[i] = open_fifo(pipe_nm[i], i == 2 ? write_mode : read_mode);
}
read_fifo(pipe_fd[0], out);
strcpy(out_store, out);
read_fifo(pipe_fd[1], out);
strcat(out_store, out);
strcat(out_store, "\n");
write_fifo(pipe_fd[2], out_store);
return 0;
}
A suspicious part of your code is:
write(fd, out_w, sizeof(out_w))
Here, out_w is not an array, and the sizeof operator would yield the size of a char * pointer, not the length of the block.
You should pass the length of out_store to your write_fifo function.
Also, I'm not really sure what your intent is when using the strtok function.