文章预览:
练习题库推荐
牛客网上有一个专门的oj输入输出练习:
练习地址
所有的测试用例输入,最后一行都有一个回车"\n"
1、getline(cin,str)读取换行符 并且将换行符替换成'\0',并将换行符从输入队列中抹去。
2、cin不会读入换行符;//这个众所周知,但是可以利用这个特点来连续读入任意个字符串
C++保留两位小数
#include <iostream>
#include <iomanip> //不要忘了头文件
using namespace std;
int main(){
//第一种写法
cout<<setiosflags(ios::fixed)<<setprecision(2);
//第二种写法
cout.setf(ios::fixed);
cout<<setprecision(2);
//第三种写法
cout<<fixed<<setprecision(2);
}
- 要保留几位小数setprecision(n)的括号里n就换成几。
- 前两种写法是一样的,第三种是简化写的。
- 上面的语句写一次就行了,对之后的数字都有效。
一、cin读取
cin遇到空格时会停止读取,所以可以使用while循环不停地读取数据
1、行数不固定,列数固定
下面这种写法就是针对行数不固定,但是每行只有两个数的情况
#include <iostream>
using namespace std;
int main() {
int a, b;
while (cin >> a >> b) { // 注意 while 处理多个 case
cout << a + b << endl;
}
}
// 64 位输出请用 printf("%lld")
2、 输入多行数据,每行个数不确定
题目描述:
输入描述:
输入数据有多组, 每行表示一组输入数据。
每行不定有n个整数,空格隔开。(1 <= n <= 100)。
输出描述:
每组数据输出求和的结果
示例1
输入
复制
1 2 3
4 5
0 0 0 0 0
输出
复制
6
9
0
关于cin.get():
cin.get()遇到结束符并不会将之删除
cin.get()并不会舍弃Space,依然会将其读取进去
利用上述特性就可以利用cin.get()来判断读取的数字的下一位是否为换行符
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int main()
{
int cur_sum = 0;
int x;
while (cin >> x)
{
cur_sum += x;
if (cin.get() == '\n')
{
cout << cur_sum << endl;
cur_sum = 0;
}
}
return 0;
}
但是如果输入的一行中最后一个数字后面是空格+换行的话,那么就会导致该行没有输出数据,举例说明,输入1 2 ‘\n’,并没有输出1+2的和
因为cin并不会读取空格,在读取到2时,get()判断下一位并不是\n,所以此时并不会输出数字,但是下一次循环时cin只会跳过空格和结束符,继续读取下一行的数
二、getline读取
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
using namespace std;
int main() {
vector<vector<int>> arr;
string input;
while (getline(cin, input)) {
if (input.size() > 0) {
stringstream stringin(input);
int num;
vector<int> a;
while (stringin >> num) {
a.push_back(num);
}
arr.push_back(a);
}
}
// 使用自测数据按钮时调试用,正式提交时要删掉。
cout << "rows: " << arr.size() << ", cols: " << arr[0].size() << endl;
for (int i=0; i<arr.size(); i++) {
for (int j=0; j<arr[i].size(); j++) {
cout << arr[i][j] << " ";
}
cout << endl;
}
}
三、scanf输入
输入时记得在变量前加&
1、不发生改变获取输入值
#include <bits/stdc++.h>
using namespace std;
int main(){
int a;//声明变量
scanf("%d",&a);//类型一致
cout<<"输出为:"<<a<<endl;
return 0;
}
2、改变长度
#include <bits/stdc++.h>
using namespace std;
int main(){
int a;//声明变量
scanf("%2d",&a);//类型一致
cout<<"输出为:"<<a<<endl;
return 0;
}
//此时输入123,a=12,取两位
3、滞后赋值
#include <bits/stdc++.h>
using namespace std;
int main(){
int a;//声明变量
scanf("%*d%d",&a);//类型一致
cout<<"输出为:"<<a<<endl;
return 0;12
}
//输入n个数字后,a的值为第二个
四、printf输出
-
语法:printf(“<格式化字符串>”,<参量表>);
-
转换格式为:%[标志][宽度][.精度][类型长度]类型
1、转换为小数
#include <bits/stdc++.h>
using namespace std;
int main(){
float a=12;//声明变量
printf("%.2f",a);//类型一致 ,两位数小数
return 0;
}
//输出为12.00
2、改变位数
#include <bits/stdc++.h>
using namespace std;
int main(){
int a=12;//声明变量
printf("%+6.5d",a);//类型一致
return 0;
}
//6表示长度,后面的.5表示五位数,最后输出为+00012
3、字符串类型
#include <bits/stdc++.h>
using namespace std;
int main(){
const char* a="hello world";//声明变量
printf("*%20.4s*",a);//类型一致
return 0;
}
//20表示字符串宽度,后面的.4表示取的字符数,最后输出为* hell*
五、构造链表
某公司嵌入式软开笔试题:输入一串数字到双向链表中,再将一个数字插入到该单向/双向链表中,最后按从小到大的顺序排列输出
单向链表
# include<iostream>
#include<vector>
using namespace std;
// 单链表
struct ListNode {
int val; // 节点上存储的元素
ListNode* next; // 指向下一个节点的指针
ListNode(int x) : val(x), next(NULL) {} // 节点的构造函数
};
ListNode* creat(vector<int>& vec) {//创建n个节点
ListNode* head = new ListNode(vec[0]);
ListNode* temp = head;
for (int i = 1; i < vec.size(); i++) {
ListNode* node = new ListNode(vec[i]);
temp->next = node;
temp = temp->next;
}
return head;
}
//往链表中插入值为val的节点,尾插法,插在尾部
void insert_list(ListNode* head, int val) {
ListNode* node = new ListNode(val);
if (head == NULL) {
head = node;
}
ListNode* temp = head;
while (temp->next) {
temp = temp->next;
}
temp->next = node;
}
//按照节点值从小到大的顺序进行排序
void sort_list(ListNode* head) {
ListNode* temp = new ListNode(0);
temp = head;
while (temp) {
ListNode* node = head;
while (node->next) {
if (node->next->val < node->val) {
int val = node->next->val;
node->next->val = node->val;
node->val = val;
}
node = node->next;
}
temp = temp->next;
}
delete temp;
}
//输出链表节点值
void print_list(ListNode* head) {
ListNode* temp = new ListNode(0);
temp = head;
while (temp) {
cout << temp->val << " ";
temp = temp->next;
}
cout << endl;
delete temp;
}
int main() {
int a = 5;
vector<int> vec{ 1,2,3,9,6,4 };
//cout << "请输入一串数字:";
//while (cin >> a) {
// vec.push_back(a);
//}
ListNode* head = creat(vec);
cout << "链表节点顺序:" << endl;
print_list(head);
//cout << "请输入要插入的数字:";
//cin >> a;
insert_list(head, a);
insert_list(head, a);
cout << "插入节点后链表节点顺序:" << endl;
print_list(head);
sort_list(head);
cout << "排序后链表节点顺序:"<<endl;
print_list(head);
return 0;
}
双向链表
双向链表的头节点和尾节点是指向NULL的,而不是尾指针指向头节点形成一个环
# include<iostream>
#include<vector>
using namespace std;
// 双向链表 头节点和尾节点都指向NULL
struct ListNode {
int val; // 节点上存储的元素
ListNode* pre; // 指向上一个节点的指针
ListNode* next; // 指向下一个节点的指针
ListNode(int x) : val(x), pre(NULL), next(NULL) {} // 节点的构造函数
};
ListNode* creat(vector<int>& vec) {//创建n个节点
ListNode* head = new ListNode(vec[0]);
ListNode* temp = head;
ListNode* pre_node = head;
for (int i = 1; i < vec.size(); i++) {
ListNode* node = new ListNode(vec[i]);
node->pre = pre_node;
pre_node = node;
temp->next = node;
temp = temp->next;
}
return head;
}
//往链表中插入值为val的节点,尾插法,插在尾部
void insert_list(ListNode* head, int val) {
ListNode* node = new ListNode(val);
if (head == NULL) {
head = node;
}
ListNode* temp = head;
while (temp->next) {
temp = temp->next;
}
temp->next = node;
node->pre = temp;
}
//按照节点值从小到大的顺序进行排序
void sort_list(ListNode* head) {
ListNode* temp = new ListNode(0);
temp = head;
while (temp) {
ListNode* node = head;
while (node->next) {
if (node->next->val < node->val) {
int val = node->next->val;
node->next->val = node->val;
node->val = val;
}
node = node->next;
}
temp = temp->next;
}
delete temp;
}
//输出链表节点值
void print_list(ListNode* head) {
ListNode* temp = new ListNode(0);
temp = head;
while (temp) {
cout << temp->val << " ";
temp = temp->next;
}
cout << endl;
delete temp;
}
int main() {
int a = 5;
vector<int> vec{ 1,2,3,9,6,4 };
//cout << "请输入一串数字:";
//while (cin >> a) {
// vec.push_back(a);
//}
ListNode* head = creat(vec);
cout << "链表节点顺序:" << endl;
print_list(head);
//cout << "请输入要插入的数字:";
//cin >> a;
insert_list(head, a);
insert_list(head, a);
cout << "插入节点后链表节点顺序:" << endl;
print_list(head);
sort_list(head);
cout << "排序后链表节点顺序:"<<endl;
print_list(head);
return 0;
}
六、ACM构造二叉树
说明:输入一个数组,将其转换成二叉树,其中-1代表空节点。
用一个数组来存储二叉树,根据给定的数组构造二叉树
从二叉树 推导到 序列,可以发现这就是层序遍历。
如果父节点的数组下标是i,那么它的左孩子下标就是i * 2 + 1,右孩子下标就是 i * 2 + 2。
构造函数的返回值是二叉树的根节点,力扣上输入变量也是二叉树的根节点
#include<iostream>
#include<vector>
#include <queue>
using namespace std;
struct TreeNode
{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) :val(x), left(NULL),right(NULL) {};
};
//构建二叉树
TreeNode* construct_tree(vector<int> vec, TreeNode* head, int i) {
//如果父节点的数组下标是i,那么它的左孩子下标就是i * 2 + 1,右孩子下标就是 i * 2 + 2
//使用递归
if (i >= vec.size()||vec[i]==-1) return head;//如果i超过数组范围或者此节点为空节点 直接返回
//说明此节点不是空节点
head->val = vec[i];
TreeNode* left = new TreeNode(-1);
head->left = construct_tree(vec, left, 2 * i + 1);
TreeNode* right = new TreeNode(-1);
head->right = construct_tree(vec, right, 2 * i + 2);
return head;
}
//层次遍历法打印二叉树
void print_tree(TreeNode* head) {
queue<TreeNode*> que;//使用队列保存每层的节点
que.push(head);
vector<vector<int>> result;
while (!que.empty()) {
int size = que.size();
vector<int> vec;
for (int i = 0; i < size; i++) {
TreeNode* node = que.front();
que.pop();
vec.push_back(node->val);//注意这个不能放在下面if判断语句里面,因为空节点也需要打印
if (node->val != -1) {//如果node节点不是空节点,可以将左右节点放进队列里面
que.push(node->left);
que.push(node->right);
}
}
result.push_back(vec);
}
for (int i = 0; i < result.size(); i++) {
for (int j = 0; j < result[i].size(); j++) {
cout << result[i][j]<< " ";
}
cout << endl;
}
}
int main() {
vector<int> vec{ 4,1,6,0,2,5,7,-1,-1,-1,3,-1,-1,-1,8 };//用-1代表空指针
TreeNode* head = new TreeNode(-1);
head=construct_tree(vec, head, 0);
print_tree(head);
return 0;
}
输出结果如下:
4
1 6
0 2 5 7
-1 -1 -1 3 -1 -1 -1 8
-1 -1 -1 -1
还有其他一些类似题目:根据前序中序数组重建二叉树等
剑指 Offer 07. 重建二叉树