0%

C语言编程题(2016年360笔试习题之病毒)

题目(编程题:病毒)

小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) { //compareString <= 1
array[0] = compareString;
if (*(cstring+n+1)) {
strcat(array, fun(cstring, n+1));
strcpy(addarray, array);
rec = addarray;
}
else
rec = cstring + n;
}
else { //compareString > 1
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[30]="测试";
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

----------------------END END----------------------