鱼C论坛

 找回密码
 立即注册
查看: 1958|回复: 3

[技术交流] 一起来做练习学思路

[复制链接]
发表于 2016-5-28 17:21:00 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

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

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

评分

参与人数 1荣誉 +5 鱼币 +5 贡献 +5 收起 理由
n0noper + 5 + 5 + 5 热爱鱼C^_^

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 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[100] = {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[rowcount-i] = (char *)malloc(strlen(sbuf)+1);//申请一段内存,将起始地址保存到指针数组
                strcpy(spp[rowcount-i],sbuf);//将缓存复制到申请的内存中
                * ((spp[rowcount-i])+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();
}
上面是单线程的,如果谁有这样的大文件借我做测试?我就来试试多线程。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 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[j]-'0')*(s2[i]-'0') + buf[len9-1];
                        buf[i+j+1] = tmp % 10;
                        buf[len9-1] = tmp / 10;
                }
                buf[i+j+1] = buf[len9-1];
                for(j=len9-2;j>=0;j--)
                {
                        rel[j] += buf [j];
                        if(rel[j]>9)
                        {
                                rel[j] %= 10;
                                rel[j-1] += 1;
                        }
                }
        }
        free(buf);
        //3.转为字符
        for(i=0;i<len9-1;i++)
        {
                rel[i] += '0';
        }
        rel[len9-1] = '\0';

        return rel;
}
void main(void)
{
        char str1[100] = {0};
        char str2[100] = {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 ……如此循环乘完所有位。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-6-28 11:03:20 | 显示全部楼层
学习
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-27 04:31

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表