CSP刷题笔记

mac2022-06-30  157

将字符串转换为整数的函数stoi(string,nullptr,base)整数与字符串之间的转换还可以通过stringstream类来实现,要注意,转换过一次之后,若还想再对其它的数据进行转换,则需要调用clear函数。十进制十六进制之间的转换sprintf(),详细说明见链接:sprintf

  以前知道i++是先用i,再让i的值加1,++i是先让i的值加1,再用i。但对这两种情况总是存在着一些误解,于是自己写代码测试了一下。

应用于数组的访问 int main() { int i = 0,j = 0; string str = "hello"; cout << str[i++] << endl; cout << str[++j] << endl; }

上面的程序输出结果如下

h e 应用于函数的实参 void Test(int i) { cout << i << endl; } int main() { int i = 0,j = 0; Test(i++); Test(++j); }

上面的程序输出结果如下

0 1

总结

i++和++i的用法在任何地方都是成立的。


可以使用transform函数进行大小写的转换。

将字符串s全部变为大写 transform(s.begin(), s.end(), s.begin(), ::toupper); 将字符串s全部变为小写 transform(s.begin(), s.end(), s.begin(), ::tolower);

一般处理大小写不敏感的情况,可以将字符串全部变为大写或全部变为小写。


sort排序是一种不稳定的排序,不要试图将sort函数用于基数排序。如果需要根据多个关键字排序,可以通过写cmp函数来实现。


如果题目中没有明确说明输入的数据有多少行,可以通过while(getline(cin,str))来实现数据的读入。注意,如果在之前有用cin进行过输入,需要先调用getchar函数将换行符从输入缓冲中读取出来。 也可以使用while(cin>>str)或者while(scanf("%d",&n) != EOF)来接收未知数量的数据,但是后者在VS2017中不可用。

下面的代码适用于一行有多个数据,但不知道具体是几个,数据之间用空格分隔的情况。注意,此代码之前一定要有其它接收输入的语句,否则getchar函数会错误的截获有用的数据。 gcc编译器下不能和ios::sync_with_stdio(false)一起用

while(getchar() != '\n'){ cin>>str; } 下面的代码也可以实现读取一行中的未知个数的数据,且在gcc中有没有ios::sync_with_stdio都可用。 while(cin.get() != '\n'){ cin>>str; }

cin和cout虽然使用起来比较方便,但是它的输入输出效率很低,通过在main函数中添加下面的代码可以提高其输入输出效率,但是可能会引发一些问题,暂不清楚具体是什么问题。

ios::sync_with_stdio(false)

tm结构体类型的变量可以模拟时间的加法运算。它里面的结构体成员如下所示

struct tm { int tm_sec; //分后的秒(0~61) int tm_min; //小时后的分(0~59) int tm_hour; //小时(0~23) int tm_mday; //一个月天数(0~31) int tm_mon; //一个后的月数(0~11) int tm_year; //1900年后的年数 Year - 1900. int tm_wday; //星期日开始的天数(0~6) int tm_yday; //从1月1日开始的时间(0~365) int tm_isdst; //夏令时标志(大于0说明夏令时有效,等于0说明无效,小于0说明信息不可用) };

C 库函数time_t mktime(struct tm *timeptr) 把 timeptr 所指向的结构体变量转换为一个依据本地时区的time_t值。我们可以利用mktime将tm类型的时间变换成正确的格式,比如说将2小时60分变成3小时0分。 tm还可以进行星期的计算,下面的代码用来求2020年3月6日是星期几

tm tt; tt.tm_year = 2020 - 1900; tt.tm_mon = 2; tt.tm_mday = 6; tt.tm_hour = 0; tt.tm_min = 0; tt.tm_sec = 0; mktime(&tt); cout << tt.tm_wday;

有一点需要注意,tm只能求1970年1月1日之后的日期是星期几,而且在求1970年1月1日的星期时还可能会出错。下面的代码可以用于求输入的年月日是星期几

tm t; t.tm_year = 2020 - 1900; t.tm_mon = 2; t.tm_mday = 5; t.tm_hour = 0; t.tm_min = 0; t.tm_sec = 0; t.tm_isdst = -1; mktime(&t); int year, mon, day; cin >> year >> mon >> day; t.tm_year = year - 1900; t.tm_mon = mon - 1; t.tm_mday = day; mktime(&t); cout << t.tm_wday;

从代码中可以看出,在输入年月日之前,先对tm进行了初始化,这个初始化的日期并不是任给的,而且一定得是星期四。这是因为在求1970年1月1日的星期时,mktime并不会进行星期计算,tm_wday的值保持不变,而1970年1月1日又恰好是星期四,所以需要用星期四的日期来初始化tm。

下面的代码同样可以实现求星期的功能,在使用上与上面的代码是相同的。(注:又发现了新问题,这段代码执行的正确性好像还有电脑的系统时间有关)

time_t rawtime; struct tm * timeinfo; int year, month, day; time(&rawtime); timeinfo = localtime(&rawtime); cin >> year >> month >> day; timeinfo->tm_year = year - 1900; timeinfo->tm_mon = month - 1; timeinfo->tm_mday = day; mktime(timeinfo); cout << timeinfo->tm_wday << endl;

像这种for(auto i : STL)遍历STL容器的方法,改变i的值,并不会引起STL的变化,有点类似于形参和实参的意思。


可以在定义结构体的时候,为其写一个构造函数。当结构体的成员比较多时,可以直接通过构造函数来进行初始化,下面是一个例子

struct studentInfo{ int id; char gender; studentInfo(){}; studentInfo(int _id,char _gender):id(_id),gender(_gender) {}; };

上面手动添加上了默认构造函数,这样在定义studentInfo类型的变量时,既可以在定义时初始化,也可以定义完之后再初始化。


在进行闰年的处理时,一种方法是根据是否闰年,动态地修改2月份的天数,还有一种方法是在定义每个月的天数时,将闰年和非闰年的情况都提前定义好,再根据是否闰年进行动态的选择。 方法一:

int DaysOfMon[12] = { 31,0,31,30,31,30,31,31,30,31,30,31 };

方法二:

int DaysOfMon[2][12] = { {31,28,31,30,31,30,31,31,30,31,30,31}, {31,29,31,30,31,30,31,31,30,31,30,31} };

CSP的OJ系统不会因为多输出一个空格或者在最后多输出了一个换行而判错。比如题目要求的输出格式是下面这样的

2 2 3 0 2 3 4 5 0 4 2 3 2 0 3 0 0 0 4 4

负责输出的代码写成下面这样不会引发错误

for (int i = 0; i < n; i++){ for (int j = 0; j < m; j++) cout << ans[i][j]<<" "; cout<<endl; }

可以看出来,上面的代码每行都会多输出一个空格,而且在最后还会多输出一个换行。


下面的代码将结果result以十六进制大写输出。

cout << uppercase << ::hex << result << "\n"; printf("%X",result);

下面的代码将结果result以8位长度输出,若不足八位,则在前面补0

cout << setfill('0') << setw(8) << result; printf("d", result);

下面的代码将double类型的变量d保留保留5位小数输出

cout << setiosflags( ios::fixed) << setprecision(5) << d; printf("%.5f", d);

下面的代码将double类型的变量d保留5位有效数字输出

cout << setprecision(5) << d;

对于vector容器,可以使用erase函数删除容器里的某个元素,但是erase的参数只能是iterator类型的,当我们想删除第i个元素时,可以通过如下代码实现

auto it = v.begin(); it += i; v.erase(it);

注:其它容器不能使用这种方法。


用scanf和printf输入输出string类型的变量

string s; s.resize(10); scanf("%s", &s[0]); printf("%s", s.c_str());

  根据先序序列和中序序列可以不经过建树而得出后续序列,同样也可以由后续序列和中序序列不经建树直接得出先序序列。


  对vector用push_back赋值要远远慢于对数组的赋值,对vector用sort函数排序效率略高于数组。用for(auto it : v)的方式访问vector的效率和访问数组的效率差不多,而用下标访问vector的效率则低下很多。


  如果函数的参数占用的内存较大,比如说一个很复杂的结构体,此时应该考虑传引用,因为这样能提高程序的效率。


  g++编译器下,对索引数组排序和对结构体数组排序效率相差不多,前提是结构体的比较函数传引用。


最新回复(0)