Lab2 Array 程序除了语法错误以外竟然一次跑通,写的时候很崩溃因为牵扯到 ASCII 码,不是很熟,但是没想到 oj 竟然一次过了,真的巨激动!
小错误:忘记设置返回值,等号判断符写错,打印漏引号
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 #include <cs50.h> #include <ctype.h> #include <stdio.h> #include <string.h> int POINTS[] = {1 , 3 , 3 , 2 , 1 , 4 , 2 , 4 , 1 , 8 , 5 , 1 , 3 , 1 , 1 , 3 , 10 , 1 , 1 , 1 , 1 , 4 , 4 , 8 , 4 , 10 };int compute_score (string word) ;int main (void ) { string word1 = get_string("Player 1: " ); string word2 = get_string("Player 2: " ); int score1 = compute_score(word1); int score2 = compute_score(word2); if (score1 > score2) { printf ("Player 1 wins!" ); } else if (score1 < score2) { printf ("Player 2 wins!" ); } else if (score1 == score2) { printf ("Tie!" ); } }int compute_score (string word) { int n = strlen (word); int m = 0 ; int score = 0 ; for (int i = 0 ; i <= n; i++) { if (word[i] >= 65 && word[i] <= 90 ) { m = word[i] - 65 ; score = score + POINTS[m]; } else if (word[i] >= 97 && word[i] <= 122 ) { m = word[i] - 97 ; score = score + POINTS[m]; } } return score; }
Problem Sets 但是问题集就不轻松了,不过也不难
文本难度判断 Readibity 需要数出一段文本的字母,单词,句子数量。计算可读性指数,四舍五入,不考虑例如 Mr.之类的句点的用法,设置初始值和输入
1 2 3 4 5 6 7 8 9 10 11 #include <cs50.h> #include <stdio.h> int main (void ) { string text = get_string("Text:" ); int letter = 0 ; int word = 1 ; int sent = 0 ; int index = 0 ; }
先看数字母,可以在 while 循环中运行,C 语言字符串型在末尾会自行添加结束标识符\0
,可以基于此作为循环条件,单词数需要在末尾加 1,因为若 word 从 0 开始计数,利用空字符检测 word 数的方法会在句子末尾\0
处失效,漏掉最后一个 word。循环代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 { int i = 0 ; while (text[i] != '\0' ) { if ((text[i] >= 65 && text[i] <= 90 ) || (text[i] >= 97 && text[i] <= 122 )) { letter++; } else if (text[i] == ' ' ) { word++; } else if ((text[i] == 33 ) || (text[i] == 46 ) || (text[i] == 63 )) { sent++; } i++; } }
此后是可读性指数计算,计算过程考虑小数,并需要四舍五入,引入delat
参数计算浮点数与其整数部分的差值,若大于 0.5 则进一,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 { float L = (float ) letter / word * 100 ; float S = (float ) sent / word * 100 ; float in = 0.0588 * L - 0.296 * S - 15.8 ; index = (float ) 0.0588 * L - 0.296 * S - 15.8 ; float delat = in - (float ) index; if (index < 1 ) { printf ("Before Grade 1\n" ); } else if (index > 16 ) { printf ("Grade 16+\n" ); } else if (delat >= 0.5 ) { printf ("Grade %i\n" , index + 1 ); } else if (delat < 0.5 ) { printf ("Grade %i\n" , index); } }
完成
注意:if 条件语句对 or 的表示与使用需要管道符与条件括号
选做 #3 substitution 用户打开程序同时输入密钥,即 26 个字母打乱,得到的新顺序的字母依次继承 ABCD……的意思
程序内用户输入明文,打印密文
思路 假设一个 key,明文为 hello,则找 key 中第 7 位对应的字母,不换行打印循环到\0
错误预防 key 必须是 26 个字母,我们只能对字母加密,明文与密文大小写相同
首先,读取 key,key 的位置在argv[1]
,获取这个字符串内的值即argv[1][i]
读取明文的每一个字母,其字母所在位置指向 key 的对应字母,依次输出,同时考虑大小写,可以使用ctype.h
库进行大小写转换,虽然手写也不难就是了。
明文每个字母有对应的 ASCII 码,将他们大小写统一再剪掉一个常数,就能得到 A-Z 的顺序 0-25,用这个指数去读取 key,打印结果时再将大小写还原
或者,使用 if 对大小写分开操作似乎更为简便,标点符号正常打印,末尾换行。
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 string ori = get_string("plaintext:" );printf ("ciphertext: " );int i = 0 ;int n = 0 ;int m = strlen (ori);do { if (ori[i] >= 97 && ori[i] <= 122 ) { n = ori[i] - 97 ; printf ("%c" , tolower (argv[1 ][n])); } else if (ori[i] >= 65 && ori[i] <= 90 ) { n = ori[i] - 65 ; printf ("%c" , toupper (argv[1 ][n])); } else { printf ("%c" , ori[i]); } if (i == m - 1 ) { printf ("\n" ); } i++; }while (i <= m);
另外,针对错误输入要有反馈,若 key 长度不等于 26(string
库),返回什么;其他格式错误返回什么
比如:传入参数数量不等于一,给出格式提示,key 长度不对,给出长度提示,两种错误同样有优先级
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include <cs50.h> #include <stdio.h> #include <string.h> int main (int argc, string argv[]) { if (argc != 1 ) { printf ("Usage: ./substitution key" ); return 1 ; } else if (strlen (argv[1 ]) != 26 ) { printf ("Key must contain 26 characters." ); return 1 ; } }
注意,key 判断语句应该最先执行
主体的完成很简单,但是 debug 相当痛苦,key 中不能有重复的字符,且不能出现字母以外的符号
排除重复可以这样写,创建一个 26 位的数组,遇到一个字母就在对应位置+1,将小写统一为大写,大于 1 即有重复,写在一开始的 key 检测部分
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 int alphabeta[26 ];int index = 0 ;for (int i = 0 ;i <= 26 ;i++) { if (argv[1 ][i] < 65 || (argv[1 ][i] > 90 && argv[1 ][i] < 97 ) || argv[1 ][i]>122 ) { return 1 ; } alphabeta[i] = 0 ; if (argv[1 ][i] >= 65 && argv[1 ][i] <= 90 ) { index = argv[1 ][i] - 65 ; alphabeta[index]++; } else if (argv[1 ][i] >= 97 && argv[1 ][i] <= 122 ) { argv[1 ][i] = toupper (argv[1 ][i]); index = argv[1 ][i] - 65 ; alphabeta[index]++; } if (alphabeta[i] > 1 ) { return 1 ; } }
提交一下
WTF!下面的修好了上面的有错了!?
给每个 return 1 写个输出看一下
1 2 3 4 5 if (argv[1 ][i] < 65 || (argv[1 ][i] > 90 && argv[1 ][i] < 97 ) || argv[1 ][i]>122 ) { printf ("the %d char %c is not ABC." ,i,argv[1 ][i]); return 1 ; }
在此次返回了the 26 char is not ABC.
数组从 0 计数,i 到 26 时自然为空,将 i 的上限改为 25,提交评测机报错
嗯?还有高手!?
上次正确的部分这次又错了[吐血]
问问 ddb
[code]为什么不起作用
ddb 看起来你正在尝试检查 argv[1]中的字符是否有重复。你的代码中有一些可能的问题。
首先,你的 alphabeta 数组的大小应该是 26,而不是 25,因为英文字母有 26 个。
其次,你在检查 alphabeta[i]是否大于 1 时,你应该检查的是 alphabeta[index],因为 index 是你实际更新的数组索引。
最后,你在将小写字母转换为大写字母后,应该再次检查 alphabeta[index]是否大于 1,因为在转换后,可能会有新的重复字母出现。
希望这些建议能帮助你解决问题。
哦~数组大小就是 26
哦~~~index 写成 i 了
提交评测机
过~~~啦!!!!
完整源代码 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 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 #include <cs50.h> #include <ctype.h> #include <stdio.h> #include <string.h> int main (int argc, string argv[]) { if (argc != 2 ) { printf ("Usage: ./substitution key" ); return 1 ; } else if (strlen (argv[1 ]) != 26 ) { printf ("Key must contain 26 characters." ); return 1 ; } int alphabeta[26 ]; int index = 0 ; for (int i = 0 ; i < 26 ; i++) { if (argv[1 ][i] < 65 || (argv[1 ][i] > 90 && argv[1 ][i] < 97 ) || argv[1 ][i] > 122 ) { return 1 ; } alphabeta[i] = 0 ; if (argv[1 ][i] >= 65 && argv[1 ][i] <= 90 ) { index = argv[1 ][i] - 65 ; alphabeta[index]++; } else if (argv[1 ][i] >= 97 && argv[1 ][i] <= 122 ) { argv[1 ][i] = toupper (argv[1 ][i]); index = argv[1 ][i] - 65 ; alphabeta[index]++; } if (alphabeta[index] > 1 ) { return 1 ; } } string ori = get_string("plaintext:" ); printf ("ciphertext: " ); int i = 0 ; int n = 0 ; int m = strlen (ori); do { if (ori[i] >= 97 && ori[i] <= 122 ) { n = ori[i] - 97 ; printf ("%c" , tolower (argv[1 ][n])); } else if (ori[i] >= 65 && ori[i] <= 90 ) { n = ori[i] - 65 ; printf ("%c" , toupper (argv[1 ][n])); } else { printf ("%c" , ori[i]); } if (i == m - 1 ) { printf ("\n" ); } i++; } while (i <= m); return 0 ; }