Różnice między wybraną wersją a wersją aktualną.
| Nowa wersja | Poprzednia wersja | ||
|
os_cp:open:solutions [2023/03/28 22:06] jkonczak utworzono |
— (aktualna) | ||
|---|---|---|---|
| Linia 1: | Linia 1: | ||
| - | ~~Exercise.#~~ | ||
| - | <code c> | ||
| - | int main(int argc, char *argv[]){ | ||
| - | return 0; | ||
| - | } | ||
| - | </code> | ||
| - | To compile, one may use any of: | ||
| - | * ''cc prog.c -o prog'' | ||
| - | * ''gcc --std=c17 -Wall --pedantic -g -O2 x.c -o x'' | ||
| - | * ''clang --std=c17 -Wall --pedantic -g -O2 x.c -o x'' | ||
| - | |||
| - | ~~Exercise.#~~ | ||
| - | <code c> | ||
| - | #include <stdio.h> | ||
| - | int main(int argc, char *argv[]){ | ||
| - | printf("Hello.\n"); | ||
| - | return 0; | ||
| - | } | ||
| - | </code> | ||
| - | <code c> | ||
| - | #include <stdio.h> | ||
| - | int main(int argc, char *argv[]){ | ||
| - | fprintf(stdout, "Hello.\n"); | ||
| - | return 0; | ||
| - | } | ||
| - | </code> | ||
| - | <code c> | ||
| - | #include <unistd.h> | ||
| - | int main(int argc, char *argv[]){ | ||
| - | write(STDOUT_FILENO, "Hello.\n", 7); | ||
| - | return 0; | ||
| - | } | ||
| - | </code> | ||
| - | |||
| - | ~~Exercise.#~~ | ||
| - | <code c> | ||
| - | #include <unistd.h> | ||
| - | #include <string.h> | ||
| - | int main(int argc, char *argv[]){ | ||
| - | write(STDOUT_FILENO, argv[1], strlen(argv[1])); | ||
| - | write(STDOUT_FILENO, "\n", 1); | ||
| - | return 0; | ||
| - | } | ||
| - | </code> | ||
| - | |||
| - | ~~Exercise.#~~ | ||
| - | <code c> | ||
| - | #include <unistd.h> | ||
| - | #include <string.h> | ||
| - | int main(int argc, char *argv[]){ | ||
| - | write(STDOUT_FILENO, argv[1]+3, strlen(argv[1])-3); | ||
| - | write(STDOUT_FILENO, "\n", 1); | ||
| - | return 0; | ||
| - | } | ||
| - | </code> | ||
| - | |||
| - | ~~Exercise.#~~ | ||
| - | <code c> | ||
| - | #include <unistd.h> | ||
| - | #include <string.h> | ||
| - | int main(int argc, char *argv[]){ | ||
| - | for(int i = 0; i < argc; ++i){ | ||
| - | write(STDOUT_FILENO, argv[i], strlen(argv[i])); | ||
| - | write(STDOUT_FILENO, "\n", 1); | ||
| - | } | ||
| - | return 0; | ||
| - | } | ||
| - | </code> | ||
| - | or, knowing that the argument array has a [[https://en.wikipedia.org/wiki/Sentinel_value|sentinel]]: | ||
| - | <code c> | ||
| - | #include <unistd.h> | ||
| - | #include <string.h> | ||
| - | int main(int argc, char *argv[]){ | ||
| - | do { | ||
| - | write(STDOUT_FILENO, *argv, strlen(*argv)); | ||
| - | write(STDOUT_FILENO, "\n", 1); | ||
| - | } while(*++argv); | ||
| - | return 0; | ||
| - | } | ||
| - | </code> | ||
| - | |||
| - | ~~Exercise.#~~ | ||
| - | <code c> | ||
| - | #include <unistd.h> | ||
| - | #include <string.h> | ||
| - | int main(int argc, char *argv[]){ | ||
| - | char buffer[256]; | ||
| - | strncpy(buffer, argv[1], 254); | ||
| - | buffer[254] = 0; | ||
| - | strcat(buffer, "\n"); | ||
| - | write(STDOUT_FILENO, buffer, strlen(buffer)); | ||
| - | return 0; | ||
| - | } | ||
| - | </code> | ||
| - | |||
| - | ~~Exercise.#~~ | ||
| - | <code c> | ||
| - | #include <unistd.h> | ||
| - | #include <stdlib.h> | ||
| - | #include <string.h> | ||
| - | int main(int argc, char *argv[]){ | ||
| - | size_t length = strlen(argv[1]); | ||
| - | char *buffer = (char*) malloc(length+1); | ||
| - | memcpy(buffer, argv[1], length); | ||
| - | buffer[length]='\n'; | ||
| - | write(STDOUT_FILENO, buffer, strlen(buffer)); | ||
| - | free(buffer); | ||
| - | return 0; | ||
| - | } | ||
| - | </code> | ||
| - | |||
| - | ~~Exercise.#~~ | ||
| - | <code c> | ||
| - | #include <unistd.h> | ||
| - | #include <ctype.h> | ||
| - | #include <stdlib.h> | ||
| - | #include <string.h> | ||
| - | int main(int argc, char *argv[]){ | ||
| - | size_t length = strlen(argv[1]); | ||
| - | char *buffer = (char*) malloc(length+1); | ||
| - | for(int i = 0; i < length; ++i) | ||
| - | buffer[i] = toupper(argv[1][i]); | ||
| - | buffer[length]='\n'; | ||
| - | write(STDOUT_FILENO, buffer, length+1); | ||
| - | free(buffer); | ||
| - | return 0; | ||
| - | } | ||
| - | </code> | ||
| - | |||
| - | ~~Exercise.#~~ | ||
| - | <code c> | ||
| - | #include <unistd.h> | ||
| - | #include <stdio.h> | ||
| - | #include <string.h> | ||
| - | int main(int argc, char *argv[]){ | ||
| - | char buffer[256]; | ||
| - | scanf("%254[^\n]", buffer); | ||
| - | strcat(buffer, "\n"); | ||
| - | write(STDOUT_FILENO, buffer, strlen(buffer)); | ||
| - | return 0; | ||
| - | } | ||
| - | </code> | ||
| - | <code c> | ||
| - | #include <unistd.h> | ||
| - | #include <stdio.h> | ||
| - | #include <string.h> | ||
| - | int main(int argc, char *argv[]){ | ||
| - | char buffer[256]; | ||
| - | fscanf(stdin, "%254[^\n]", buffer); | ||
| - | strcat(buffer, "\n"); | ||
| - | write(STDOUT_FILENO, buffer, strlen(buffer)); | ||
| - | return 0; | ||
| - | } | ||
| - | </code> | ||
| - | <code c> | ||
| - | #include <unistd.h> | ||
| - | int main(int argc, char *argv[]){ | ||
| - | char buffer[256]; | ||
| - | int length = read(STDIN_FILENO, buffer, 256); | ||
| - | write(STDOUT_FILENO, buffer, length); | ||
| - | return 0; | ||
| - | } | ||
| - | </code> | ||
| - | |||
| - | |||
| - | ~~Exercise.#~~ | ||
| - | <code c> | ||
| - | #include <unistd.h> | ||
| - | #include <stdio.h> | ||
| - | int main(int argc, char *argv[]){ | ||
| - | char buffer[256]; | ||
| - | while(1){ | ||
| - | int length = read(STDIN_FILENO, buffer, 256); | ||
| - | if(length == -1){ | ||
| - | perror(NULL); | ||
| - | return 1; | ||
| - | } | ||
| - | if(length == 0) | ||
| - | break; | ||
| - | write(STDOUT_FILENO, buffer, length); | ||
| - | } | ||
| - | return 0; | ||
| - | } | ||
| - | </code> | ||
| - | |||
| - | ~~Exercise.#~~ | ||
| - | <code c> | ||
| - | #include <unistd.h> | ||
| - | #include <stdio.h> | ||
| - | int readFile(){ | ||
| - | char buffer[256]; | ||
| - | while(1){ | ||
| - | int length = read(STDIN_FILENO, buffer, 256); | ||
| - | if(length == -1){ | ||
| - | perror(NULL); | ||
| - | return 1; | ||
| - | } | ||
| - | if(length == 0) | ||
| - | return 0; | ||
| - | write(STDOUT_FILENO, buffer, length); | ||
| - | } | ||
| - | } | ||
| - | int main(int argc, char *argv[]){ | ||
| - | if(readFile()) | ||
| - | return -1; | ||
| - | lseek(STDIN_FILENO, 0, SEEK_SET); | ||
| - | if(readFile()) | ||
| - | return -1; | ||
| - | return 0; | ||
| - | } | ||
| - | </code> | ||
| - | |||
| - | ~~Exercise.#~~ | ||
| - | <code c> | ||
| - | #include <unistd.h> | ||
| - | #include <stdio.h> | ||
| - | int main(int argc, char *argv[]){ | ||
| - | char buffer[256]; | ||
| - | while(1){ | ||
| - | int length = read(4, buffer, 256); | ||
| - | if(length == -1){ | ||
| - | perror(NULL); | ||
| - | return 1; | ||
| - | } | ||
| - | if(length == 0) | ||
| - | break; | ||
| - | write(STDOUT_FILENO, buffer, length); | ||
| - | } | ||
| - | return 0; | ||
| - | } | ||
| - | </code> | ||
| - | |||
| - | ~~Exercise.#~~ | ||
| - | <code c> | ||
| - | #include <unistd.h> | ||
| - | #include <fcntl.h> | ||
| - | #include <stdio.h> | ||
| - | int main(int argc, char *argv[]){ | ||
| - | int fd = open("/tmp/z", O_RDONLY); | ||
| - | if(fd == -1){ | ||
| - | perror(NULL); | ||
| - | return 1; | ||
| - | } | ||
| - | char buffer[256]; | ||
| - | while(1){ | ||
| - | int length = read(fd, buffer, 256); | ||
| - | if(length == -1){ | ||
| - | perror(NULL); | ||
| - | return 1; | ||
| - | } | ||
| - | if(length == 0) | ||
| - | break; | ||
| - | write(STDOUT_FILENO, buffer, length); | ||
| - | } | ||
| - | close(fd); | ||
| - | return 0; | ||
| - | } | ||
| - | </code> | ||
| - | |||
| - | ~~Exercise.#~~ | ||
| - | <code c> | ||
| - | #include <unistd.h> | ||
| - | #include <fcntl.h> | ||
| - | #include <stdio.h> | ||
| - | int main(int argc, char *argv[]){ | ||
| - | int fd = open(argv[1], O_RDONLY); | ||
| - | if(fd == -1){ | ||
| - | perror(NULL); | ||
| - | return 1; | ||
| - | } | ||
| - | char buffer[256]; | ||
| - | while(1){ | ||
| - | int length = read(fd, buffer, 256); | ||
| - | if(length == -1){ | ||
| - | perror(NULL); | ||
| - | return 1; | ||
| - | } | ||
| - | if(length == 0) | ||
| - | break; | ||
| - | write(STDOUT_FILENO, buffer, length); | ||
| - | } | ||
| - | close(fd); | ||
| - | return 0; | ||
| - | } | ||
| - | </code> | ||
| - | |||
| - | ~~Exercise.#~~ | ||
| - | <code c> | ||
| - | #include <unistd.h> | ||
| - | #include <fcntl.h> | ||
| - | #include <stdio.h> | ||
| - | #include <stdlib.h> | ||
| - | #include <string.h> | ||
| - | |||
| - | int main(int argc, char *argv[]){ | ||
| - | int fd = open(argv[1], O_RDONLY); | ||
| - | if(fd == -1){ | ||
| - | perror(NULL); | ||
| - | return 1; | ||
| - | } | ||
| - | int num = 1; | ||
| - | int printNumber = 1; | ||
| - | while(1){ | ||
| - | char c; | ||
| - | int count = read(fd, &c, 1); | ||
| - | if(count == -1){ | ||
| - | perror(NULL); | ||
| - | return 1; | ||
| - | } | ||
| - | if(count == 0) | ||
| - | break; | ||
| - | if(printNumber){ | ||
| - | char numBuf[16]; | ||
| - | sprintf(numBuf, "%5d ", num++); | ||
| - | write(STDOUT_FILENO, numBuf, strlen(numBuf)); | ||
| - | printNumber=0; | ||
| - | } | ||
| - | write(STDOUT_FILENO, &c, 1); | ||
| - | if(c == '\n') | ||
| - | printNumber=1; | ||
| - | } | ||
| - | close(fd); | ||
| - | return 0; | ||
| - | }</code> | ||
| - | ++++ The program above is intentionally made simple rather than efficient; the program below is more efficient, but has a few more lines. | | ||
| - | <code c> | ||
| - | #include <unistd.h> | ||
| - | #include <fcntl.h> | ||
| - | #include <stdio.h> | ||
| - | #include <string.h> | ||
| - | |||
| - | void checkPrintNl(int *shallPrint, unsigned *number){ | ||
| - | if(!*shallPrint) | ||
| - | return; | ||
| - | char buf[12]; | ||
| - | sprintf(buf, "%5u ", (*number)++); | ||
| - | write(STDOUT_FILENO, buf, strlen(buf)); | ||
| - | *shallPrint=0; | ||
| - | } | ||
| - | |||
| - | int main(int argc, char *argv[]){ | ||
| - | int fd = open(argv[1], O_RDONLY); | ||
| - | if(fd == -1){ | ||
| - | perror(NULL); | ||
| - | return 1; | ||
| - | } | ||
| - | int printLineNum = 1; | ||
| - | unsigned lineNum = 1; | ||
| - | while(1){ | ||
| - | char buf[256]; | ||
| - | int length = read(fd, buf, 256); | ||
| - | if(length == -1){ | ||
| - | perror(NULL); | ||
| - | return 1; | ||
| - | } | ||
| - | if(length == 0) | ||
| - | break; | ||
| - | char *it = buf, *nlPos; | ||
| - | while( (nlPos = memchr(it, '\n', length)) ){ | ||
| - | checkPrintNl(&printLineNum, &lineNum); | ||
| - | int partLen = nlPos+1-it; | ||
| - | write(STDOUT_FILENO, it, partLen); | ||
| - | length -= partLen; | ||
| - | it = nlPos+1; | ||
| - | printLineNum = 1; | ||
| - | } | ||
| - | if(length){ | ||
| - | checkPrintNl(&printLineNum, &lineNum); | ||
| - | write(STDOUT_FILENO, it, length); | ||
| - | } | ||
| - | } | ||
| - | return 0; | ||
| - | } | ||
| - | </code> | ||
| - | ++++ | ||
| - | |||
| - | ~~Exercise.#~~ | ||
| - | <code c> | ||
| - | #include <unistd.h> | ||
| - | #include <fcntl.h> | ||
| - | #include <stdio.h> | ||
| - | #include <stdlib.h> | ||
| - | |||
| - | int main(int argc, char *argv[]){ | ||
| - | ++argv; --argc; // get rid of program name; simplifies array indexes | ||
| - | int *file = malloc(sizeof(int) * argc); | ||
| - | int running = 0; | ||
| - | for(int i = 0; i < argc; ++i){ | ||
| - | file[i] = open(argv[i], O_RDONLY); | ||
| - | if(file[i] == -1) | ||
| - | perror(argv[i]); | ||
| - | else | ||
| - | running = 1; | ||
| - | } | ||
| - | while(running){ | ||
| - | running = 0; | ||
| - | for(int i = 0; i < argc; ++i){ | ||
| - | while(file[i] != -1){ | ||
| - | char c; | ||
| - | int l = read(file[i], &c, 1); | ||
| - | if(l <= 0){ | ||
| - | if(l == -1) | ||
| - | perror(argv[i]); | ||
| - | close(file[i]); | ||
| - | file[i] = -1; | ||
| - | break; | ||
| - | } | ||
| - | if(c == '\n'){ | ||
| - | running = 1; | ||
| - | break; | ||
| - | } | ||
| - | write(STDOUT_FILENO, &c, 1); | ||
| - | } | ||
| - | write(STDOUT_FILENO, (i == argc-1) ? "\n" : "\t", 1); | ||
| - | } | ||
| - | } | ||
| - | free(file); | ||
| - | return 0; | ||
| - | } | ||
| - | </code> | ||
| - | ++++ The program above is intentionally made simple rather than efficient; the program below is more efficient, but has more lines. | | ||
| - | NB: speedup of this program vs the one above is way beyond 100x | ||
| - | <code c> | ||
| - | #include <unistd.h> | ||
| - | #include <fcntl.h> | ||
| - | #include <stdio.h> | ||
| - | #include <string.h> | ||
| - | #include <stdlib.h> | ||
| - | #include <assert.h> | ||
| - | |||
| - | /** A few words of explanation: each 'read' and 'write' call involves | ||
| - | * the operating system. Calling the OS is expensive. Thus, I/O is | ||
| - | * usually buffered. This program buffers both input and output, but | ||
| - | * to buffer output and still use OS API, one has to buffer I/O oneself. | ||
| - | */ | ||
| - | #define BUFSIZE 4096 | ||
| - | |||
| - | // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ OUTPUT BUFFERING ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | ||
| - | |||
| - | struct { //< custom standard output buffer | ||
| - | char b[2*BUFSIZE]; | ||
| - | size_t c; | ||
| - | } outBuf; | ||
| - | |||
| - | void flushOutput(){ //< writes out the standard output buffer | ||
| - | if(outBuf.c != write(STDOUT_FILENO, outBuf.b, outBuf.c)){ | ||
| - | perror("writing to output failed"); | ||
| - | exit(1); | ||
| - | } | ||
| - | outBuf.c = 0; | ||
| - | } | ||
| - | |||
| - | /** adds data to output buffer and outputs if buffer is sufficiently filled | ||
| - | * @warning: this relies on an assumption that count never exceeds BUFSIZE */ | ||
| - | void bufferOutput(char *data, size_t count){ | ||
| - | assert(count <= BUFSIZE); | ||
| - | memcpy(outBuf.b + outBuf.c, data, count); | ||
| - | if((outBuf.c += count) >= BUFSIZE) | ||
| - | flushOutput(); | ||
| - | } | ||
| - | |||
| - | // ~ ~ ~ ~ ~ READING LINES FROM INPUT & BUFFERING INPUT ~ ~ ~ ~ ~ | ||
| - | |||
| - | struct myFile { //< stores state & buffer of a file | ||
| - | char *name; //< used for diagnostics when read returns -1 | ||
| - | int fd; //< once the file ends (or read fails), -1 is put here | ||
| - | char buf[BUFSIZE]; | ||
| - | int pos; //< position where data in buf starts | ||
| - | int count; //< number of bytes in but from pos to end of data | ||
| - | }; | ||
| - | |||
| - | /// reads from file to buffer, @returns 0 if any data was read, else returns 1 | ||
| - | int readChunk(struct myFile *f){ | ||
| - | f->pos = 0; | ||
| - | f->count = read(f->fd, f->buf, BUFSIZE); | ||
| - | if(f->count<=0){ | ||
| - | if(f->count == -1) | ||
| - | perror(f->name); | ||
| - | close(f->fd); | ||
| - | f->fd = -1; | ||
| - | return 1; | ||
| - | } | ||
| - | return 0; | ||
| - | } | ||
| - | |||
| - | /** reads and outputs a line from file, | ||
| - | * @returns 0 if there is any outstanding data in file, else returns 1 */ | ||
| - | int readAndOutputLine(struct myFile *f){ | ||
| - | while(1){ | ||
| - | if(f->fd == -1) | ||
| - | return 1; | ||
| - | if(f->count == 0) | ||
| - | if(readChunk(f)) | ||
| - | return 1; | ||
| - | char *nlPos, *startPos = f->buf+f->pos; | ||
| - | if( (nlPos = memchr(startPos, '\n', f->count)) ){ | ||
| - | int partLen = nlPos-startPos; | ||
| - | bufferOutput(startPos, partLen); | ||
| - | f->pos += partLen+1; | ||
| - | f->count -= partLen+1; | ||
| - | if(f->count) | ||
| - | return 0; | ||
| - | return readChunk(f); | ||
| - | } | ||
| - | bufferOutput(startPos, f->count); | ||
| - | f->count = 0; | ||
| - | } | ||
| - | } | ||
| - | |||
| - | // ~ ~ ~ ~ ~ OPENING FILES, LOOPING THROUGH LINES ~ ~ ~ ~ ~ | ||
| - | |||
| - | int main(int argc, char *argv[]){ | ||
| - | ++argv; --argc; // get rid of program name; simplifies array indexes | ||
| - | struct myFile *myFiles = malloc(sizeof(myFiles) * argc); | ||
| - | int allFilesEof = 1; | ||
| - | for(int i = 0 ; i < argc; ++i){ | ||
| - | myFiles[i].fd = open(argv[i], O_RDONLY); | ||
| - | if(myFiles[i].fd == -1) | ||
| - | perror(argv[i]); | ||
| - | else { | ||
| - | myFiles[i].name = argv[i]; | ||
| - | allFilesEof &= readChunk(myFiles+i); | ||
| - | } | ||
| - | } | ||
| - | while(!allFilesEof){ | ||
| - | allFilesEof = readAndOutputLine(myFiles); | ||
| - | for(int i = 1 ; i < argc; ++i){ | ||
| - | bufferOutput("\t", 1); | ||
| - | allFilesEof &= readAndOutputLine(myFiles+i); | ||
| - | } | ||
| - | bufferOutput("\n", 1); | ||
| - | } | ||
| - | free(myFiles); | ||
| - | flushOutput(); | ||
| - | return 0; | ||
| - | } | ||
| - | </code> | ||
| - | ++++ | ||
| - | |||
| - | |||
| - | ~~META: | ||
| - | language = en | ||
| - | ~~ | ||