C面經——基礎部分

2020-08-09 11:54:05

1、計算機內部的記憶體單位換算

	1G = 2^10 M = 2 ^ 20 K = 2 ^30 B
	1B = 8bit
	例:100萬個整形數據佔多大?
	答:1M

2、fwrite函數的參數是什麼?

答:int fwirte(const void *ptr,int size,inr count,FILE * stream)
		ptr:指向儲存數據的指針
		size:每個數據型別的大小
		count:數據個數
		stream:檔案指針
	擴充套件:給定一個檔案,如何計算檔案的大小?提示:使用fseek和ftell
#include<stdio.h>
#include<assert.h>
int main()
{
	FILE *p;
	int len;
	P = fopen("xxxx.xxxx","r");
	assert(p != NULL);
	fseek(p,0,SEEK_SET);
	len = ftell(p);
	printf("%d",len);
	return 0;
};

3、extern關鍵字的作用

在一個檔案中參照另一個檔案的變數或者函數
在C++語言中穿插C語言就需要使用extern 「C」{}將程式碼括起來

4、malloc,calloc,realloc的作用和區別

  1. C語言動態開闢記憶體有三個函數,分別是malloc,calloc,realloc,釋放記憶體的只有一個函數free
  2. malloc是使用最多也是最簡單的,只需要一個參數(開闢記憶體空間的大小),如果堆內有連續空間可以滿足使用者需求,則返回記憶體首地址,否則返回NULL;
  3. calloc實在malloc的基礎上將分配好的每個位元組賦值爲0;
  4. realloc函數之前開闢的儲存空間改變爲給定的大小size。 size可以是任意大小,大於或小於原尺寸都可以。
    返回值是指向新空間的指針,如果錯誤發生返回NULL。

(重點)開闢空間之後一定要free釋放,否則會導致記憶體漏失問題

5、strcpy爲什麼不安全?(西安諾瓦科技)

因爲如果被拷貝字串長度大於「空」字串的長度的話會造成月結問題,所以說是不安全的。
因此使用strcpy_s(const char * p1,sizof(p2),const char *p2)函數

6、大小端問題

小端:低地址存放低位元組數據
大端:低地址存放高位元組數據

例:如何測試大小端?
方法有很多:可以使用指針偏移,可以使用聯合體等

bool is_big()
{
	short int a = 0x1234;
	char b = (char)a;
	if(b == 0x12)
	{
		return true;
	}
	return false;
};


bool is_big()
{
	union num
	{
	 	int a;
	 	char b;
	 }:
	 num p.a = 0x1234;
	 if(p.b == 0x12)
	 {
	 	return true;
	 }
	 return false;
};
*
	 

7、二分查詢

二分查詢也稱爲折半查詢,二分查詢的前提是數據必須有序!!!
有重複的數位返回其左邊的數據

//非遞回方式
int BinSearch(int *arr,int left,int last,int val)
{
//left左位置下標 last右位置下標
	assert(arr != NULL);
	
	while(left <= right)
	{
		int order =(ringht + left) / 2;
		if(arr[order] == val)
		{
			if(arr[order - 1] = val) order -= 1;
			return order;
		}
		if(arr[order] > val)
		{
			left = order;
		}
		if(arr[order] < val)
		{
			right = order;
		}
	}
	return -1;	
}

	

8、static關鍵字的用法和作用

static主要是定義全域性靜態變數,定義區域性靜態變數,定義靜態函數。
一、定義靜態變數:在全域性變數前面加上static關鍵字
特點:1、如果初始化且初始化不爲0的在.data分配記憶體,如果沒有初始化或者初始化爲0的在.bss儲存
2、如果沒有初始化,其預設值爲0
3、該變數在本檔案定義到檔案結束可見
二、定義靜態函數;在函數返回值型別加上static關鍵字,函數即被定義成靜態函數。
特點:1、靜態函數只能在本檔案中使用
2、在檔案作用域中宣告的inline函數預設爲static
3、在C++中,靜態成員方法與類相聯繫,不依賴物件呼叫。靜態成員函數不能存取非靜態數據成員。
4、靜態成員函數和靜態成員都沒有this指針。
在《C深度剖析》中有一道很經典的題
在这里插入图片描述
問i和j的值分別是多少?

9、括號匹配問題(深信服)

使用棧從左到右依次入棧,當入棧第一個右括號的時候找到距離棧頂最近的第一個左括號與其匹配,然後將兩個括號之間的所有元素或者符號出棧。

10、魔方陣

魔方陣,是指元素爲自然數1、2、3、4…n^2的n*n的模擬,其中無重複元素,且每行、每列以及主、副對角線上個n個元素之間的和相等
奇數魔方陣構造演算法描述如下:
1、數位1方陣第一行中間。
2、當數位放在前一個數字的上一行,後一列,注意如果已經到頂行則上一行爲最後一行即把線性看着環形
3、如果當前位置有已經有數據,則放在前一個數字的下一行,同列

#define N 15
#define M N
void MagicMatrix()
{
	int arr[N][M] = {0};
	assert(N % 2 != 0);
	int curn = 0;
	int curm = curn / 2;
	arr[curn][curm] = 1;
	for(int i = 2;i < M * N;++i)
	{
		curn--;
		if(curn < 0)
		{
			curn = N - 1;
		}
		curm = (curm + 1) % N;
		if(arr[curn][curm] != 0)
		{
			curn = (curn + 2) % N;
			curm = (curm - 1 + M) % M;
		}
		arr[curn][curm] = i;
	}
}

11、翻轉句子中的單詞順序,但是單詞內字元順序不變

void str_reverse(char *start,char *end)
{
	char temp;
	while(start < end)
	{
		temp = *start;
		*start = *end;
		*end = temp;
		start++;
		end--:
	}
}
char* str_reverse(char *sen)
{
	char *start = sen;
	char *end = sen + sizeof(sen) - 1;
	str_reverse(start,end);//先反轉所有句子,包括單詞
	end = start;
	while(*start != '\0');
	{
		if(*end == ' ' || *end == '\0')
		{
			str_reverse(start,end - 1);
			if(*end == '\0')break;
			end += 1;
			start = end;
		}
		else
		{
			++end;
		}
	}
	return sen;
}
	
int main()
{
	char str[] = "hello,i am a student!";
	char *res = str_reverse(str);
	printf("%s\n",res);
	return 0;
}

12、指針和陣列的區別

1、大小不同,在32位元系統下是四個位元組,陣列大小爲陣列長度*sizeof(陣列單元格):sizeof(arr) / sizeof(arr[0].
2、存取許可權不同,陣列arr指向的永遠是陣列的開頭元素不能移動,指針可以發生移動
3、存取方式不同,arr[i] 是在陣列名後面偏移i個單元格,然後取值,而p[i]是先將p的值加上i然後再跳轉地址取值。

13、回圈陣列

環形陣列在遍歷完最後一個下標後不結束,而是將陣列的第一個元素作爲最後一個元素的下一個
約瑟夫環

#define NUM 3
int joseph(int n)
{
	assert(n > 0);
	int *arr = (int *)malloc(n * sizeof(int));
	int i = 0 ;
	int count = n;
	int tmp = 0;
	for(i = 0;i < n;i++)
	{
		arr[i] = 1;
	}
	i = 0;
	while(count > 1)
	{
		if(arr[i] == 1)
		{
			tmp++;
			if(tmp == NUM)
			{
				arr[i] = 0;
				tmp = 0;
				count--;
			}
		}
		i++;
		if(i == n)
		{
			i = 0
		}
	}
	for(i = 0;i < n;i++)
	{
		if(arr[i] ==1)
		{
			break;
		}
	}
	free(arr);
}
int main()
{
	printf("%d\n",joseph(1));
	printf("%d\n",joseph(2));
	printf("%d\n",joseph(3));
	printf("%d\n",joseph(4));
	return 0;
}

14、數位判斷(葡萄城)

題目描述: 判斷一個字串是否是一個十進制數位 。

題目要求:

  1. 不允許使用正則或者框架或者第三方提供的判斷數位的方法。需要自行實現判斷邏輯
  2. 需要支援用科學計數法表示的數位

範例:

以下字串是合法的十進制數位:
0
123
1.23
-123
1.23E+10
以下字串是不合法的十進制數位:
000
123abc
.123
0.1.2

/*
範例型別展示不太齊全:"01"是否屬於十進制範疇,在下述程式碼中將其視爲非十進制數
*/
#define MAXINT 2147483647
bool  Str_Dec(const char *str)
{
	long long max = 0;
	bool res = true;
	int tag1 = 0;//小數點標誌位
	int tag2 = 0;//科學計數標誌位
	while ('\0' != *str)
	{
		if (isdigit(*str))
		{

			++str;
		}
		else
		{
			if (*str == '.' && tag1 == 0)
			{
				str++;
				tag1++;
				continue;
			}
			else
			{
				if ((*str == 'e' || *str == 'E') && (*(str + 1) == '-' || *(str + 1) == '+') && tag2 == 0)
				{
					str += 2;
					tag2++;
					continue;
				}
				else
				{
					res = false;
					return res;
				}
			}
		}
	}
	return res;
}
bool judge(const char *str)
{
	int res = false;
	if (!isdigit(*str))
	{
		if (*str == '+' || *str == '-')
		{
			str++;
			res = Str_Dec(str);
		}
		return res;
	}
	else
	{
		if (*str == '0' && *(str + 1) == '\0')
		{
			res = false;
			return res;
		}
		res = Str_Dec(str);;
	}
	return res;
}
int main()
{
	const char *ptr = "0100.0.0000004";
	bool res = judge(ptr);
	if (res == false)
	{
		printf("字串:%s不是十進制數位", ptr);
	}
	else
	{
		printf("字串:%s是十進制數位", ptr);
	}
	return 0;
}

15、楊輝三角

題目5:楊輝三角
程式語言:不限

題目描述: 楊輝三角是我國古代一個重要的數學成就 。
楊輝三角是一個滿足以下條件的幾何排列:

  1. 每個數等於它上方兩數之和。
  2. 每行數位左右對稱,由1開始逐漸變大。
    第 n 行的數位有 n 項。
    請編寫一個程式,按題目要求輸出楊輝三角中第 n 行第 m 個數字。
    輸入
    第一行,兩個數位 n 和 m ,表示需要輸出的數位在楊輝三角上的位置,行列均從 1 開始,(1<=n,m<=10000),以空格分隔。
    輸出
    僅包含一個整數,即楊輝三角中第 n 行第 m 列處的數位。
    輸入範例
    7 5
    輸出範例
    15
    題解:除了前兩行每一行都遵循一定的規律,故用遞回。



int triangle(int n, int m)
{
	if (n == m || m == 1)
	{
		return 1;
	}
	return triangle(n - 1, m - 1) + triangle(n - 1, m);
}
int main()
{
	int n, m;
	while (cin >> n >> m, (n > 0 && m > 0))
	{
			cout << triangle(n, m) << endl;
	}
	return 0;
}