描述
编写一个C程序,实现两个分数的加减法
输入
输入包含多行数据
每行数据是一个字符串,格式是"a/boc/d"。
其中a, b, c, d是一个0-9的整数。o是运算符"+"或者"-"。
数据以EOF结束
输入数据保证合法
输出
对于输入数据的每一行输出两个分数的运算结果。
注意结果应符合书写习惯,没有多余的符号、分子、分母,并且化简至最简分数
样例输入
1/8+3/8
1/4-1/2
1/3-1/3
样例输出
1/2
-1/4
0
题目比较有意思,代码如下:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a,b,c,d,x,y;
char o;
while(scanf("%d/%d%c%d/%d",&a,&b,&o,&c,&d)!=EOF)
{
x=a*d;y=b*d;
c=c*b;d=d*b;
if(o=='+')
{
x=x+c;
if(x%y==0)
printf("%d\n",x/y);
if(x%y!=0)
{
int i=2;
for(i;i<=y;i++)
{
if(x%i==0&&y%i==0)
{
x=x/i;y=y/i;
i=2;
}
}
printf("%d/%d\n",x,y);
}
}
if(o=='-')
{
x=x-c;
if(x%y==0)
printf("%d\n",x/y);
if(x%y!=0)
{
int i=2;
for(i;i<=y;i++)
{
if(x%i==0&&y%i==0)
{
x=x/i;y=y/i;
i=2;
}
}
printf("%d/%d\n",x,y);
}
}
}
return 0;
}
实现两个分数的加减法编写一个C程
#include <stdio.h>
int a,b,c,d;
int yuefen(int fenzi,int fenmu)//找最大公约数
{
int da=fenzi,xiao=fenmu;
if(da<xiao)
{
int t=da;
da=xiao;
xiao=t;
}
while(da%xiao!=0)
{
da=da/xiao;
if(da<xiao)
{
int t=da;
da=xiao;
xiao=t;
}
}
return xiao;
}
int main()
{
char s[7];
while(scanf("%s",s)!=EOF)
{
a=s[0]-48;
b=s[2]-48;
c=s[4]-48;
d=s[6]-48;
if(s[3]=='+')
{
if(a==0&&c==0)//0和一个数不能找最大公约数
{
printf("0\n");
}
else
{
int fenzi=a*d+c*b;
int fenmu=b*d;
int gongyueshu=yuefen(fenzi,fenmu);
fenzi=fenzi/gongyueshu;
fenmu=fenmu/gongyueshu;
if(fenmu==1)//分母为1只输出分子
{
printf("%d\n",fenzi);
}
else
{
printf("%d/%d\n",fenzi,fenmu);
}
}
}
if(s[3]=='-')
{
if((double)a/b<(double)c/d)//先判断大小
{
int fenmu=b*d;
int fenzi=b*c-a*d;
int gongyueshu=yuefen(fenzi,fenmu);
fenzi=fenzi/gongyueshu;
fenmu=fenmu/gongyueshu;
if(fenmu==1)//分母为1只输出分子
{
printf("-%d\n",fenzi);
}
else
{
printf("-%d/%d\n",fenzi,fenmu);
}
}
else
{
if((a==c&&b==d)||(a==0&&c==0))//分子为0
{
printf("0\n");
}
else
{
int fenmu=b*d;
int fenzi=a*d-b*c;
int gongyueshu=yuefen(fenzi,fenmu);
fenzi=fenzi/gongyueshu;
fenmu=fenmu/gongyueshu;
if(fenmu==1)//分母为1只输出分子
{
printf("%d\n",fenzi);
}
else
{
printf("%d/%d\n",fenzi,fenmu);
}
}
}
}
}
return 0;
}
1)线程的同步互斥
(2)进程之间通信问题:管道,有名管道,信号,消息队列,共享内存,信号量,套接字socket
(3)select函数有什么作用:send,read,accept函数都会导致阻塞,而Linux的select函数可以使我们在程序中同时监听多个文件描述符的读写状态,程序会停在select这里等待,直到被监视的文件描述符有某一个或者多个状态改变。select的机制中提供一fd_set的数据结果,实际上是一long类型的数组,每一个数组元素都能与一打开的文件描述符建立联系,当调用select时,由内核根据IO状态修改fd_set的内容,由此来通知执行了select的进程哪一socket或文件可读。
(4)死锁,如何避免死锁:两个或者两个以上的进程在执行的过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,如果没有外力作用,它们都将无法推荐下去。此时称系统状态或者系统产生了死锁,这些永远在相互等待的进程称为死锁进程。
(5)信号量对应的函数:
(6)TCP的三次握手
(7)TCP和UDP的区别
(8)TCP的建立以及对应的函数
服务器:socket,bind,listen,accept,send,recv,closesocket....
客户端:socket,connect,recv,send
(9)UDP的建立以及对应的函数
服务器:socket,bind,recvfrom...
客户端:socket,sendto
(10)如何创建一个线程:pthread_create
(11)多线程怎么退出,是在创建的子进程内退出还是在主程序里面退出
(12)网络字节序:htons将主机的无符号短整形数转换成网络字节顺序
(13)TCP的报文格式
(14)PayLoad里面放了些什么
(15)什么叫流式传输,什么是报文传输
(16)UDP为什么是无链接的
(17)线程和进程的区别
(18)进程通信
(19)临界区是什么
(20)GDB调试
(21)Shell编程
(22)C语言的编译过程:编辑、预处理、编译、连接
(23)C语言的内存是如何排布的
(24)栈和堆的区别
(25)volatile
(26)sizeof和strcpy
(27)memcpy和strcpy的区别:
- 复制的内容不同:strcpy只能复制字符串,而memcpy可以复制任意内容,比如字符数组,整形,结构体,类等等
- 复制的方法不同:strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,所以容易溢出。memcpy则是根据其3个参数决定复制的长度
- 用途不同:通常复制字符串用strcpy,而需要复制其他类型数据一般用memcpy
(28)fwrite和write的区别
(29)strstr是干嘛的:strstr(str1, str2)函数用于判断字符串str1是否是str2的子串。
(30)指针
(31)结构体内存对齐
(32)结构体拷贝问题
(33)字符串常用操作函数
(34)栈里面放了什么东西
(35)冒泡排序法、字符串反转[现场写]
(36)判断链表有环、链表反转[现场写]
(37)静态链接和动态链接的区别
(38)大小端问题
(39)网络编程的一般流程
(40)中断模型
(41)设备模型
(42)proc文件系统
(43)gcc的编译选项
(44)makefile
(45)驱动想要被外部看到应该怎么样:export
(46)如何安装驱动程序
(47)RTSP的端口
(48)HI3518EV200支持的最大分辨率
(49)uboot是如何引导内核的
(50)uboot是怎么给内核传参的
(51)nfs服务器用来干嘛
(52)busybox
(53)如何调试程序
(54)快速排序【现场写】
(55)如何用UDP实现安全传输
(56)众多客户端,如何在服务端判断哪个客户端是否关闭,如果是光机,又是如何判断的
(57)typedef 和#define的区别
(58)“编译”前,计算机做了什么。“编译后”,计算机得到了什么
(59)struct和union的区别
(60)怎么引用数组元素,可以*p[i]吗?
(61)动态分配的内存,局部变量,静态变量分别存放在哪里
(62)linux中栈分配大小默认是多少
(63)什么是红黑树
(64)数据结构,二叉树
(65)TCP如何检测包错误
(66)线程资源要不要回收
(67)线程同步的作用
(68)UDP如何实现可靠性
(69)ip协议和icmp协议分别在哪一层
(70)linux的权限管理
(71)gcc命令
冒泡排序法
我们已经知道了将N个整数按从小到大排序的冒泡排序法。本题要求将此方法用于字符串序列,并对任意给定的K(<N),输出扫描完第K遍后的中间结果序列。
输入格式:
输入在第1行中给出N和K(1<=K<N<=100),此后N行,每行包含一个长度不超过10的、仅由小写英文字母组成的非空字符串。
输出格式:
输出冒泡排序法扫描完第K遍后的中间结果序列,每行包含一个字符串。
输入样例:
6 2
best
cat
east
a
free
day
输出样例:
best
a
cat
day
east
free
要注意首字母相同的情况,以及最大情况:字符数10个,再加上一个换行字符,
-
#include <stdio.h>
-
#include <string.h>
-
int main()
-
{
-
int m,n;
-
while(scanf("%d%d",&m,&n)!=EOF)
-
{
-
char a[101][11];
-
char b[11];
-
int i,j;
-
for(i=0;i<m;i++)
-
scanf("%s",&a[i]);
-
for(j=0;j<n;j++)
-
{
-
for(i=0;i<m-1-j;i++)
-
{
-
if(strcmp(a[i],a[i+1])>0)
-
{
-
strcpy(b,a[i]);
-
strcpy(a[i],a[i+1]);
-
strcpy(a[i+1],b);
-
}
-
}
-
}
-
for(i=0;i<m;i++)
-
printf("%s\n",a[i]);
-
}
-
return 0;
-
}
字符串反转
-
#include<stdio.h>
-
#include<string.h>
-
//编写一个字符串反转函数
-
void reverse_string(char *l,char *r)
-
{
-
char temp;
-
while(l < r)
-
{
-
temp = *l; //进行值的交换
-
*l = *r;
-
*r = temp;
-
l++;
-
r--;
-
}
-
}
-
//reverse 用于找到新单词,并且调用上面的函数反转
-
void reverse(char str[],int n)
-
{
-
int i = 0; //定义i表示数组的下标
-
char *l = str; //定义指针l用来指向单词的每个单词首字母出现的位置
-
char *r = str; //定义指针r用来指向单词的每个单词尾的空格位置
-
while(str[i]) //当这个字符串中的字符不为'\0'时
-
{
-
if(str[i] == ' ') //当出现空格的时候交换这个反转这个单词
-
{
-
reverse_string(l,r-1);
-
l = ++r; //使l指向下一个单词的首字母
-
}
-
else
-
{
-
r++; //如果还没出现空格,使l往后值,寻找空格;
-
}
-
i++; //整个while循环中,i必须往后加;
-
}
-
reverse_string(str,str+n-1);//反转每个单词后,再将整个字符串反转
-
}
-
int main()
-
{
-
char ch[] = "student a am i";
-
reverse(ch,strlen(ch)); //在这里只需调用reverse函数即可
-
printf("%s\n ",ch);
-
return 0;
-
}
链表反转
#include <iostream>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <list>
#include <algorithm>
using namespace std;
/*
链表反转
1. 注意用一个变量存储cur节点的下一个结点,不要断链即可
*/
struct ListNode
{
ListNode *next;
int val;
ListNode(int x) : val(x), next(nullptr) {}
};
ListNode *reverList(ListNode *head)
{
if (head == nullptr)
return nullptr;
ListNode *pre = head;
ListNode *cur = head->next;
ListNode *post = nullptr;
while (cur != nullptr)
{
post = cur->next;
cur->next = pre;
pre = cur;
cur = post;
}
return pre;
}
int main()
{
ListNode *p = new ListNode(1);
ListNode *p1 = new ListNode(2);
ListNode *p2 = new ListNode(3);
ListNode *p3 = new ListNode(4);
p->next = p1;
p1->next = p2;
p2->next = p3;
ListNode *res = reverList(p);
for (int i = 0; i < 4; ++i)
{
cout << res->val << " ";
res = res->next;
}
cout << endl;
system("pause");
return 0;
}
判断链表是否有环
-
#include <iostream>
-
#include <vector>
-
#include <stack>
-
#include <map>
-
#include <set>
-
#include <list>
-
#include <algorithm>
-
using namespace std;
-
/*
-
链表有环
-
1. 是否存在环:一个走一步,一个走两步,判断是否会相遇
-
2. 找出环的入口:分别用一个指针(ptr1, prt2),同时从head与slow和fast的相遇点出发,
-
每一次操作走一步,直到ptr1 == ptr2,此时的位置也就是入口点
-
*/
-
struct ListNode
-
{
-
ListNode *next;
-
int val;
-
ListNode(int x) : val(x), next(nullptr) {}
-
};
-
bool ifCircle(ListNode *head)
-
{
-
if (head == nullptr)
-
return 0;
-
ListNode * fast = head; //每次走两步
-
ListNode * slow = head; //每次走一步
-
while (fast != nullptr && fast->next != nullptr)
-
{
-
slow = slow->next;
-
fast = fast->next->next;
-
if (slow == fast)
-
return true;//有环
-
}
-
return false;
-
}
-
ListNode* circleStart(ListNode *head)
-
{
-
if (head == nullptr)
-
return nullptr;
-
ListNode * fast = head; //每次走两步
-
ListNode * slow = head; //每次走一步
-
while (fast != nullptr && fast->next != nullptr)
-
{
-
slow = slow->next;
-
fast = fast->next->next;
-
if (slow == fast)
-
break;//有环
-
}
-
if (fast == nullptr && fast->next == nullptr)
-
return nullptr;
-
ListNode *ptr1 = head;
-
ListNode *ptr2 = slow;
-
while (ptr1 != ptr2)
-
{
-
ptr1 = ptr1->next;
-
ptr2 = ptr2->next;
-
}
-
return ptr1;
-
}
-
int main()
-
{
-
ListNode *p = new ListNode(1);
-
ListNode *p1 = new ListNode(2);
-
ListNode *p2 = new ListNode(3);
-
ListNode *p3 = new ListNode(4);
-
p->next = p1;
-
p1->next = p2;
-
p2->next = p3;
-
p3->next = p2;
-
int res = ifCircle(p);
-
cout << res << endl;
-
ListNode *ans = circleStart(p);
-
cout << ans->val << endl;
-
system("pause");
-
return 0;
}
快速排序
1 待排序数组首地址
2 数组中待排序元素数量
3 各元素的占用空间大小
4 指向函数的指针,用于确定排序的顺序
C++版本
#include <iostream>
using
namespace
std;
void
Qsort(
int
a[],
int
low,
int
high)
{
if
(low >= high)
{
return
;
}
int
first = low;
int
last = high;
int
key = a[first];
/*用字表的第一个记录作为枢轴*/
while
(first < last)
{
while
(first < last && a[last] >= key)
{
--last;
}
a[first] = a[last];
/*将比第一个小的移到低端*/
while
(first < last && a[first] <= key)
{
++first;
}
a[last] = a[first];
/*将比第一个大的移到高端*/
}
a[first] = key;
/*枢轴记录到位*/
Qsort(a, low, first-1);
Qsort(a, first+1, high);
}
int
main()
{
int
a[] = {57, 68, 59, 52, 72, 28, 96, 33, 24};
Qsort(a, 0,
sizeof
(a) /
sizeof
(a[0]) - 1);
/*这里原文第三个参数要减1否则内存越界*/
for
(
int
i = 0; i <
sizeof
(a) /
sizeof
(a[0]); i++)
{
cout << a[i] <<
""
;
}
return
0;
}
/*参考数据结构p274(清华大学出版社,严蔚敏)*/
C语言版本
void
sort(
int
*a,
int
left,
int
right)
{
if
(left >= right)
/*如果左边索引大于或者等于右边的索引就代表已经整理完成一个组了*/
{
return
;
}
int
i = left;
int
j = right;
int
key = a[left];
while
(i < j)
/*控制在当组内寻找一遍*/
{
while
(i < j && key <= a[j])
/*而寻找结束的条件就是,1,找到一个小于或者大于key的数(大于或小于取决于你想升
序还是降序)2,没有符合条件1的,并且i与j的大小没有反转*/
{
j--;
/*向前寻找*/
}
a[i] = a[j];
/*找到一个这样的数后就把它赋给前面的被拿走的i的值(如果第一次循环且key是
a[left],那么就是给key)*/
while
(i < j && key >= a[i])
/*这是i在当组内向前寻找,同上,不过注意与key的大小关系停止循环和上面相反,
因为排序思想是把数往两边扔,所以左右两边的数大小与key的关系相反*/
{
i++;
}
a[j] = a[i];
}
a[i] = key;
/*当在当组内找完一遍以后就把中间数key回归*/
sort(a, left, i - 1);
/*最后用同样的方式对分出来的左边的小组进行同上的做法*/
sort(a, i + 1, right);
/*用同样的方式对分出来的右边的小组进行同上的做法*/
/*当然最后可能会出现很多分左右,直到每一组的i = j 为止*/
}