2.5 BC38 变种水仙花
描述:变种水仙花数 - Lily Number:把任意的数字,从中间拆分成两个数字,比如1461 可以拆分成(1和461),(14和61),(146和1),如果所有拆分后的乘积之和等于自身,则是一个Lily Number。例如:655 = 6 * 55 + 65 * 5;1461 = 1*461 + 14*61 + 146*1求出 5位数中的所有 Lily Number。输入描述:无 输出描述:一行,5位数中的所有 Lily Number,每两个数之间间隔一个空格。
1. #include <stdio.h> 2. #include <math.h> 3. int main() 4. { 5. // 12345 12345/10 * 12345%10 6. //12345/100 * 12345%100 7. 8. int i = 0; 9. for (i = 10000; i < 99999; i++) 10. { 11. int j = 0; 12. int sum = 0; 13. for (j = 1; j <= 4; j++) 14. { 15. int m = i / pow(10, j); 16. int n = i % (int)pow(10, j); 17. sum = sum + m * n; 18. } 19. if (i == sum) 20. { 21. printf("%d ", i); 22. } 23. } 24. return 0; 25. }
知识点:(1)%的两边的数字,必须是整形(2)pow返回的值为double类型的
2.6一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。编写一个函数找出这两个只出现一次的数字。例如:有数组的元素是:1,2,3,4,5,1,2,3,4,6;只有5和6只出现1次,要找出5和6.
1. #include <stdio.h> 2. //进行分组:只出现一次的两个数字分到两个分组中,一组一个 3. // 如何进行分组:没有进行分组的时候,组内数字进行异或出现的结果,结果是1的位置说明,两个数字是不同的,按照这个位置的数字是1还是0,就可以将这两个数字分到不同的组中 4. //每个组都满足,只有一个数字出现一次,其他数字都是成对出现的,这样每一个组的数字进行异或,那么结果就是只出现一次的那个数字 5. int main() 6. { 7. int arr[] = { 1, 2, 3, 4, 5, 1, 2, 3, 4, 6 }; 8. //0异或任何数还是等于任何数 9. //1.先数组内进行异或 10. int ret = 0; 11. int sz = sizeof(arr) / sizeof(int); 12. int i = 0; 13. for (i = 0; i < sz; i++) 14. { 15. ret = ret ^ arr[i]; 16. } 17. //计算ret的二进制中第几位是1 18. int pos = 0; 19. for (i = 0; i < 32; i++) 20. { 21. if (((ret >> 1) & 1) == 1) 22. { 23. pos = i; 24. break; 25. } 26. } 27. //3.按照pos位的0或者1进行分组 28. int m = 0; 29. int n = 0; 30. for (i = 0; i < sz; i++) 31. { 32. if (((arr[i] >> pos) & 1) == 1) 33. { 34. m = m ^ arr[i]; 35. } 36. else 37. { 38. n = n ^ arr[i]; 39. } 40. } 41. printf("%d %d\n", m, n); 42. return 0; 43. }
2.7 模拟实现atoi
1. #include <stdio.h> 2. #include <stdlib.h> 3. #include <assert.h> 4. #include <ctype.h> 5. //atoi a to i 头文件是<stdlib.h> 6. //把字符串转换为整形 7. //'1' -'0' = 1 字符1减去字符0等于1;'2' - '0' = 2 8. //比如,字符串"12" 0*10+1=1; 1*10+2=12; 9. //比如“123” 0*10+1=1; 1*10+2=12 12*10+3=123 10. //空指针 空字符串 正负 非数字字符 超大数字(超过int整形范围的数字)空白字符 11. enum State //枚举 12. { 13. INVALID,//valid 合法的 14. VALID 15. }; 16. enum State status = INVALID; 17. //正常的情况只有一种,非法的情况有许多,所以这里直接写INVALID 18. int my_atoi(const char* str) 19. { 20. assert(str); 21. //空字符串的问题 22. if (*str == '\0') 23. return 0;//这里的0,就是非法0,的0 24. //空白字符,跳过空白字符,只打印空白字符后面的数字字符串即可 25. while (isspace(*str))//isspace可以判断是否为空白字符,是的话返回真,头文件为ctype.h 26. { 27. str++; 28. } 29. 30. //+- 31. int flag = 1;//如果没有正负号的话,就是正数,所以在这里默认是1 32. if (*str == '+') 33. { 34. flag = 1; 35. str++; 36. } 37. else if (*str == '-') 38. { 39. flag = -1; 40. str++; 41. } 42. //遍历字符串,判断是否有非数字字符 43. long long n = 0;//打印的shuzi//可以判断出超大字符 44. while (isdigit(*str)) 45. { 46. n = (n * 10 )+ flag*(*str - '0'); 47. if (n > INT_MAX || n < INT_MIN)//INT_MAX和INT_MIN分别是整形的最大值和最小值 48. { 49. return 0; 50. } 51. str++; 52. } 53. if (*str == '\0') 54. { 55. //合法返回 56. status = VALID; 57. return (int)n; 58. } 59. return (int)n; 60. } 61. 62. 63. int main() 64. { 65. int ret = my_atoi(" 123a"); 66. if (status == VALID) 67. printf("%d\n", ret); 68. else 69. printf("非法返回\n"); 70. return 0; 71. }
三 文件
3.1 知识点
(1)文件名中有一些禁止使用的字符
(2)getchar也是适用于标准输入流的字符输入函数(即从键盘中获取)
(3)return 0;结束所在函数的程序,exit(0);结束整个程序
(4)scanf和printf是针对标准输入、输出流的格式化输入、输出语句。
(5)文件名可以不包含后缀名。
(6)文件的后缀名决定了一个文件的默认打开方式
四 程序环境和预处理
4.1 知识点
(1)链接可以发现被调用的函数未定义(链接的时候,多个目标文件进行链接的时候会通过符号表,查看来自外部的符号是否真实存在)
(2)编译:将预处理完的文件逐一进行一系列词法分析、语法分析、语义分析及优化后,产生相应的汇编代码文件。编译是针对单个文件编译的,只校验本文件的语法是否有问题,不负责寻找实体。
链接:通过链接器将一个个目标文件(或许还会有库文件)链接在一起生成一个完整的可执行程序。 链接程序的主要工作就是将有关的目标文件彼此相连接,也就是将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,使得所有的这些目标文件成为一个能够被操作系统装入执行的统一整体。在此过程中会发现被调用的函数未被定义。需要注意的是,链接阶段只会链接调用了的函数/全局变量,如果存在一个不存在实体的声明(函数声明、全局变量的外部声明),但没有被调用,依然是可以正常编译执行的。
(3)避免在头文件中定义变量,引用文件的时候,会导致变量的重复定义
4.2 写一个宏,可以将一个整数的二进制位的奇数位和偶数位交换。
1. #include <stdio.h> 2. //1011 奇数位拿出来,偶数位置0 0001(A) & 01 3. // 偶数位拿出来,奇数位置0, 1010 (B) &10 4. // 1011=0001+1010, 5. //因为奇数位和偶数位互换,则A向左移动一位0010,B向右移动一位0101,在进行相加即可0111 6. #define SWAP(x) (((x&0x55555555)<<1) + (x&0xaaaaaaaa)>>1) 7. 8. 9. int main() 10. { 11. int a = 10; 12. printf("%d\n", SWAP(a)); 13. return 0; 14. }
4.3 写一个宏,计算结构体中某变量相对于首地址的偏移,并给出说明。考察:offsetof
宏的实现
1. #include <stdio.h> 2. #define OFFSETOF(s_name, m_name) (int)&(((s_name*)0)->m_name) 3. // (s_name*)0假设结构体的地址为0, s->a 找到的是假设的成员,& 此时假设成员的地址就是偏移量 4. struct S 5. { 6. char a; 7. int b; 8. double c; 9. }; 10. 11. int main() 12. { 13. struct S s = { 0 }; 14. printf("%d\n", OFFSETOF(struct S, a)); 15. printf("%d\n", OFFSETOF(struct S, b)); 16. printf("%d\n", OFFSETOF(struct S, c)); 17. return 0; 18. }
(1)第一个位置的偏移量为0(单位字节)
(2)offsetof(结构体类型,结构体成员名)
(3)offsetof的头文件是<stddef.h>
五 练习题
5.1 知识点
(1)unsigned 的数值大于等于0;j = 0;unsigned char i = 7;for (; i > 0; i-=3){++j};那么这个for循环,只有值等于0的时候,才可以停止。j = 173;173次
(2)unsigned char a = 10;a++;首先10是一个整形,它是32位,但是由于放到char类型中,所以就发生截断,0000 1010;a++,因为是表达式计算,所以就会发生整形提升(所以只有计算的时候,才会注意到是unsigned还是signed ),经过计算后,还是一个32位,但是由于a是char类型的,所以又发生截断。就是0000 1011。(unsigned整形提升的时候用,char 截断的时候需要)
(3)C++ const修饰的变量彻底成为常量,C语言中是常变量
(4)野指针是指未分配或者已经释放的内存地址。
5.2 代码运行结果,输入1abcedf2df<回车>输出结果
1. #include<stdio.h> 2. int main() 3. { 4. char a = 0, ch; 5. while ((ch = getchar()) != '\n') 6. { 7. if (a % 2 != 0 && (ch >= 'a' && ch <= 'z')) 8. ch = ch - 'a' + 'A'; 9. a++; 10. putchar(ch); 11. } 12. printf("\n"); 13. }
知识点:(1)‘a’的ASCII值是97,'A'的ASCII值是65(2)char小写字母减去32,就是小写字母对应的大写字母。(-‘a’+'A'为-32)
运行结果:1AbCeDf2dF
5.3 Fibonacci数列是这样定义的:F(0) = 0;F(1) = 1;for each i>=2 F[i] = F[i-1] + F[i - 2],因此,Fibnonacci数列就形如:0,1,1,2,3,5,8,13,…在Fibonacci数列中的数我们称之为Fibnoacci数。给你一个N,你想让其成为一个变成一个Fibnacci数,每一步你可以把当前数字变为X-1或者X+1,现在给你一个数N,求最少需要多少步可以变为Fibonacci数
1. #include <stdio.h> 2. 3. int main() 4. { 5. int a = 0; 6. int b = 1; 7. int c = 0; 8. c = a + b; 9. int n = 0; 10. int d = 0; 11. scanf("%d", &n); 12. while (1) 13. { 14. if (n == b) 15. { 16. d = 0; 17. break; 18. } 19. else if (n < b) 20. { 21. d = ((n - a) > (b - n) ? (b - n) : (n - a)); 22. break; 23. } 24. else 25. { 26. a = b; 27. b = c; 28. c = a + b; 29. } 30. 31. } 32. printf("%d\n", d); 33. 34. return 0; 35. }
abs(a,b)求两个数的绝对值
5.4 请实现一个函数,将字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换后的字符串为We%20Are%20Happy。
1. class Solution { 2. public: 3. void replaceSpace(char *str,int length) { 4. char* a = str; 5. int space = 0; 6. while (*a) 7. { 8. if (*a == ' ') 9. { 10. space++; 11. } 12. a++; 13. } 14. int newlength = length + (2 * space); 15. int end1 = length - 1; 16. int end2 = newlength - 1; 17. while (end1 != end2) 18. { 19. if (str[end1] != ' ') 20. { 21. str[end2--] = str[end1--]; 22. } 23. else 24. { 25. str[end2--] = '0'; 26. str[end2--] = '2'; 27. str[end2--] = '%'; 28. end1--; 29. } 30. } 31. } 32. };