C语言的一点复习
都忘光了,拿来复习一小下
运行环境Win7 VS2010
题目是某年和某年华为的某几道上机题目,题目不去找了。
【第一个】
就是实现一个方法,将链表倒序。
#include "stdafx.h" #include<iostream> typedef struct tagListNode{ int value; struct tagListNode *next; }ListNode; void converse(ListNode **head){ ListNode *currentNode = *head; ListNode *privNode = NULL; ListNode *nextNode = NULL; while(currentNode!=NULL){ nextNode = (*currentNode).next; (*currentNode).next = privNode; privNode = currentNode; currentNode = nextNode; } *head = privNode; } void PrintList(ListNode **head){ ListNode *currentNode = *head; while(currentNode!=NULL){ printf_s("%d",(*currentNode).value); currentNode = (*currentNode).next; } printf_s("\n"); } void main(){ ListNode *head; ListNode *body1; ListNode *body2; ListNode *tail; head = (ListNode *)malloc(sizeof(ListNode)); body1 = (ListNode *)malloc(sizeof(ListNode)); body2 = (ListNode *)malloc(sizeof(ListNode)); tail = (ListNode *)malloc(sizeof(ListNode)); (*head).next = body1; (*head).value = 1; (*body1).next = body2; (*body1).value = 2; (*body2).next = tail; (*body2).value = 3; (*tail).next = NULL; (*tail).value = 4; ListNode **phead = &head; PrintList(phead); converse(phead); PrintList(phead); getchar(); }
结构体做链表的时候是要申请内存的。
*pi = i;和pi = &i;的理解
二级指针还是得再理解理解。
这块为啥用二级指针呢,因为这个函数不是靠返回值的,操作完之后,链表的头是之前的尾巴,如果我们只是将链表的头传进来,注意链表的头指向的地址是结构体的地址,如果我们粗暴地让它指向尾巴,那么这个结构体就丢了,当然可以通过一系列交换操作,但是毫无疑问会很麻烦。用二级指针的话,这个二级指针是一个链表以外的东西,链表无论怎么动,这个东西指向谁都可以再去确定。也就是在我们操作完之后再叫二级指针指向尾巴就好了。
【第二个】
将字符串里面的所有空格换成逗号,多个换成一个。
#include "stdafx.h" #include<iostream> using namespace std; void DevideString(const char *pInputStr, long lInputLen, char *pOutputStr){ int i, j; for(i=0; pInputStr[i]==' '; i++); for(j=0; i<lInputLen; i++){ if(pInputStr[i]!=' '){ pOutputStr[j] = pInputStr[i]; j++; }else if(pInputStr[i+1]!=' '){ pOutputStr[j] = ','; j++; }else{ ; } } pOutputStr[j] = ','; pOutputStr[j+1] = '\0'; } void main(){ while(1){ char *strIn = (char *)malloc(sizeof(char)*1024); char *strOut = (char *)malloc(sizeof(char)*1024); scanf_s("%[^\n]", strIn,1024); //cout<<strlen(strIn); DevideString(strIn, strlen(strIn), strOut); cout<<strOut<<endl; getchar(); } }
scanf_s与scanf的区别是后面要加一个确定读取长度的参数。还有这个函数会吃掉空格,利用正则表达式来简单解决一下,如代码所示。
字符串的结束标志是'\0'(大概
【第三个】
字符串的去重并排序
#include "stdafx.h" #include<iostream> using namespace std; void sort(char* s, int len){ int dup = 0; for(int i=0; i<len-1; i++){ for(int j=i+1; j<len;j++){ if(s[i]!='z'+1 && s[i]==s[j]){ s[j] = 'z'+1; dup++; } } } for(int i=0; i<len-1; i++){ for(int j=0; j<len-1;j++){ if(s[j]>s[j+1]){ char temp = s[j]; s[j] = s[j+1]; s[j+1] = temp; } } } len-=dup; s[len] = '\0'; cout<<s<<endl; } void main(){ char s[1024]; while(1){ cin>>s; int len = strlen(s); sort(s,len); } }
明明做的时候总有麻烦,回头一看又感觉没啥难的= =
【第四个】
给你1 2 3 4 5 6 7 8 9中间放+-或者不放,给定结果输出得到这个结果的式子有多少个
#include"stdafx.h" #include<iostream> using namespace std; int cou = 0; int all = 0; int result; char ops[] = {'1',' ','2',' ','3',' ','4',' ','5',' ','6',' ','7',' ','8',' ','9','='}; void mydfs(int layer, char lastop, int lastSum, int currentSum){ if(layer!=1) ops[layer*2-3] = lastop; int currentNum = 0; if(lastop == '+'){ currentNum = layer; } if(lastop == '-'){ currentNum = -1*layer; } if(lastop == ' '){ if(lastSum>0) currentNum = lastSum*10+layer; if(lastSum<0) currentNum = lastSum*10-layer; } if(layer==9){ cou++; //cout<<layer<<"|"<<cou<<"\n"; if(currentSum+currentNum == result){ all++; cout<<ops<<result<<endl; } return; } mydfs(layer+1, '+', 0, currentSum+currentNum); mydfs(layer+1, '-', 0, currentSum+currentNum); mydfs(layer+1, ' ', currentNum, currentSum); } void main(){ while(1){ all = 0; cin>>result; mydfs(1, '+', 0, 0); cout<<all<<endl; getchar(); } }
去年大约这个时候我也做过这个题,一塌糊涂做不出来,虽然这个也有参考别人的代码,但是还是有自己的理解的。
其实就是遍历了所有的结果,之前的想法是将可能的符号做成类似表格的东西,但是结果就是很困难,一个是组合的时候你得考虑这个对应的符号是什么,另一个你得考虑字符串转数字。
这个是利用了递归,就是每一种可能的情况都去验证接下来的三种可能,在达到结束条件的时候结束,类似的问题都可以考虑这种解决方案。
递归要涉及一个“边界”问题,就是开头和结束的地方该怎么处理,像我这个程序里面,就是为1的时候怎么怎么办,然后为9的时候又做了些什么,其他的时候函数的操作应该都是完全一样的。
突然想起来以前写过一个扫雷,大约是大二的时候,console的,很简陋,代码所在的硬盘已经死了。
那个代码里面用了递归,但是效率很低很低,虽然运行时没有问题的。有空可以作死一下。