C语言程序设计第二版课后习题--第五章

部分答案参考了官方题解和网上的答案,仅供参考,可能也有部分bug未发现或解决。 exercise5-1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 int getint(int *pn) { int c, sign; while (isspace(c = getch())) /* skip white space */ ; if (!isdigit(c) && c != EOF && c != '+' && c != '-') { ungetch(c); /* it is not a number */ return 0; } sign = (c == '-') ?...

October 12, 2024 · 27 min · 5733 words · Jagger

C语言程序设计第二版课后习题--第四章

部分答案参考了官方题解和网上的答案,仅供参考,可能也有部分bug未发现或解决。代码在gitee上面。 exercise4-1 编写函数 strindex(s, t),它返回字符串 t 在 s 中最右边出现的位置。如果 s 中不包含 t,则返回-1。 代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 void getLine(char s[]) { int c, i = 0; while ((c = getchar()) != EOF && c != '\n') s[i++] = c; } int strindex(char s[], char t[]) { int i, j, k; int lens = strlen(s), lent = strlen(t); for (i = lens - 1; i >= 0; i--) { for (j = lent - 1, k = i; j >= 0 && k >= 0 && s[k] == t[j]; j--, k--); if (j < 0) return k + 1; } return -1; } int main() { char s[MAXLEN] = {0}; char t[MAXLEN] = {0}; printf("Please input the string s: \n"); getLine(s); printf("Please input the string t: \n"); getLine(t); printf("The rightmost position of '%s' in '%s' is: %d\n", t, s, strindex(s, t)); return 0; } 运行:...

October 10, 2024 · 10 min · 1975 words · Jagger

C语言程序设计第二版课后习题--第三章

部分答案参考了网络上的答案和官方题解。代码在gitee上面。 exercise3-1 在上面有关折半查找的例子中,while 循环语句内共执行了两次测试,其实只要一次就足够(代价是将更多的测试在循环外执行)。重写该函数,使得在循环内部只执行一次测试。比较两种版本函数的运行时间。 代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 #include <stdio.h> #include <time....

October 8, 2024 · 7 min · 1442 words · Jagger

C语言程序设计第二版课后习题--第二章

部分答案参考了官方题解和网上的答案,仅供参考,可能也有部分bug未发现或解决。代码在gitee上面。 exercise2-1 编写一个程序以确定分别由 signed 及 unsigned 限定的 char、short、int 与 long 类型变量的取值范围。采用打印标准头文件中的相应值以及直接计算两种方式实现。后一种方法的实现较困难一些,因为要确定各种浮点类型的取值范围。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #include <stdio.h> #include <limits.h> int main() { printf("Size of char %d\n", CHAR_BIT); printf("Size of char max %d\n", CHAR_MAX); printf("Size of char min %d\n", CHAR_MIN); printf("Size of short min %d\n", SHRT_MIN); printf("Size of short max %d\n", SHRT_MAX); printf("Size of int min %d\n", INT_MIN); printf("Size of int max %d\n", INT_MAX); printf("Size of long min %ld\n", LONG_MIN); printf("Size of long max %ld\n", LONG_MAX); printf("Size of unsigned char %u\n", UCHAR_MAX); printf("Size of unsigned short %u\n", USHRT_MAX); printf("Size of unsigned int %u\n", UINT_MAX); printf("Size of unsigned long %lu\n", ULONG_MAX); return 0; } 1 2 3 4 5 6 7 8 9 10 11 12 13 Size of char 8 Size of char max 127 Size of char min -128 Size of short min -32768 Size of short max 32767 Size of int min -2147483648 Size of int max 2147483647 Size of long min -9223372036854775808 Size of long max 9223372036854775807 Size of unsigned char 255 Size of unsigned short 65535 Size of unsigned int 4294967295 Size of unsigned long 18446744073709551615 exercise2-2 在不使用运算符&&或||的条件下编写一个与上面的 for 循环语句等价的循环语句。...

September 29, 2024 · 7 min · 1368 words · Jagger

C语言程序设计第二版课后习题--第一章

部分答案参考了官方题解和网上的答案,仅供参考,可能也有部分bug未发现或解决。代码在gitee上面。 exercise1-1 在你自己的系统中运行“hello, world”程序。再有意去掉程序中的部分内容,看看会得到什么出错信息。 1 2 3 main() { printf("hello world!"); } 除去头文件 不报错且能运行,但是会有警告warning: implicit declaration of function ‘printf’ [-Wimplicit-function-declaration]。 除去返回类型 不报错且能运行,但是会有警告warning: return type defaults to ‘int’ [-Wimplicit-int]。 exercise1-2 做个实验,当 printf 函数的参数字符串中包含\c(其中 c 是上面的转义字符序列中未曾列出的某一个字符)时,观察一下会出现什么情况。 1 2 3 4 5 6 7 8 9 10 int main(void) { printf("Experiment\f to find out what\f happens when \fprintf 's argument string contains \\c\n"); printf("---------\n"); printf("Experiment\v to find out what \vhappens when printf 's \vargument string contains \\c\n"); printf("---------\n"); printf("Experiment\r to find out what \rhappens when printf 's \rargument string contains \\c\n"); printf("---------\n"); return 0; } 1 2 3 4 5 6 7 8 9 10 11 12 Experiment to find out what happens when printf 's argument string contains \c --------- Experiment to find out what happens when printf 's argument string contains \c --------- argument string contains \c --------- exercise1-3 修改温度转换程序,使之能在转换表的顶部打印一个标题...

September 28, 2024 · 16 min · 3345 words · Jagger

SSH密钥登陆

阿里云 尝试使用windows客户端登录阿里云服务器,参考了10分钟手把手教你通过SSH,使用密钥/账号远程登录Linux服务器(Windows/macOS) 客户端生成密钥 进入到C:\Users\用户名\.ssh目录下,若没有公钥和私钥文件,则进行生成。 执行ssh-keygen命令,之后一路回车,然后在该目录下会出现ida_rsa和ida_rsa.pub两个文件,分别存放私钥和公钥。 部署公钥 使用密码登录服务器,在用户目录下进入到.ssh文件夹,创建或编辑authorized_keys文件,将上一步获得的公钥内容复制并追加到该文件中。 中科大vlab Vlab实验中心,参考帮助文档 下载私钥 进入到管理界面,下载私钥vlab-vm9164.pem。 本地配置 将该私钥文件放置到本地C:\Users\用户名\.ssh文件夹之下,并重命名为vlab.pem。 然后即可以在 cmd 中使用ssh -i ~/.ssh/vlab.pem ubuntu@vlab.ustc.edu.cn来登录到远程主机。 配置文件 如果需要使用vscode来进行操作,则可以使用SSH配置文件。进入到C:\Users\用户名\.ssh文件夹之下,创建或编辑config文件。然后最好使用 vscode 打开该文件并编辑,追加以下内容: 1 2 3 4 Host vlab HostName vlab.ustc.edu.cn User ubuntu IdentityFile ~/.ssh/vlab.pem 之后在vscode中就可以方便地进行连接了。

September 8, 2024 · 1 min · 36 words · Jagger

硬件产生的信号

TLPI 22.4:处理由硬件产生的信号 代码(为网站上获取) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 #define _GNU_SOURCE /* Get strsignal() declaration from <string....

September 7, 2024 · 2 min · 380 words · Jagger

信号处理函数中调用不可重入的函数

TLPI 21.1.2: 可重入函数和异步信号安全函数 代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #define _XOPEN_SOURCE 600 #include <unistd.h> #include <signal.h> #include <string.h> #include <crypt.h> #include "tlpi_hdr.h" static char *str2; static int handled = 0; // 设置处理器函数,一旦遇上SIGINT,便对str2进行加密 static void handler(int sig) { crypt(str2, "xx"); handled++; } int main(int argc, char *argv[]) { char *cr1; int callNum, mismatch; struct sigaction sa; if (argc !...

August 1, 2024 · 1 min · 202 words · Jagger

在备选栈中处理信号

TLPI 21.3:在备选栈中处理信号:sigaltstack() 代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 static void sigsegvHandler(int sig) { int x; // 捕捉信号,并通过局部变量的位置来大致判断为当前函数所分配的空间处于什么位置 printf("Caught signal %d (%s)\n", sig, strsignal(sig)); printf("Top of handler stack near %10p\n", (void *)&x); // fflush(NULL)的作用是在程序异常终止前确保所有标准输出缓冲区的数据都被写入到相应的输出设备。 fflush(NULL); _exit(EXIT_FAILURE); } static void overflowStack(int callNum) { char a[100000]; // 此类分配数组方式为栈上分配 printf("Call %4d - top of stack near %10p\n", callNum, &a[0]); overflowStack(callNum + 1); // 无限递归调用,不断在栈上分配空间,每次分配100000字节以上 } int main(int argc, char *argv[]) { stack_t sigstack; struct sigaction sa; int j; printf("Top of standard stack is near %10p\n", (void *)&j); // 分配备用栈并通知内核 // 在堆当中分配备用栈 sigstack....

July 31, 2024 · 2 min · 287 words · Jagger

处理SIGCHLD信号

处理SIGCHLD信号 1 2 3 4 5 6 7 8 9 10 11 12 void sig_chld(int signo) { pid_t pid; int stat; // wait()是为了清理僵死进程 // pid = wait(&stat); // printf("child %d terminated\n", pid); while ((pid = waitpid(-1, &stat, WNOHANG)) > 0) printf("child %d terminated\n", pid); return; } wait版本行不通的原因 若服务器和客户端在同一主机上,则该信号处理函数只执行过一次(根据UNP的描述是这样的,但是本人实测,信号处理器函数执行了两次)。 但是如果我们在不同的主机上运行客户和服务器,那么信号处理器函数一般执行两次:一次是由第一个产生的信号引起的,由于另外4个信号在信号处理函数第一次执行时发生,因为该处理函数仅仅再被调用一次,从而留下3个僵死进程。 不过有的时候,根据FIN到达主机的时机,信号处理函数可能会执行3次甚至4次 根据本人猜想,如果在相同主机测试,由于没有网络数据传播时延的影响,本机的客户端所有五个FIN都几乎在同一时间传递给服务器, 从而使得服务器的5个子进程基本在同一时刻终止,从而5个SIGCHLD在同一时刻发送给父进程,都在第一个信号处理函数执行之前发生, 而Unix信号一般是不排队的(这里详见TLPI对应的小节),因此信号处理函数只执行一次。 但是如果在不同主机测试,由于网络数据传播,各个FIN到达服务器的时间差较大一些,导致FIN以不可忽略的时差到达服务器。 例如在处理第一个SIGCHLD信号时,其他FIN才到达,从而引起信号处理函数执行多次。 1 2 3 4 5 6 7 ➜ bin git:(main) ✗ ./TCPSERV03 & [1] 65001 ➜ bin git:(main) ✗ ....

July 31, 2024 · 2 min · 227 words · Jagger