日志排序——北京大学

知识点

输入 和 排序

疑问

关于输入还存在疑惑

代码

未改进代码

/**
1.首尾有空格
2.之间空格不定
**/ 
#include "bits/stdc++.h" 
#include<string>
#include<vector> 
using namespace std;

struct myLog{
	string str;	//原始输入
	double end;	//结束时间 
	int ms;		//微秒
	int totalA;
	int totalB;
}; 

vector<myLog> logs;

string str;		//放到外面节省空间

char start[23];	//时间数组 

int year;	//年份
int month;	//月份
int day;	//日
int hour;	//小时
int minute;	//分钟
int s;		//秒

//读取空格函数,传地址的 
void readbs(int &idx){
	while(str[idx] == ' '){
		idx++;
	}
} 
 
bool cmp(myLog a,myLog b){
	if(a.end < b.end){
		return true;
	}else if(a.end == b.end){
		if(a.totalA < b.totalA){
			return true;
		}else if(a.totalA == b.totalA){
			if(a.totalB < b.totalB){
				return true;
			}else if(a.totalB == b.totalB){
				if(a.ms < b.ms){
					return true;
				}else{
					return false;
				}
			}	
		}
	}
	
	return false;
} 
 
void print(){
	for(int i=0;i<logs.size();i++){
		cout<<logs[i].str<<endl;
	}
} 
 
int main(){
	getline(cin,str);

	while(str.size()!=0){
		myLog l;
		l.str = str;
		int idx = 0;	//表示读取到字符串哪里了 
		
		//如果行首有空格,一直读到没有空格 
		if(str[0] == ' '){
			readbs(idx); 
		}
		
		//开始读取名字
		while(str[idx] != ' '){
			idx++;
		} 
		
		//再次读取空格
		readbs(idx);
		
		//读入时间数组 
		for(int i=0;i<23;i++){
			start[i] = str[idx++]; 
		} 
		
		//将时间输入
		sscanf(start,"%d-%d-%d %d:%d:%d,%d",&year,&month,&day,&hour,&minute,&s,&l.ms);
		
		l.totalA = year*10000+month*100+day;
		l.totalB = hour*10000+minute*100+s;
		
		//读取空格
		readbs(idx);
		
		char end[23];	//用时数组 
		int len = 0;
		//读取结束时间数组 
		while(str[idx] != '('){
			end[len++] = str[idx];
			idx++;
		} 
		
		//将字符串转换成数字
		sscanf(end,"%lf",&l.end); 
		
		//放入数组
		logs.push_back(l); 
		getline(cin,str);		
	}
	
	//排序
	sort(logs.begin(),logs.end(),cmp);	

	print();
	
	return 0;
}

改进代码

之前自己对输入处理不太理解,看了别人的代码理解了,改进建议:

  1. 当使用scanf("%s",str)读取字符数组时,%s是从第一个不是空格和换行的字符开始读入的,以空格和换行结束读入的。 比如:
    输入一行字符串"   abc def\n"
    scanf("%s",str)
    得到的str是"abc",它跳过了前面的空格和换行!!!
    
    可以延伸的是,除了%c,其他都会跳过空格和换行的,而%c会读取空格和换行!《算法笔记》上有写。
  2. 当使用gets()读取字符数组时,它是读取一整行,它是原封不动的把一行保存下来,它以换行结束读入。
    输入一行字符串"   abc def\n"
    gets(str)
    得到的str是"   abc def"
    
  3. 字符数组除了在声明时可以使用“=”赋值,其他时候都不行:
    char str[10] = "hello" //正确
    ------------------------------
    char str[10];
    str = "hello"	//错误,得使用strcpy(str,"hello"),是把后面赋给前面
    
  4. sscanf()是从左到右匹配,如果没有将str全部赋值完也没有关系,比如下面的代码中就省略了"(s)"和它后面的空格

理解了上面的概念,就可以对代码进行改进了。

/**
1.首尾有空格
2.之间空格不定
**/ 

#include "bits/stdc++.h" 
#include<string.h>
#include<vector> 
using namespace std;

const int maxn = 100;

struct myLog{
	char str[maxn];	//原始输入
	double end;	//结束时间 
	int ms;		//微秒
	int totalA;
	int totalB;
}; 

vector<myLog> logs;

char str[maxn];		//放到外面节省空间

char name[20]; //名称 
int year;	//年份
int month;	//月份
int day;	//日
int hour;	//小时
int minute;	//分钟
int s;		//秒
 
bool cmp(myLog a,myLog b){
	if(a.end < b.end){
		return true;
	}else if(a.end == b.end){
		if(a.totalA < b.totalA){
			return true;
		}else if(a.totalA == b.totalA){
			if(a.totalB < b.totalB){
				return true;
			}else if(a.totalB == b.totalB){
				if(a.ms < b.ms){
					return true;
				}else{
					return false;
				}
			}	
		}
	}
	
	return false;
} 
 
void print(){
	for(int i=0;i<logs.size();i++){
		printf("%s\n",logs[i].str);
	}
} 
 
int main(){
	
	//gets()读取一行 
	gets(str);

	while(strlen(str)!=0){
		myLog l;
		
		strcpy(l.str,str);
		
		//使用sscanf进行读入 
		sscanf(str,"%s %d-%d-%d %d:%d:%d,%d %lf",name,&year,&month,&day,&hour,&minute,&s,&l.ms,&l.end);
		
		//方便比较 
		l.totalA = year*10000+month*100+day;
		l.totalB = hour*10000+minute*100+s;
		
		//放入数组
		logs.push_back(l); 
		
		gets(str);		
	}
	
	//排序
	sort(logs.begin(),logs.end(),cmp);	

	print();
	
	return 0;
}

反思

见改进建议

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值