yundi 发表于 2016-5-28 17:21:00

一起来做练习学思路

本帖最后由 yundi 于 2016-6-25 14:37 编辑

目录
1. 1个1G大小的txt文件,每行是一条用户记录(用户名,密码,电话...).编写一个程序,按姓名检索文件,要求越快越好。
2. 两个大数相乘

yundi 发表于 2016-5-28 17:26:30

本帖最后由 yundi 于 2016-5-28 22:36 编辑

1 . 1个1G大小的txt文件,每行是一条用户记录(用户名,密码,电话...).编写一个程序,按姓名检索文件,要求越快越好。

思路:现在电脑一般都4G内存,不用白不用,把文件全加载到内存,然后在内存中检索。

#include <stdio.h>
#include <stdlib.h>
#include <windows.h> //GetTickCount需要

int main()
{
        char path[] = "C:\\Users\\Administrator\\Desktop\\asdfe.txt";
        FILE * fp = NULL;//文件指针
        char sbuf = {0};//缓存
        int star,end;//计时
        int rowcount = 0;//文件行数
        char **spp = NULL;//指向指针数组
        int i;
        char **tmpp = NULL;//用于遍历指针数组
        int count ;//统计结果
        char flag='y';//控制查询循环
        fp = fopen(path,"r");//打开文件
        if(fp==NULL)
        {
                return -1;
        }
        star = (int)GetTickCount();//开始计时
        while(!feof(fp))//获取总行数
        {
                fgets(sbuf,100,fp);
                rowcount++;
        }
        spp = (char **)malloc(sizeof(char*)*rowcount);//分配保存指针数组的内存空间
        i = rowcount;
        fseek(fp,0,SEEK_SET);//上一次读到文件尾,这里要回到文件头

        //将文件全部加载到内存,避免查询时频繁读取硬盘,提高查询效率
        while(!feof(fp))
        {
                fgets(sbuf,100,fp);//在文件中读取一行,放到缓存
                spp = (char *)malloc(strlen(sbuf)+1);//申请一段内存,将起始地址保存到指针数组
                strcpy(spp,sbuf);//将缓存复制到申请的内存中
                * ((spp)+strlen(sbuf)) = '\0';//结尾加字符串结束标志
                i--;//移动到指针数组的下一位置
        }
        end = (int)GetTickCount();
        printf("载入内存完成!历时%d毫秒\n",end-star);

        //查询代码
        while(flag!='n'&&flag!='N')
        {
                printf("\n\n请输入姓名:");
                scanf("%s",sbuf);
                star = (int)GetTickCount();
                count = 0;
                for(tmpp = spp;tmpp<spp+rowcount;tmpp++)
                {
                        if(strstr(*tmpp,sbuf))
                        {
                                printf("\n%d行:%s",(tmpp-spp)/sizeof(char*)+1,*tmpp);
                                count ++;
                        }
                }
                end = (int)GetTickCount();
                printf("\n本次查询历时%d毫秒,共有%d条记录",end - star,count);
                printf("\n是否继续查询?(y/n)");
                scanf("%c",&flag);//用来吃掉输入姓名后的回车键
                scanf("%c",&flag);//第二次才接受到'y' or 'n'
        }
        //关闭文件!
        fclose(fp);
        //释放内存!!!
        for(tmpp = spp;tmpp<spp+rowcount;tmpp++)
        {
                free(*tmpp);
        }
        free(spp);
        getchar();
}

上面是单线程的,如果谁有这样的大文件借我做测试?我就来试试多线程。{:5_108:}

yundi 发表于 2016-6-25 14:35:25

2. 两个大数相乘 。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//两大数相乘,返回字符串,例如:
// s1   76789 (i--)
// s2      98 (j--)
char * bigmul(const char * s1, const char * s2)
{
        int len1 = strlen(s1);//下标 0~len1-1
        int len2 = strlen(s2);//下标 0~len2-1
        int len9 = len1 + len2 + 1;//下标 0~len9-2,len9-1
        int i,j,tmp;
        char * rel = NULL;
        char * buf = NULL;
        //1.申请空间
        rel = (char *)malloc(sizeof(char)*len9);//保存最终结果,最后一字节是'\0'
        memset(rel,0,sizeof(char)*len9);
        buf = (char *)malloc(sizeof(char)*len9);//临时存放s2的某一位与s1相乘结果,最后一字节保存每次相乘的进位
        //2.计算
        for(i=len2-1;i>=0;i--)
        {
                memset(buf,0,sizeof(char)*len9);
                for(j=len1-1;j>=0;j--) //s2的某一位与s1每位依次相乘
                {
                        tmp = (s1-'0')*(s2-'0') + buf;
                        buf = tmp % 10;
                        buf = tmp / 10;
                }
                buf = buf;
                for(j=len9-2;j>=0;j--)
                {
                        rel += buf ;
                        if(rel>9)
                        {
                                rel %= 10;
                                rel += 1;
                        }
                }
        }
        free(buf);
        //3.转为字符
        for(i=0;i<len9-1;i++)
        {
                rel += '0';
        }
        rel = '\0';

        return rel;
}
void main(void)
{
        char str1 = {0};
        char str2 = {0};
        char * pstr = NULL;
        scanf("%s%s",str1,str2);
        pstr = bigmul(str1,str2);
        printf("\n%s\n",pstr);
        free(pstr);
        system("pause");
}

代码计算过程说明:假设 s1是76789 (i--),s2是 98 (j--),i递减表示s1从个位到最高位,j表示s2从个位到最高位。先用s2个位8乘 s1,8*9=72,2存到buf,7存到buf最后一字节;再8*8(s1的十位)=64,64+刚才的进位7=71,1存到buf,又有进位7存到buf最后一字节;直到8*s1最高位,这时buf结果是76789*8=614312。把本轮结果放到rel中,然后进行第二轮,即s2的十位9依次乘s1,结果76789*9=691101存到buf,再把buf累加到rel ……如此循环乘完所有位。

xhbsingle 发表于 2016-6-28 11:03:20

学习
页: [1]
查看完整版本: 一起来做练习学思路