When I run my program:
char stringnums[(NUMSIZE + 1) * NUMINROW + 1];
for(int i = 0; i < NUMINROW; i++)
sprintf(stringnums, "%d %s", rand() % (NUMSIZE * 10), stringnums);
if (write(desc, stringnums, strlen(stringnums)) == -1)
perror("write");
I can see some rubbish in the end of a file:
21 21 21 27 22 22 12 12 12 12 ... strange symbols...
Full code:
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#define NUMINROW 10
#define NUMSIZE 3
int main(){
int desc;
struct flock fl;
char stringnums[(NUMSIZE + 1) * NUMINROW + 1];
char* path = "randnums.txt";
srand(time(NULL));
desc = open(path, O_WRONLY);
if (desc == -1)
perror("open");
if (fcntl(desc, F_GETLK, &fl) == -1)
perror("fcntl_getlk");
fl.l_type = F_WRLCK;
if (fcntl(desc, F_SETLK, &fl) == -1)
perror("fcntl_setlk");
for(int i = 0; i < NUMINROW; i++)
sprintf(stringnums, "%d %s", rand() % (NUMSIZE * 10), stringnums);
if (write(desc, stringnums, strlen(stringnums)) == -1)
perror("write");
fl.l_type = F_UNLCK;
if (fcntl(desc, F_SETLK, &fl) == -1)
perror("fcntl_setlk");
if (close(desc) == -1)
perror("close");
return 0;
}
I have tried either to initialize stringnums as "\0" and put in write() sizeof() instead of strlen(), but it's not worked.
As #AndreasWenzel points out, you are attempting to concatenate a string overtop of itself... This is likely to break.
The receiving buffer must be large enough to hold what you want to put into it. Don't scrimp! Why not use 10Kb instead of trying to work with what you hope to be the minimum required?
To correctly concatenate into a large enough buffer:
char buf[ 10 * 1024 ], *at = buf;
for( i = 0; i < 5; i++ )
at += sprintf( at, "Something %d ", i );
The current length of the growng buffer can be quickly determined by at - buf.
You may also want to use snprintf() to pre-calculate the intending addition to the growing string to avoid writing beyond the end of the buffer.
Related
I have a large file (around 1,000,000 characters) in the format "AATACGTAGCTA" and a subsequent file, such as "CGTATC" (10,240 characters). I want to find the largest match of the subsequence within the main sequence. A full, 100% subsequence match may not exist, this is not guaranteed. For the sake of a smaller example, the above would output: Longest match is 4/6 starting at position 5.
I'm working on my C basics, and would like to implement it like so:
The user chooses how many processes they would like to split the work
into.
Each process does 1/nth of the work and updates the shared memory
values located in the struct.
The longest match (it may not be all characters) is reflected in the
struct, as well as it's starting position, and how many
characters were matched. See output below.
Code
#define _GNU_SOURCE
#include <limits.h>
#include <stdio.h>
#include <errno.h>
#include <semaphore.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/shm.h>
typedef struct memoryNeeded {
int start_pos, total_correct;
char sequence[1038336];
char subsequence[10240];
sem_t *sem;
} memoryNeeded;
// Used to check all arguments for validity
int checkArguments(char* p, int argc) {
char *prcs;
errno = 0;
int num;
long conv = strtol(p, &prcs, 10);
if (errno!= 0 || *prcs != '\0' || conv > INT_MAX || conv > 50) {
puts("Please input a valid integer for number of processes. (1-50)");
exit(1);
} else {
num = conv;
if (argc != 4) {
puts("\nPlease input the correct amount of command line arguments (4) in"
"the format: \n./DNA (processes) (sequence) (subsequence)\n");
exit(1);
} else
printf("Looking for string using %d processes...\n", num);
return(num);
}
}
int main (int argc, char* argv[]) {
int processes = checkArguments(argv[1], argc);
key_t shmkey;
int procNumber, shmid, pid;
FILE *sequence;
FILE *subsequence;
char *buf1, *buf2;
// Create shared memory
size_t region_size = sizeof(memoryNeeded);
shmkey = ftok("ckozeny", 5);
shmid = shmget(shmkey, region_size, 0644 | IPC_CREAT);
if (shmid < 0) {
perror("shmget\n");
exit(1);
}
// Create structure in shared memory, attach memory and open semaphore
memoryNeeded *mn;
mn = (memoryNeeded *)shmat(shmid, NULL, 0);
mn->sem = sem_open("sem", O_CREAT | O_EXCL, 0644, 1);
sequence = fopen(argv[2], "r");
subsequence = fopen(argv[3], "r");
// Get file sizes
fseek(sequence, 0L, SEEK_END);
int sz1 = ftell(sequence);
rewind(sequence);
fseek(subsequence, 0L, SEEK_END);
int sz2 = ftell(subsequence);
rewind(subsequence);
// Read files into 2 buffers, which are put into struct mn
buf1 = malloc(sz1);
buf2 = malloc(sz2);
if (sz1 != fread(buf1, 1, sz1, sequence)) {
free(buf1);
}
if (sz2 != fread(buf2, 1, sz2, subsequence)) {
free(buf2);
}
// Initialize struct with necessary values
mn->start_pos = 0;
mn->total_correct = 0;
strncpy(mn->sequence, buf1, sz1);
strncpy(mn->subsequence, buf2, sz2);
fclose(sequence);
fclose(subsequence);
// Begin n forks
for (procNumber = 0; procNumber < processes; procNumber++) {
pid = fork();
if (pid < 0) {
sem_unlink("sem");
sem_close(mn->sem);
printf ("Fork error.\n");
} else if (pid == 0)
break;
}
if (pid != 0) {
while ((pid = waitpid (-1, NULL, 0))){
if (errno == ECHILD)
break;
}
printf("Best match is at position %d with %d/10240 correct.", mn->start_pos, mn->total_correct);
printf ("\nParent: All children have exited.\n");
sem_unlink("sem");
sem_close(mn->sem);
shmdt(mn);
shmctl(shmid, IPC_RMID, 0);
exit(0);
} else {
// this child process will do its 1/nth of the work
sem_wait(mn->sem);
printf ("Child(%d) is in critical section.\n", procNumber);
sleep(1);
int i = 0;
int longest, count = 0;
for (i = 0; i < sz1; i += processes) {
for (int j = 0; j < sz2; j += processes) {
count = 0;
while (mn->sequence[i+j] == mn->subsequence[j]) {
count++;
j++;
}
if (count > longest) {
longest = count;
}
}
}
// If local match is longer than that of the struct, update and unlock
if (longest > mn->total_correct) {
mn->total_correct = count;
mn->start_pos = (i - count);
sem_post(mn->sem);
} else
// If not - unlock and let next process go
sem_post(mn->sem);
exit(0);
}
return 1;
}
The current child code is more or less "pseudocode". I've put it together how it makes sense in my head. (I'm aware this may not be correct or function as intended.) My question is in regard to the child code algorithm near the bottom.
How do I implement this so each child does 1/nth of the work, and finds the longest match, even though it may not match 100%?
Final output would be:
./DNA 6 sequence1 subsequence1
Looking for string using 6 processes...
Best match is at position 123456 with 9876/10240 correct.
Thanks.
I would like to create a program name patch witch recives a FILENAME and a string.In the file there is the string 'allis'.I need to replace each time the string 'allis' appears in the text with the string I recieved as an input.
I need to use only system call and not the standat libary.
This is an example code on how the code should look like(this just example of the structure it is not the mission, the code writes "allis" word instead of "hello world"):
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc , char* argv[], char* envp[])
{
char buf[6];
int fd = open(argv[1],O_WRONLY,0777);
if (fd == -1)
exit(1);
write(fd,"hello world!\n",13);
close(fd);
fd = open(argv[1], O_RDONLY);
if (fd == -1)
exit(1);
read(fd,buf,5);
buf[5]='\0';
close(fd);
fd = open(argv[1],O_WRONLY,0777);
if (fd == -1)
exit(1);
write(fd,"allis",5);
close(fd);
return 0;
}
I need to use the system call lseek but I dont know how I should use it because I dont know where in the text 'allis' is located and what happens if the string i get as an input is bigger than 'allis' I need to move all the text to the right or something because I will override other text.
EDIT:
I wrote a code which check char by char (instead of allis its shira and it replace it with sergay)It actually worked. and than I tried to change the code to work with argv[1] and argv[2] as needed and it didnt work I revert back to the code that originally worked for me and its just doesnt work now!! The problem is that the buf doesnt take 5 character (only 1)
and believe me or not it worked before.
The code :
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#define SYS_WRITE 1
#define STDOUT 1
extern int system_call();
int main(int argc , char* argv[], char* envp[])
{
char buf[5];
int index1=0,index2=0;//the index of the file
int fd1;
int fd = open("file.txt", O_RDONLY);
if (fd == -1)
return 1;
fd1 = open("copytext.txt",O_WRONLY,0777);
if (fd1 == -1)
return 1;
int i =0;
while (fd!=-1){//while there is still info to read
printf("enter the %d loop\n",i);
i++;
if(read(fd,buf,5) == 0 ) break;//read 5 chars from the file //buf[5]='\0';//!! not sure about this
printf("the buffer is: %s\n",buf);
if ((buf[0]=='s') && (buf[1]=='h') && (buf[2]=='i') && (buf[3]=='r') && (buf[4]=='a'))// if (strcmp(buf,"shira")==0)//if we found shira
{
write(fd1,"sergay",6);//replace shira
index2 = index2 + 6;
if(lseek(fd1,index2,SEEK_SET) < 0) break;
index1 = index1 + 5;//size of shira
if(lseek(fd,index1,SEEK_SET) < 0) break;
}
else {//we did not find shira;
write(fd1,buf,1);//write only one
index2++;
if(lseek(fd1,index2,SEEK_SET) < 0) break;
index1++;
if(lseek(fd,index1,SEEK_SET) < 0) break;
}
}
printf("get out of the loop\n");
char buffer[index2];
fd1 = open("copytext.txt", O_RDONLY);
if (fd1 == -1)
return 1;
if(lseek(fd1,0,SEEK_SET) < 0) return 1;
if(read(fd1,buffer,index2) == 0 ) return 1;
fd = open("file.txt",O_WRONLY,0777);
if (fd == -1)
return 1;
if(lseek(fd,0,SEEK_SET) < 0) return 1;
write(fd,buffer,index2);
close(fd);
close(fd1);
return 0;
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
hi i want to Write a command that reads a string from a file using the Linux kernel functions, and then writes the string with the largest length in the second file./ its in c /
But I have a problem with the fact that first, the program takes the string from the input, not from the file that is in the system, and the second is that it displays the output instead of the second file.
I did a lot of work but I could not do it if you can correct the code for me
/* Trivial file copy program using low-level I/O */
#include <fcntl.h>
#include <stdlib.h>
#define BSIZE 16384
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void main()
{
int fin, fout; /* Input and output handles */
char buf[BSIZE];
int count;
if ((fin = open("foo", O_RDONLY)) < 0) {
perror("foo");
exit(1);
}
if ((fout = open("bar", O_WRONLY | O_CREAT, 0644)) < 0) {
perror("bar");
exit(2);
}
while ((count = read(fin, buf, BSIZE)) > 0)
{
char string[100], word[20], max[20], min[20], c;
int i = 0, j = 0, flag = 0;
printf("Enter string: ");
i = 0;
do
{
fflush(stdin);
c = getchar();
string[i++] = c;
} while (c != '\n');
string[i - 1] = '\0';
for (i = 0; i < strlen(string); i++)
{
while (i < strlen(string) && !isspace(string[i]) && isalnum(string[i]))
{
word[j++] = string[i++];
}
if (j != 0)
{
word[j] = '\0';
if (!flag)
{
flag = !flag;
strcpy(max, word);
strcpy(min, word);
}
if (strlen(word) > strlen(max))
{
strcpy(max, word);
}
if (strlen(word) < strlen(min))
{
strcpy(min, word);
}
j = 0;
}
}
printf("The largest word is '%s' and smallest word is '%s' in '%s'.\n", max, min, string);
return 0;
}
write(fout, buf, count);
close(fin);
close(fout);
}
There are several issues here, but you're basically reading from standard input when you shouldn't be. In fact more than half of that code is unnecessary.
I have a small example here, that sticks to the wording of your original question and at least shows what part of the code needs cutting:
/* Find the longest word in a text file (foo) and write that word out to another file (bar) */
/* A word is a group of characters delimited by white space */
/* A word is shorter than 16384 characters */
/* We are trying to use low-level system functions (e.g. open, close, read, write) */
/* instead of standard library functions (e.g. fopen, fclose, fread, fwrite) */
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define BSIZE 16384
/* read a single word from a file */
static int read_word(int fd, char *buf)
{
int i = 0;
char c = 0;
int bytes = read(fd, &c, 1); /* extract a single character */
while (isspace(c) && bytes != 0) /* skip whitespace */
bytes = read(fd, &c, 1);
while (!isspace(c) && bytes != 0) {
buf[i++] = c; /* store character */
bytes = read(fd, &c, 1);
}
return i; /* return number of characters read */
}
int main()
{
int fin = open("foo", O_RDONLY);
if (fin < 0) {
perror("foo");
exit(1);
}
int fout = open("bar", O_WRONLY | O_CREAT, 0644);
if (fout < 0) {
perror("bar");
exit(2);
}
char buf[BSIZE] = {0};
char largest[BSIZE] = {0};
int bytes = 0;
int count = 0;
do {
bytes = read_word(fin, buf); /* read next word */
if (bytes > count) {
strncpy(largest, buf, BSIZE - 1); /* preserve largest word seen so far */
count = bytes;
}
memset(buf, 0, BSIZE);
} while (bytes > 0);
write(fout, largest, count); /* write largest word to file */
close(fin);
close(fout);
printf ("\nLargest word found was %s # %d characters length.\n", largest, count);
return 0;
}
I am currently implementing the Unix HEAD command with C and using only system functions. So far, it works perfectly on files, which have lines with less length than the one that I specified for my buffer:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define LINES_TO_READ 10
#define BUFF_SIZE 4096
int main(int argc, char const *argv[]) {
for (ssize_t i = 1; i < argc; i++) {
const char *filename = argv[i];
int fd = open(filename, O_RDONLY);
if (fd < 0) {
perror("open");
return -1;
}
char ch, buffer[BUFF_SIZE];
size_t index = 0, lines = 1;
ssize_t rresult, wresult;
// Read the file byte by byte
while ((rresult = read(fd, &ch, 1)) != 0) {
if (rresult < 0) {
perror("read");
return -1;
}
// Check if the current character is a new line (the line ends here)
if (ch == '\n') {
buffer[index] = ch;
buffer[index + 1] = '\0';
ch = 0;
index = 0;
// Print the line
wresult = 0;
ssize_t buffer_length = strlen(buffer);
while (wresult != buffer_length) {
ssize_t res = write(STDOUT_FILENO, buffer + wresult, buffer_length - wresult);
if (wresult < 0) {
perror("write");
return -1;
}
wresult += res;
}
// Stop if we read 10 lines already
if (lines == LINES_TO_READ) {
break;
}
lines++;
} else {
buffer[index++] = ch;
}
}
if (close(fd) < 0) {
perror("close");
return -1;
}
}
return 0;
}
And it works on files, which have a line length with less than BUFF_SIZE (as now set, 4096).
How to avoid this and make it work for whatever the line length is?
Don't read one byte at a time. Read a chunk (4096 or 8192 bytes are reasonable sizes, or use PIPE_BUF (from limits.h)) into a buffer. Output each character while counting newlines. If you print enough newlines, terminate. If you reach the end of the buffer and haven't printed enough lines, read more data into the buffer.
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
C programming print a certain amount of bytes to screen
I would like to read partSize amount of bytes from one file, which can be of any type, and print that same exact amount that was read to a new file which already exists. The program I wrote seems to write less than it is suppose to and gives a segmentation fault.
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#define PERMS 0777
#include <errno.h>
int main()
{
int createDescriptor;
int openDescriptorOriginal;
int closeCreateDescriptor;
char fileNameOriginal[15]="picture.jpg";
//char fileNameOriginal[15]="myFile.txt";
//char fileNameNew[15]="NEWFILE.txt";
char fileName[15]="NEWFILE.jpg";
int parts;
int partSize;
parts=2;
int bytesRemaining;
int partNumber;
char BUFFER[512];
int readDescriptor;
int openDescriptor;
if ((openDescriptorOriginal = open(fileNameOriginal, O_RDONLY )) == -1)
{
printf("Error opening %s", fileNameOriginal);
exit(EXIT_FAILURE);
}
struct stat buf;
int r = fstat(openDescriptorOriginal, &buf);
if(r)
{
fprintf(stderr, "error: fstat: %s\n",(char *)strerror(errno));
exit(1);
}
int originalFileSize=buf.st_size;
printf("The file is %d Bytes large.\n",originalFileSize);
partSize=((originalFileSize+parts)-1)/parts;
printf("Each part is %.9f Kilobytes large.\n",(double)partSize/1024 );
partNumber=1;
printf("Part number: %d\n", partNumber);
if ((openDescriptor = open(fileName, O_WRONLY )) == -1)
{
printf("Error creating %s\n", fileName);
exit(EXIT_FAILURE);
}
ssize_t count, total;
total = 0;
char *bufff = BUFFER;
while (partSize) {
count = read(openDescriptorOriginal, bufff, partSize);
if (count < 0) {
// handle error
break;
}
if (count == 0)
break;
bufff += count;
total += count;
partSize -= count;
}
write (openDescriptor, BUFFER, total);
printf("\n");
return 0;
}
Some initial problems:
add the CREAT flag to your open() in case the file isn't there.
partSize should not be adjusted
Take out the line where you adjust partSize and it should work.
int bytesReceived;
.... open files ....
while ((bytesReceived = read(openDescriptorOriginal, BUFFER, sizeof(BUFFER)) > 0) {
if (bytesReceived != write(openDescriptor, BUFFER, bytesReceived) {
printError(...);
}
}