新买的 U盘这么快就中病毒了!




题目描述
なに?!新买的 U盘这么快就中病毒了!

目录下多出很多同名的可执行文件:比如 1.gif 与 1.gif.exe 对应,main.c 于 main.c.exe 对应。
它们都是病毒。但并不是所有可执行文件(扩展名为 .exe 的文件)都是病毒,
比如图中的 problem.exe,并没不存在一个文件名字叫 problem,所以它不是病毒。

 

我会给你一些文件名列表,你能开发一款“病毒扫描器”帮我识别出哪些是病毒文件吗?

识别方法是:
文件名以“.exe”结尾。
    //strlen(input[i])
在文件名列表中同时还存在去掉“.exe”后同名的文件。
(病毒文件有其源文件)

输入
输入数据有多组。

每组输入的第一行是一个整数 n(0 < n <= 1000),表示接下来会有 n 个文件名。

接下来的 n 行为文件名,每个文件名占一行。

文件名最多 16 个字符,并且中间不包含空格。

如果 n 等于 0,则程序结束。

输出
以字典顺序输出
每一组数据中的病毒文件名。
每个文件名输出一行。
2
a.txt
a.txt.exe

2(改组没有病毒文件)
a
a.txt

10
a.txt
b.txt
d.txt.exe
c.txt
d.txt
a.txt.exe
e.txt
f.txt
e.txt.exe
g.txt

0
(结束的标志)

样例输出
a.txt.exe(第一组的数据)

a.txt.exe
d.txt.exe
e.txt.exe
提示
 例子中第二组没有病毒文件。
找出病毒文件后,输出前不要忘了排序。

 识别方法是:
文件名以“.exe”结尾。(就是做出判断:(文件名以“.exe”结尾)的模块)
    //strlen(input[i]),strlen(接受字符串首地址.)

在文件名列表中   同时还存在  去掉“.exe”后同名的文件。
//这个说法可以等价转换为多种角度的命题/要求.(比如正向/间接反向(截/补))
    //strcmp()
(病毒文件有其源文件)

//!改版本处理直接.exe的文件名,当然你可以以它为单个输入排查bug
//处理空白:&&不为空(在k处)

/* 升序版字符排序. */
#include <stdio.h>
#include <string.h>
int main()
{

    char input[2000][17] ;
    char str_exe[2000][17];/* 保存尾缀为.exe的文件 */
    char cp_str_exe[2000][17];
    
    /* test */
   // printf("test_8\n");

    /* 

    这样写会有个问题,在scanf结束读入后,回车键还残留在缓冲区中,这会使第一个gets()直接被结束掉.
    gets(input[i]);
   for (int i = 0; i < n; i++)
    */
    
    
    int n;/* 要读入的文件数目 */
    /*测试多组数据:这是要注意变量残留,即某些变量要设置在for/while的内部才可以重新的初始化,当然表达式要初始化一个值才行 */
    for(;scanf("%d", &n),n != 0;)
    {
        int len = 0;/* 文件名字符串的长度 */
        int cnt_str_exe = 0;/* 计数str_exe数组中有多少个该类字符串 */
            /* 字符串们写入数组input */
        for (int i = 0; i < n ; i++)
        {
            scanf("%s",input[i]); 
            
        }

        /* 从从input数组中筛选出尾缀为.exe,并写入到str_exe数组中 */
        int j = 0; //解决数组str_exe空洞.
        for (int i = 0; i < n; i++)
        {
            len = strlen(input[i]);//如果没有该处的迭代,len可能是个庞大的数据,造成数组下标越界,segtment fault.
            if (strcmp(&input[i][len - 4], ".exe") == 0)//需要随着i变化而迭代的量:len = strlen(input[i]);
            {
                
                //strcpy(str_exe[i],input[i]);//这样写会造成str_exe有空洞
                strcpy(str_exe[j++], input[i]); //这里的j能否内嵌?
                cnt_str_exe += 1;
            }
        }
            

        //     /* may be the files is a  virus file. */
        //     /* 在文件名列表中   同时还存在  去掉“.exe”后同名的文件。deal_file_name */
       


        /* deal_file_name   */
        int k = 0;/* 防止cp_str_exe空洞 */
        for (int i = 0; i < cnt_str_exe; i++)
        {
            len = strlen(str_exe[i]);
            str_exe[i][len - 4] = '\0';/* 字符串截断处理 */

            //int k = 0;/* 防止cp_str_exe空洞,但是把它安排在在循环内部其值无法得到保留,应外挪 */
            for (int j = 0; j < n + 1; j++) //内嵌循环时要注意更换循环变量和表达式.
            /* 检查input中是否有对应的源文件(病毒文件去壳) */
                if (strcmp(str_exe[i], input[j]) == 0 && *input[j] != NULL)
                //或strlen(input[i]) != 0;
                
                    /* //str_exe已经被修改截断只好后期加上.exe  */
                // printf("This is a virus file:%s.exe\n", str_exe[i]);
                    strcpy(cp_str_exe[k++],str_exe[i]);
        }
        
    //     /* int i=0,j=0;
    //     int n = 0; redefined*/

        int i = 0;
        j = 0;
        char buf[200];
        /* 冒泡排序算法 */
        for(i = 0;i<k-1;i++)
        {
            for(j=0;j<=k-2-i;j++)
            {
                /* 如果前者大于后者.交换位置使得最大者尽量靠后 */
                if(strcmp(cp_str_exe[j],cp_str_exe[j+1]) > 0)
                {
                    /* 调用strcpy(),可以使得字符串的排序和赋值项整数那样利索. */
                    strcpy(buf,cp_str_exe[j]);
                    strcpy(cp_str_exe[j],cp_str_exe[j+1]);/* 是加号 */
                    strcpy(cp_str_exe[j+1],buf);
                }

            }  
        }
        
        for(int i = 0 ; i<k;i++)
        {
            //printf("out:");
            printf("%s.exe\n",cp_str_exe[i]);
        }
    }
   

    return 0;
}
posted @ 2022-03-11 23:21  xuchaoxin1375  阅读(28)  评论(0)    收藏  举报  来源