题目(编程题:病毒)
小B最近对破解和程序攻击产生了兴趣,她迷上了病毒,然后可怕的事情发生了。不知道什么原因,可能是小B的技术水平还不够高,小B编写的病毒程序在攻击一个服务器时出现了问题。尽管成功的入侵了服务器,但并没有按照期望的方式发挥作用。
小B的目的很简单:控制服务器内存区域,试图在内存中装入从1到n之间的n个自然数,以覆盖内存区域。可能是小B对编程理解上的问题,病毒似乎没有完全成功。可能是由于保护机制的原因,内存写入只接受二进制的形式,所以十进制表达中除了0和1之外的其他值都没有成功写入内存。小B希望知道,究竟有多少数成功的写入了服务器的内存!
输入
输入中有多组测试数据,每组测试数据在单独的一行中,为整数n(1<=n<=10^9)。
输出
对每组测试数据,在单独的行中输出问题的答案。
举例
输入:10
输出: 2
输入:20
输出:3
代码
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
| #include <stdio.h> #include <string.h> #include <stdlib.h> * 1. 输入的字符数组从最高位开始依次与1做比较 * 2. 小于等于1 取原值,并比较下一位,如果没有下一位,则返回; * 3. 大于1,则其后的位数都取1,并返回; * 4. 将得到的字符数组看作二进制,并转化为十进制。 * */ static char addarray[10] = ""; static char array1[10] = ""; char * fun(char *cstring, int n) { char compareString = *(cstring + n); char *onestring = "1"; char array[10] = ""; char *rec = ""; if (strcmp(onestring,&compareString) >= 0) { array[0] = compareString; if (*(cstring+n+1)) { strcat(array, fun(cstring, n+1)); strcpy(addarray, array); rec = addarray; } else rec = cstring + n; } else { for (int i = 0; i < (strlen(cstring) - n); i++) { strcat(array1, onestring); } rec = array1; } return rec; } int main(int argc, const char * argv[]) { char nstring[10]; printf("Input String:"); scanf("%s", nstring); char *resultString = fun(nstring, 0); printf("%s\n", resultString); long result = strtol(resultString, NULL, 2); printf("%ld\n", result); return 0; }
|
输出:
Input String:20
11
3
Input String:1040
1011
11
Input Stirng:2300304
1111111
127
知识点总结
关于字符数组和字符串在函数间的传递
从代码中可以看到我用了两个静态数组变量,之所以不直接定义在函数体内作为局部变量是因为:
当用字符指针char*
返回字符数组首地址时,函数体内的局部变量数组里的值已经被释放,返回的首地址虽然没有变,但里面的值已经无意义了。
例如:
1 2 3 4 5 6 7 8 9 10 11 12 13
| #include "stdio.h" char *test() { char *tmp="测试"; return tmp; } void main(void) { printf("%s",test()); }
|
打印出来的值可能是乱码也能为nil。
解决方式:
1. static全局变量
1 2 3 4 5 6 7 8 9 10 11 12
| #include "stdio.h" char *test() { static char tmp[30]="static测试"; return tmp; } void main(void) { printf("%s",test()); }
|
在数组tmp[30]前面加入了static
关键字,它就使得tmp[30]
存放在内存中的静态存储区中,所占用的存储单元一直不释放,直到整个程序运行结束。所以当主函数调用完print()
函数后,该空间依然存在。所以main()
函数中接到首地值后可以访问数组中的元素。
2. 结构体作为返回值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #include "stdio.h" #include "string.h" struct ret { char buf[30]; }; struct ret test(char *tmp) { struct ret a; strcpy(a.buf,tmp); return a; } void main(void) { struct ret b; b=test("用结构体作为返回值传递数组"); printf("%s",b.buf); }
|
两点注意:
1、数组之间的赋值不要直接,即不要直接将数组 A 赋给数组 B,而是要用strcpy
(字符型数组)或者memcpy
(非字符型数组)。
2、用结构体定义变量和函数时不要忘了结构体名(上面程序的ret
)。
Reference
[1] 【原】C语言函数返回数组的问题 http://www.cnblogs.com/wuqi1003/archive/2013/01/09/2853657.html
[2] C语言中字符串如何转换为二进制、八进制、十进制、十六进制 http://blog.csdn.net/edonlii/article/details/9162769
[3] C语言之strcat函数 http://blog.csdn.net/hgj125073/article/details/8439448
[4] C语言strcmp()函数:比较字符串(区分大小写) http://c.biancheng.net/cpp/html/162.html