C/C++中的ACM题目输入处理——简单易上手

发布时间 2023-09-30 16:02:39作者: ^_^ok

这里就不按其他文章的以各种情况为分类方法,而是以方法本身为分类办法。因为有一些方法是不同情况通用的,比如已知数量数字的输入和未知数量数字的输入,其实可以用同一种办法。

输入

C/C++ :scanf正则表达式

头文件<stdio.h><cstdio>

普通使用时,语法为scanf("%d",&a),当遇到空格符、换行、Tab时结束输入,并且丢弃这些空格符、换行、Tab键符号。

所以比如说我们读取的字符串有空格符时,或者需要读取特定的字符,就要用到scanf的一些其他用法,语法如下:

1. scanf("%ns",str)//n为整数,读入的字符串最长不超过n,然后在末尾补’\0’
	char str[100];
	scanf("%5s",str);输入abcdefghcd,最终str为abcde
2. scanf("%nf",&data);//读入的浮点数最多有n位整数,位数多于n,会截断。
	float p;
	scanf("%5f",&p);输入123,输出为p为123.00000;输入1234567,输出为12345.000000
3. scanf("%n[a-z]",&str);//读入最多n个字符,如果遇到非a-z的字符,停止,同理,%[0-9]表示只读入’0’到’9’之间的字符,%[a-zA-Z]表示只读入字母
4. scanf("%[^c]",&str);//读入任意多的字符,直到遇到字符c为止停止,这种方法主要是读取含空格、tab字符的字符串
	char *str;
	scanf("%[^\n]%*c",str);//这就是获取一行字符串,遇到换行符停止。%*c的作用是吸收\n,"%*"表示读入后不赋予任何变量,即跳过该输入值,也就是那个换行符,否则他会在缓冲区里,影响下一次输入

对于第四点,我们做个实验,先写如下代码运行

    char a[500];
    char b[500];
    scanf("%[^\n]",a);
    scanf("%[^\n]",b);
    printf("%s",a);
    printf("%s",b);

结果:输入abcd,换行,马上就输出了abcd,程序结束。

进行更改代码如下,运行

    char a[500];
    char b[500];
    scanf("%[^\n]%*c",a);
    scanf("%[^\n]%*c",b);
    printf("%s",a);
    printf("%s",b);

结果:输入abcd,换行,继续输入efg,换行,程序输出abcdefg,结束。

原因是,第一个程序中,第一个scanf输入abcd和换行,遇到换行了,于是输入结束,字符串a为abcd,换行符虽然没有输入到a里面,但它还在缓冲区,将作为下一次的输入第一个字符,于是第二个scanf输入字符串b时,由于直接输入了还在缓冲区的换行符,所以输入也结束,字符串b为空字符串。

第二个程序使用%*c,表示跳过了缓冲区的一个字符,就是那个换行符,于是达到我们的目的。当然如果把第一个scanf的换行符换为别的字符,效果应该会更明显,读者自行验证。

参考文章:scanf( )与正则表达式

C++ :std::cin

c++中cin的用法,参考C++中cin的详细用法,这里只给出针对acm输入cin的一些简单用法。

首先,cin>>data,遇到空格、tab、换行就停止输入,但是输入之前遇到这些空格、tab、换行,或缓冲区中第一个字符是空格、tab或换行这些分隔符时,cin>>会将其忽略并清除,继续读取下一个字符,若缓冲区为空,则继续等待。但是如果读取成功,字符后面的分隔符是残留在缓冲区的,cin>>不做处理。

所以如果输入的数据是以空格、换行分开,就直接cin>>就行了,如果数量未知,就用while循环

#include<iostream>
#include<vector>
using namespace std;
int main(){
    vector<int>data;
    int temp;
    while (cin>>temp){
        data.push_back(temp);
    }
    for (int i = 0; i < data.size(); i++){
        cout<<data[i]<<" ";
    }
}
输入:
	1 2 3 4
	5 6 7 8
	9
输出:
	1 2 3 4 5 6 7 8 9

第二,就是cin.get()用法,如下

  1. cin.get(char类型变量) ;
  2. cin.get(char类型变量数组,最大读取数量);
  3. cin.get();用于舍弃输入流的不需要的字符(比如回车什么的)

参考c++中的cin.get()的用法

C++ :getline

头文件<iostream>

简单用法,可以通过getline来获取一行字符语法如下

std::string s;
getline(std::cin, s) //从输入流中读取一行赋给s。
getline(std::cin, s ,ch)//从输入流中读取内容,赋给s,直到遇到字符ch,返回结果。

举个栗子

    std::string s1;
    std::string s2;
    char ch=',';
    getline(std::cin,s1);
    getline(std::cin,s2,ch);
    std::cout<<s1<<std::endl<<s2<<std::endl;
输入:
	a,2,b,5 wd hh
	2b,LOL
输出:
	a,2,b,5 wd hh
	2b

我们看到第二行,getline遇到,就停止输入了,那么如果我们想要把拆分后的字符串都保存,怎么办呢?那就用循环。还是用栗子说话。
输入

输入
	1,2,5,9,74,582,1124

存储的数据结构自己选择,我这里用vector,代码如下

#include<iostream>
#include<vector>
using namespace std;
int main(){
    string s;
    char ch=',';
    vector<string>str(0);
    while (getline(cin,s,ch)){
        str.push_back(s);
    }
    for (int i = 0; i < str.size(); i++){
        cout<<str[i]<<" ";
    }
}

输出

1 2 5 9 74 582 1124

当然也可以用for循环,特别是如果知道了输入数量的,比如输入n行字符串,保存

输入:
	3
	I love China
	I am chinese
	I am not SB
#include<iostream>
#include<vector>
using namespace std;
int main(){
    int num;
    cin>>num;
    cin.get();//之所以要cin.get(),是因为cin>>num之后有一个换行符,这个换行符残留在缓冲区了(前面cin有讲),getline不会忽略缓冲区的换行、空格等,所以要主动去掉
    vector<string>str(num);
    for (int i = 0; i < num; i++){
        getline(cin,str[i],',');
    }
    for (int i = 0; i < str.size(); i++){
        cout<<str[i]<<" ";
    }
}

当然,getline还可以用作单独的字符串分割,用到stringstream输入流,这里给出实例代码

#include<sstream>
#include <iostream>
/*
@func    字符串分割
@para1   待分割长字符串
@para2   分割标志字符
@ret     分割后子字符串数组,不包含标志字符delim
*/
vector<string>stringSplit(const string str,char delim){
    stringstream ss;
    ss<<str;
    string item;
    vector<string>elems;
    while (getline(ss,item,delim))
    {
        if(!item.empty()){
            elems.push_back(item);
        }
    }
    return elems;
}

C++基本上使用以上cin和getline方法就可以处理大部分输入了,灵活运用就行。

输出

输出指定小数点后位数

C语言:printf("%.nf",number);

C++ :cout

#include<iomanip>
cout<<setprecision(n)<<数字<<endl;

其他

类型转换

  1. string to char*

    str1.c_str();,然后使用strcpy复制

  2. 字符串拼接

    • string类型,直接相加 +
    • 字符串(字符数组),可以用strcat(str1,str2)// #include<string.h>
  3. char* to number

    atoi(char*) // #include <stdlib.h> int

    atof(char*) float

  4. number to string

    to_string(num); // #include <string>

  5. char* to string

    char ach1[] = "Hello";
    string str1(ach1);
    string str2 = ach1;