1. 不用循環和遞歸,實現打印數字0到999。
1 #include <iostream> 2 #include<stdio.h> 3 using namespace std; 4 5 #define A(x) x;x;x;x;x;x;x;x;x;x; 6 7 int main(void) 8 { 9 int n = 0; 10 11 A(A(A(printf("%d\n", n++)))); 12 13 system("pause"); 14 return 0; 15 }
2. 寫一個函數找出一個整數數組中第二大的數。
如:a[10]={1,2,3,4,5,6,7,8,9,10} ==> nextmax = 9;
a[10]={1,2,3,4,5,6,7,10,10,10} ==> nextmax = 7;
a[10]={8,8,8,2,8,8,8,8,8,8} ==> nextmax = 2;
a[10]={8,8,8,8,8,8,8,8,8,8} ==> nextmax = 不存在;
1 // C語言實現如下 2 #include <stdio.h> 3 #include <stdlib.h> 4 5 int getmax(int *p, int n) 6 { 7 //假定第一個數最大,與剩下的數逐一進行比較 8 int maxdata = p[0]; //最大數的值 9 int maxi = 0; //最大數的下標 10 11 for (int i = 1; i < n; i++) 12 { 13 if (maxdata<p[i]) 14 { 15 maxdata = p[i]; 16 maxi = i; 17 } 18 } 19 20 return maxi; //返回下標 21 } 22 23 void swap(int *p1, int *p2) //根據地址交換兩個變量 24 { 25 int temp = *p1; 26 *p1 = *p2; 27 *p2 = temp; 28 } 29 30 31 void main() 32 { 33 int a[10] = { 8,8,8,8,5,8,8,8,8,8 }; 34 //printf("%d\n", getmax(a, 10)); 35 int maxi = getmax(a, 10); //保留最大值的下標 36 int max = a[getmax(a, 10)]; //保留最大值 37 38 swap(&a[0], &a[maxi]); 39 40 int i = 1; 41 int flag = 0; //0代表沒有第二大的數,比如全部相同時 42 while (i<10) 43 { 44 int nextmaxi = i + getmax(a + i, 10-i); //注意下標+1 45 int nextmax = a[nextmaxi]; 46 47 if (max != nextmax) 48 { 49 printf("\nnextmax = %d", nextmax); 50 flag = 1; //代表數組並非全部相同 51 break; 52 } 53 54 swap(&a[i],&a[nextmaxi]); 55 i++; 56 } 57 58 if (!flag) 59 { 60 printf("next max不存在"); 61 } 62 63 system("pause"); 64 return ; 65 }
3. 看程序寫結果:
char str1[] = "abc"; char str2[] = "abc"; const char str3[] = "abc"; const char str4[] = "abc"; const char *str5 = "abc"; const char *str6 = "abc"; char *str7 = "abc"; char *str8 = "abc"; cout << (str1 == str2) << endl; //0 不等 cout << (str3 == str4) << endl; //0 cout << (str5 == str6) << endl; //1 相等 cout << (str7 == str8) << endl; //1
4. 結構體重要考點:
struct name1 { char t; char k; unsigned short i; unsigned long m; }; struct name2 { char str2; short x2; int num2; }; struct name3 { char str3; int num3; short x3; }; printf("%d\n", sizeof(name1)); //8 printf("%d\n", sizeof(name2)); //8 printf("%d\n", sizeof(name3)); //12
5. 用宏定義寫出swap(x,y),即交換兩數。
1 #include <iostream> 2 using namespace std; 3 4 //方法一:加減 5 #define swap(x,y) (x)=(x)+(y);(y)=(x)-(y);(x)=(x)-(y); //注意需要加上() 6 7 //方法二:異或 8 #define swap(x,y) (x)=(x)^(y);(y)=(x)^(y);(x)=(x)^(y); //注意需要加上() 9 10 void main() 11 { 12 int a = 10, b = 20; 13 cout << "交換前:" << endl; 14 cout << "a:" << a << " " << "b:" << b << endl; 15 16 swap(a, b); 17 18 cout << "交換后:" << endl; 19 cout << "a:" << a << " " << "b:" << b << endl; 20 21 system("pause"); 22 return ; 23 }
6. 指針與整數相加: ====>與類型密切相關!
unsigned char *p1; unsigned long *p2; p1 = (unsigned char *)0x801000; p2 = (unsigned long *)0x810000; cout << p1 + 5 << endl; //0x801005 cout << p2 + 5 << endl; //0x810020
7. 數組指針的步長問題:
int a[5] = { 1,2,3,4,5 }; int *ptr = (int *)(&a + 1); printf("%d,%d", *(a + 1), *(ptr - 1)); // 2,5
8. 關於switch,輸出結果是什么:
1 #include <iostream> 2 using namespace std; 3 4 int func(int a) 5 { 6 int b; 7 switch (a) 8 { 9 case 1: 10 b = 30; 11 case 2: 12 b = 20; 13 case 3: 14 b = 10; 15 default: 0; 16 } 17 return b; 18 } 19 20 void main() 21 { 22 printf("%d\n", func(1)); //10 23 24 system("pause"); 25 return ; 26 }
9. 關於malloc的用法:
1 #include <iostream> 2 using namespace std; 3 4 void main() 5 { 6 //char *p = (char *)malloc(0); //分配字節為0,仍然會返回地址,只有分配失敗才會返回NULL 7 //printf("%d\n", p); //5210848 8 9 char *ptr= (char *)malloc(0); 10 if (ptr == NULL) 11 cout << "得到NULL指針" << endl; 12 else 13 cout << "得到非空指針" << endl; 14 15 system("pause"); 16 return ; 17 }
10. 編寫strcpy函數:
已知strcpy函數的原型是char *strcpy(char *strDest,char *strSrc);其中strDest是目的字符串,strSrc是源字符串。
(1)不調用C/C++的字符串庫函數,請編寫出函數strcpy。
1 #include <iostream> 2 #include<assert.h> 3 using namespace std; 4 5 char *strcpy(char *strDest,char *strSrc) 6 { 7 assert((strDest != NULL) && (strSrc != NULL)); //異常處理 8 //if ((strDest == NULL) && (strSrc == NULL)) 9 //{ 10 // cout << "異常..." << endl; 11 //} 12 13 char *address = strDest; 14 while ((*strDest++ = *strSrc++) != '\0') //牛掰的語句,並沒有把語句放在循環體中 15 NULL; 16 return address; 17 } 18 19 void main() 20 { 21 char str1[] = "hello world"; 22 char str2[20]; 23 24 cout << str1 << endl; 25 strcpy(str2, str1); 26 cout << str2 << endl; 27 28 system("pause"); 29 return ; 30 }
(2)strcpy()函數能把strSrc的內容復制到strDest,為什么還要用char * 類型的返回值?
答案:為了實現鏈式表達式,如:
int length = strlen(strcpy(str2, str1));
11. 請編寫一個C函數,該函數給出一個字節中被置1的位的個數。
#include <iostream> using namespace std; unsigned int TestAsOne(char log) { int i; unsigned int num = 0, val; for (i = 0; i < 8; i++) { val = log >> i; //移位 val &= 0x01; //與1相與 if (val) num++; } return num; } void main() { char x = 'a'; int count = TestAsOne(x); cout << count << endl; //3 system("pause"); return ; }
12. 請編寫一個C函數,該函數將給定的一個字符串轉換成整數。
#include <iostream> using namespace std; int invert(char *str) { int num = 0; while (*str!='\0') { int digital = *str - 48; num = num * 10 + digital; str = str + 1; } return num; } void main() { char str[20] = "hello world"; cout << str << endl; int number = invert(str); cout << number << endl; //1186889628 system("pause"); return ; }
13. 請編寫一個C函數,該函數將給定的一個整數轉換成字符串。
void IntToChar(int num, char *pval) { char strval[100]; int i, j; int val0 = 0; int val1 = 0; val0 = num; for (i=0;i<100;i++) { val1 = val0 % 10; //取余 val0 = val0 / 10; //取整 strval[i] = val1 + 48; //數字-->字符 if (val0 < 10) { i++; strval[i] = val0 + 48; break; } } for (j=0;j<=i;j++) //倒置 { pval[j] = strval[i - j]; } pval[j] = '\0'; }
14. 實現strcmp()函數:
已知strcmp函數的原型是 int strcmp(const char *str1,const char *str2),不調用C/C++的字符串庫函數,請編寫函數strcmp。
#include <iostream> #include <assert.h> using namespace std; int strcmp(const char *str1, const char *str2) { assert((str1 != NULL)&&(str2 != NULL)); int ret = 0; while ( !(ret = *(unsigned char *)str1 - *(unsigned char *)str2) && *str2 ) { str1++; str2++; } if (ret > 0) ret = 1; //str1 > str2 else if (ret < 0) ret = -1; //str1 < str2 return ret; } void main() { char str1[] = "aBcDeF"; //a ==>97 char str2[] = "AbCdEf"; //A ==>65 int ret = strcmp(str1, str2); cout << ret << endl; if(ret == 1) cout << "str1 > str2" << endl; else cout << "str1 < str2" << endl; system("pause"); return ; }
15. 請編寫一個C函數,該函數將一個字符串逆序。
#include <iostream> #include <string> #include <algorithm> using namespace std; //方法一: void reverse1(char *str) { char t; //交換的中間變量 for (int i = 0, j = strlen(str) - 1; i < strlen(str) / 2; i++, j--) { t = str[i]; str[i] = str[j]; str[j] = t; } } //方法二: void reverse2(char *str) { char t; //交換的中間變量 int head = 0; //字符數組第一個字符 int tail = strlen(str) - 1; //字符數組最后一個字符 for (; head < tail; head++, tail--) { swap(str[head], str[tail]); } } //方法三:直接調用函數 _strrev() ,注意:strrev()不能對string類型使用 //方法四:直接調用算法中的reverse()函數,需要包含頭文件 #include <algorithm> //方法五:使用replace()函數 void main() { char a[50]; memset(a, 0, sizeof(a)); cin.getline(a, 50, '\n'); //reverse1(a); //reverse2(a); //_strrev(a); reverse(a,a+strlen(a)); //此處本應該用迭代器,改為了指針,正常用法如下: //string s = "hello"; //reverse(s.begin(),s.end()); cout << a << endl; cin.get(); }
16. 請編寫一個 C 函數,該函數在給定的內存區域搜索給定的字符,並返回該字符所在位置索引值。(內存搜索)
int search(char *cpSource,int n,char ch) //起始地址,搜索長度,目標字符 { int i; for (i = 0; i < n && *(cpSource + i) != ch; ++i) { return i; } }
17. 請編寫一個 C 函數,該函數在一個字符串中找到可能的最長的子字符串,該字符串是由同一字符組成的。
int ChildString(char *p) { char *q = p; int stringlen = 0, i = 0, j = 1, len = 0, maxlen = 1; while (*q != '\0') //不能用strlen求得字符串長度 { stringlen++; q++; } while (i<stringlen) { if ( *(p+i)==*(p+j) && j<stringlen ) { len++; //統計子串的長度 i++; j++; } else { if (len>maxlen) //統計最大子串的長度 { maxlen = len + 1; len = 0; } else { len = 0; } i++; j++; } } return maxlen; }
18. 華為面試題:怎么判斷鏈表中是否有環?
【參考答案】答:用兩個指針來遍歷這個單向鏈表,第一個指針p1,每次走一步;第二個指針p2,每次走兩步; 當p2 指針追上 p1的時候,就表明鏈表當中有環路了。
int testLinkRing(Link *head) { Link *t1 = head, *t2 = head; while (t1->next && t2->next) { t1 = t1->next; if (NULL == (t2 = t2->next->next)) return 0; //無環 if (t1 == t2) return 1; //有環 } return 0; }
19. 有一浮點型數組A,用C語言寫一函數實現對浮點數組A進行降序排序,並輸出結果,要求要以數組A作為函數的入口。(建議用冒泡排序法)
#include <iostream> using namespace std; void BubbleSort(double arr[], int n) { int i, j; int exchange = 1; //交換標志 for (i = 1; i < n; i++) //最多做n-1趟排序 { exchange = 0; //本趟排序開始前,交換標志應為假 for(j=n-1;j>=i;j--) //對當前無序區R[i..n]自下向上掃描 if (arr[j + 1] > arr[j]) //交換記錄 { arr[0] = arr[j + 1]; //R[0]不是哨兵,僅做暫存單元 arr[j + 1] = arr[j]; arr[j] = arr[0]; exchange = 1; //發生了交換,故將交換標志置為真 } if (!exchange) //本趟排序未發生交換,提前終止算法 return; } } void main() { double A[20] = { 0 }; int n; cout << "請輸入數組元素的個數( <20 ):" << endl; cin >> n; cout << "請輸入數組的每個元素:" << endl; for (int i = 1; i <= n; i++) cin >> A[i]; cout << "數組如下:" << endl; for (int i = 1; i <= n; i++) cout << A[i] << " "; cout << endl; BubbleSort(A, n); cout << "降序排列結果如下:" << endl; for (int i = 1; i <= n; i++) cout << A[i] << " "; cout << endl; system("pause"); return ; }
20. 實現雙向鏈表刪除一個節點P,在節點P后插入一個節點,寫出這兩個函數。
//刪除操作 Status ListDelete_Dul(DuLinkList &L, int i, ElemType &e) { if (!(p = GetElemP_DuL(L, i))) return ERROR; e = p->data; p->prior->next = p->next; p->next->prior = p->prior; free(p); return OK; } //插入操作 Status ListInsert_DuL(DuLinkList &L, int i, ElemType &e) { if (!(p = GetElemP_DuL(L, i))) return ERROR; if (!(s = (DuLinkList)malloc(sizeof(DuLNode)))) return ERROR; s->data = e; s->prior = p; p->next->prior = s; p->next = s; s->next = p->next->next; return OK; }
21. 讀文件 file1.txt 的內容(例如):
12
34
56
輸出到 file2.txt :
56
34
12
22. 寫一個函數,求一個字符串的長度,在main函數中輸入字符串,並輸出其長度。
#include <iostream> using namespace std; int strLength(char *str) { int length=0; while (*str != '\0') { length++; str++; } return length; } void main() { int len; char str[20]; cout << "請輸入一個字符串:" << endl; cin >> str; len = strLength(str); cout << "字符串的長度為: " << len << endl; system("pause"); return ; }
23. 把一個鏈表反向(鏈表逆置)。
void reverse(test *head) { test *pe = head; test *ps = head->next; while (ps) { pe->next = ps->next; ps->next = head; head = ps; ps = pe->next; } }
24. 有兩個雙向循環鏈表 A,B,知道其頭指針為:pHeadA,pHeadB,請 寫一函數將兩鏈表中 data 值相同的結點刪除。
25. 輸出和為一個給定整數的所有組合。
26. 輸入一行字符,統計其中有多少個單詞。
#include <iostream> using namespace std; int wordCount(string str) { int num = 0, word = 0; char c; for (int i = 0; (c = str[i]) != '\0'; i++) if (c == ' ') word = 0; else if (word == 0) { word = 1; num++; } return num; } void main() { char str[81]; int num; cout << "請輸入一行字符,以回車結束:" << endl; gets_s(str); num=wordCount(str); cout << "共有 " << num << " 個單詞" << endl; system("pause"); return ; }
27. 寫一個內存拷貝函數memcpy(),不用任何庫函數。
#include <iostream> #include <assert.h> using namespace std; //內存拷貝函數: //功能:由src指向地址為起始地址的連續n個字節的數據復制到以destin指向地址為起始地址的空間內。 //返回值:函數返回一個指向dest的指針 //與strcpy相比:memcpy並不是遇到'\0'就結束,而是一定會拷貝完n個字節 //memcpy用來做內存拷貝,可以拿它拷貝任何數據類型的對象,可以指定拷貝的數據長度 void *memcpy(void *dest, const void *src, size_t size) { assert((dest != NULL) && (src != NULL)); char *pdest = (char *)dest; char *psrc = (char *)src; while ( (size--) > 0 ) { *pdest++ = *psrc++; } return pdest; } void main() { char str1[10] = "abcdefghi"; char str2[20]; memcpy(str2, str1, sizeof(str1)); cout << str1 << endl; //abcdefghi cout << str2 << endl; //abcdefghi //若改為如下: char str3[20] = "abcdefghi"; char str4[10]; memcpy(str4, str3, sizeof(str3)); //此時會造成str4內存地址溢出 cout << str3 << endl; cout << str4 << endl; system("pause"); return ; }
【解析】面試中如問到memcpy的實現,要小心了,這里有陷阱。標准的memcpy()函數中,對於地址重疊的情況,該函數的行為是未定義的。事實上陷阱也在於此,自己動手實現memcpy()時就需要考慮地址重疊的情況。
庫函數中的memcpy不能處理src和dest有重疊的情況。如果是自己實現memcpy的話,最好還是把地址有重疊的情況考慮進去,這樣才能更好的體現編碼的嚴謹。
//把地址有重疊的情況考慮進去 void *memcpy(void *dest, const void *src, size_t size) { assert((dest != NULL) && (src != NULL) && (size > 0) ); //添加了size > 0的條件 char *pdest, *psrc; if ((dest > src) && ((char *)dest < (char *)src + size)) //有內存重疊,則從后向前拷貝 { pdest = (char *)dest + size - 1; //指針指向拷貝的最后一個位置 psrc = (char *)src + size - 1; while (size--) { *pdest-- = *psrc--; } } else //沒有內存重疊,從前往后拷貝即可 { pdest = (char *)dest; //指針指向拷貝的起始位置 psrc = (char *)src; while (size--) { *pdest++ = *psrc++; } } return pdest; }
【擴展】memmove和memcpy函數都是C語言中的庫函數,作用是拷貝一定長度的內存的內容,它們的作用是一樣的,唯一的區別就是當內存發生局部重疊的時候,memmove保證拷貝的結果是正確的,memcpy不保證拷貝的結果是正確的。它與memcpy的功能相似,都是將src所指的n個字節復制到dest所指的內存地址起始位置中,但該函數可以處理src和dest有重疊的情況。實際上,memcpy可以看作是memmove的子集。
上面優化后的memcpy()函數實際上就是memmove()函數的實現。
28. 有1、2、3、4個數字,能組成多少個互不相同且無重復數字的三位數?都是多少?
#include <iostream> using namespace std; void main() { int i, j, k,count=0; cout << endl; for(i=1;i<5;i++) for(j=1;j<5;j++) for (k = 1; k < 5; k++) { if (i != j&&i != k&&j != k) { cout << i << "," << j << "," << k << endl; count++; } } cout << "能組成" << count << "個互不相同且無重復數字的三位數" << endl; system("pause"); return ; }
29. 取一個整數a從右端開始的4~7位。
void main() { unsigned a, b, c, d; scanf("%o", &a); b = a >> 4; c = ~(~0 << 4); d = b&c; printf("%o\n%o\n", a, b); }
30. (回文字符串)判斷一個字符串是否是回文字符串。
31. 給定字符串 A 和 B,輸出 A 和 B 中的最大公共子串。
32. 寫一個函數,將一個整數逆轉,例如12345,轉換為54321。
33. 809*??=800*??+9*??+1 其中??代表的兩位數,8*??的結果為兩位數,9*??的結果為3位數。求??代表的兩位數,及809*??后的結果。
#include <iostream> #include <stdio.h> using namespace std; void output(long b, long i) { printf("\n %ld%ld=809*%ld+%ld,b,i,b,ib%i"); } void main() { long int a, b, i; a = 809; for (i = 10; i < 100; i++) { b = i*a + 1; if (b >= 1000 && b <= 10000 && 8 * i < 100 && 9 * i >= 100) output(b, i); } system("pause"); return ; }
34. 某個公司采用公用電話傳遞數據,數據是四位的整數,在傳遞過程中是加密的,加密規則如下:
每位數字都加上5,然后用和除以10的余數代替該數字,再將第一位和第四位交換,第二位和第三位交換。
#include <iostream> using namespace std; void main() { int a, i, aa[4], t; cout << "請輸入一個4位整數:" << endl; cin >> a; aa[0] = a % 10; //個位 aa[1] = a % 100 / 10; //十位 aa[2] = a % 1000 / 100; //百位 aa[3] = a / 1000; //千位 for (i = 0; i <= 3; i++) { aa[i] += 5; aa[i] %= 10; } for (i = 0; i <= 3 / 2; i++) { t = aa[i]; aa[i] = aa[3 - i]; aa[3 - i] = t; } for (i = 3; i >= 0; i--) cout << aa[i]; system("pause"); return ; }
35. 計算字符串中子串出現的次數。
#include <iostream> using namespace std; void main() { char str1[20], str2[20], *p1, *p2; //str1為父串 str2為子串 int sum = 0; cout << "Please input two strings:" << endl; cin >> str1; cin >> str2; p1 = str1; p2 = str2; while (*p1 != '\0') { if (*p1 == *p2) { while (*p1 == *p2 && *p2 != '\0') { p1++; p2++; } } else p1++; if (*p2 == '\0') sum++; p2 = str2; } cout << "子串出現次數為:" << sum << endl; system("pause"); return ; }
36. 有兩個磁盤文件A和B,各存放一行字母,要求把這兩個文件中的信息合並(按字母順序排列),輸出到一個新文件C中。
#include <iostream> using namespace std; void main() { FILE *fp; int i, j, n, ni; char c[160], t, ch; if ((fp = fopen("A", "r")) == NULL) { cout << "file A cannot be opened" << endl; exit(0); } cout << "A contents are:" << endl; for (i = 0; (ch = fgetc(fp)) != EOF; i++) { c[i] = ch; putchar(c[i]); } fclose(fp); ni = i; if ((fp = fopen("B", "r")) == NULL) { cout << "file B cannot be opened" << endl; exit(0); } cout << "B contents are:" << endl; for (i = 0; (ch = fgetc(fp)) != EOF; i++) { c[i] = ch; putchar(c[i]); } fclose(fp); n = i; for(i=0;i<n;i++) for(j=i+1;j<n;j++) if (c[i] > c[j]) { t = c[i]; c[i] = c[j]; c[j] = t; } cout << "C file is:" << endl; fp = open("C", "w"); for (i = 0; i < n; i++) { putc(c[i], fp); putchar(c[i]); } fclose(fp); system("pause"); return ; }
37. 寫一個函數strlen(),求一個字符串的長度。
38.寫出二分查找的代碼。
#include <iostream> using namespace std; int binary_search(int *arr, int key, int n) { int low = 0; int high = n - 1; int mid; while (low <= high) { mid = (low + high) / 2; if (key < arr[mid]) high = mid - 1; else if (key > arr[mid]) low = mid + 1; else return mid; } return -1; } void main() { int A[] = { 1,3,5,7,9,11,13,15,17 }; int len = sizeof(A) / sizeof(A[0]); int key; cout << "數組如下:" << endl; for(int i=0;i<len;i++) cout << A[i] << " "; cout << endl; cout << "請輸入待查找的關鍵字key:" << endl; cin >> key; int ret=binary_search(A, key, len); if (-1 == ret) cout << "沒有找到,數組中無關健值" << key << endl; else cout << "已找到關鍵值" << key << ",它是A[" << ret << "]" << endl; system("pause"); return ; }