Dydaktyka:
FeedbackTo jest stara wersja strony!
Exercise 1
int main(int argc, char *argv[]){ return 0; }
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 2
#include <stdio.h> int main(int argc, char *argv[]){ printf("Hello.\n"); return 0; }
#include <stdio.h> int main(int argc, char *argv[]){ fprintf(stdout, "Hello.\n"); return 0; }
#include <unistd.h> int main(int argc, char *argv[]){ write(STDOUT_FILENO, "Hello.\n", 7); return 0; }
Exercise 3
#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; }
Exercise 4
#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; }
Exercise 5
#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; }
or, knowing that the argument array has a sentinel:
#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; }
Exercise 6
#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; }
Exercise 7
#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; }
Exercise 8
#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; }
Exercise 9
#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; }
#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; }
#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; }
Exercise 10
#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; }
Exercise 11
#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; }
Exercise 12
#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; }
Exercise 13
#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; }
Exercise 14
#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; }
Exercise 15
#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; }
#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; }
Exercise 16
#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; }
NB: speedup of this program vs the one above is way beyond 100x
#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; }