传智杯 2022 初赛 C 题解
简要题意:给定不定行数的字符串,要求给它标上行号。
解法:本题的关键点在于不定行数字符串的读入,而且字符串是可能有空格的,这使得无法直接使用 cin >> str 的方法对字符串进行读入。事实上,我们可以采取多种方式读入这种文本:其一是使用 getchar(),出题人也是这么写的,但是我不喜欢 getchar()。因此,这里就需要使用一个叫做 fgets 的函数。
fgets 的用法如下:fgets(char *str, int n, FILE *stream),换而言之传三个参数,第一个参数是要存的字符数组,第二个参数是存多少个字符,第三个参数在竞赛语境中可以理解为 stdin。fgets 每次会读一行,而且在读完文件后会返回一个 NULL,因此可以使用这样的代码进行不定行数文件的读取:
while(fgets(buf,len,stdin)!=NULL) {
do sth.
}
接着我们可以开一个 vector <char> s[maxn],用 vector 存放下每一行的每个字母,以便后续我们输出。这里不能开二维数组,因为尽管累计字符长度是 a[200000][200000],会爆内存,所以要用 vector 这类为我们自动分配内存的容器。
后面就是求位数了,可以用循环,也可以预处理位数数组,也可以用 log() 函数求出。这里应该就不是重难点了。
参考代码:
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
char buf[200050];
vector <char> s[200050];
int cnt;
int get_digit(int x)
{
int digit=1,ret=1;
while (ret<=x)
{
digit++;
ret*=10;
}
return digit;
}
int main()
{
while(fgets(buf,200000,stdin)!=NULL)
{
cnt++;
for (int i=0;buf[i]!='\n';i++)
s[cnt].push_back(buf[i]);
}
int cnt_digit=get_digit(cnt);
for (int i=1;i<=cnt;i++)
{
for (int j=1;j<=cnt_digit-get_digit(i);j++)
putchar(' ');
cout << i << ' ';
for (int j=0;j<s[i].size();j++)
putchar(s[i][j]);
putchar('\n');
}
return 0;
}