【820复试】编程题/填空题(二)

1.最长公共前缀
输入:strs = ["flower","flow","flight"]
输出:"fl"
char* longestCommonPrefix(char** strs, int strsSize) {
    if (strsSize == 0) {
	    return "";
    }
    for (int i = 0; i < strlen(strs[0]); i++) {
	    for (int j = 1; j < strsSize; j++) {
            //每次都要遍历一个相同字符都要将所有对应字符都要做比较
            if (strs[0][i] != strs[j][i])
            {
                strs[0][i] = '\0';
                return strs[0];
            }
        }
    }
    return strs[0];
}
2.二进制相加(字符串类型)
3.去掉字符串的首尾空格
// 函数trim:去掉字符串首尾空格
// 参数:str-字符指针,指向输入的字符串
// 返回值:字符指针,指向去掉首尾空格后的字符串(首地址)
char * trim(char * str){
    char *p = str;
    while(*p==' ') p++;
    char *q,*pre;
    q=p;
    pre = p;
    while(*q!='\0'){
        if(*q!=' '){
            pre = q;
        }
        q++;
    }
    pre++;
    *pre = '\0';
    return p;
}
4.选出串中的数字

在一串隐藏着一个或多个数值的字符中,选出字符串中的所有数字字符,并将选出的数字字符重新组成新字符串。如果在第一个数字字符之前有负号,则保留该负号,有多个负号时只保留一个。

例如:输入的字符串为“a-1-2-4sd5 s6”,抽取数字后得到的新字符串为“-12456”。

void extractNum(char * str){
    char *ans = str; //这里将ans的指针指向str,修改ans的值就可以修改str了
    char *p=str; //p为遍历指针
    bool flag = true;
    while(*p!='\0'){
        if(*p=='-' && flag){
            flag = false;
            *ans = *p; //对指针指向的地址元素进行值修改
            ans++;
            p++;
        }else if(*p>='0' && *p <='9'){
            flag = false;
            *ans = *p;
            ans++;
            p++;
        }else p++;
    }
    *ans = '\0';
    /********** End **********/
}

int main(){
    char s[1024];
    cin.getline(s,1024);     // 输入一行字符
    extractNum(s);     // 调用extractNum函数,选出数字
    cout<<s<<endl;     // 输出选出的数字
    return 0;
}
5. 子串出现的次数

计算一个字符串(子串)在另一个字符串(长串)中出现的次数。
【注意】:这里出现的次数,要将第一次出现的字符匹配了之后将这段字符去掉,否则若是输入子串aa、主串aaaa,那么答案就会不同一。

//需要用到的字符串函数
int strlen(const char* str); //返回字符数组str的长度

char* strstr(const char* substr, const char* str); 
//显然是在str中查找substr,其返回值是在str中第一次出现字串substr的首地址
如:
char *str = "abcdeabcde";
char *substr = "bcd";
cout<< strstr(substr,str); //输出的是bcdeabcde

本题输入样例:

测试输入1:
aaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
预期输出1:
7

测试输入2:
ab
aaaaabbbbbabcdefg
预期输出2:
2
完整代码如下:

// 包含字符串函数库
#include <string.h>
#include <iostream>
using namespace std;
int frequency(char * substr, char * str){
    int ans = 0;
    int len = strlen(substr);
    while(1){
        str = strstr(str,substr);
        if(str!=NULL) ans++;
        else break;
        str = str+len;
    }
    return ans;
}

int main(){
    char sub[128],str[1024];
    cin.getline(sub,128);     // 输入子串
    cin.getline(str,1024);     // 输入长串
    int n = frequency(sub,str);     // 调用frequency函数,计算子串在长串中出现的次数
    cout<<n<<endl;     // 输出次数
    return 0;
}
6.字符串替换

在字符串str中,把str中的所有串s1替换为s2;

输入样例1:abcxxdexxf xx ooo
输出样例1:abcooodeooof

输入样例2:mnkullsxxlo ll u
输出样例2:mnkuuxxlo

输入样例3:XuJianJun j o
输出样例3:XuJianJun
char *ReplaceString(char *str, char *s1, char *s2){
    char backup[100];
    strcpy(backup,str);
    str[0]='\0';
    char *t = backup;
    char *sub = strstr(t,s1); //找不到子串则为NULL
    while(sub !=NULL){
        int len = strlen(t)-strlen(sub); //原字符串-查找到的子串=第一个子串前的字符数
        strncat(str,t,len); //连接s1之前的字符串
        strcat(str,s2);    //连接s2子串
        t = sub + strlen(s1); //移动
        sub = strstr(t,s1);
    }       
    strcat(str,t);
    return str;
}
7.大数相加/减/乘/除

输入字符串s1,符号位op,字符串s2。要求输出s1 op s2的结果。不能有前导0
提示:
对于加法,考虑先把两个数对齐,再按位加(要考虑进位),运算结果以字符串形式输出。
对于减法,先比较被减数和减数的大小,如果被减数小于减数,则需要交换被减数和减数,然后再按位减(要考虑借位)。

要点:
先将字符串的每个字符转换成整数放入数组;
分别写出加法、减法、乘法、除法的函数,调用清晰,模块化处理。

代码如下:

//加法
string add(string a, string b){
	string res="";
	int t= 0;
	for(int i=a.size()-1,j=b.size()-1; i>=0 || j>=0; i--,j--){
		int x = i>=0 ?a[i]-'0' :0;
		int y = j>=0 ?b[j]-'0' :0;
		int sum = x+y+t;
		res += to_string(sum %10);
		t = sum /10;
	}
	reverse(res.begin(),res.end());
	return res;
}

//减法
string subtract(string a, string b){
	string res = "";
	bool flag = false;
	if(a.size() < b.size()){ //特判
        flag = true;
        swap(a,b);
    } 
	int t=0;
	int i=a.size()-1,j=b.size()-1;
	while(i>=0 || j>=0){
		int x = i>=0 ?a[i]-'0' :0;
		int y = j>=0 ?b[j]-'0' :0;
		int diff = x-y-t;
		if(diff<0){
			diff +=10;
			t =1;
		}else t =0;
		res += to_string(diff);
		i--;
		j--;
	}
	reverse(res.begin(),res.end()); //翻转
	while(res.size()>1 && res[0]=='0') res.erase(res.begin()); //前导零
	if(t==1 || flag) res = "-"+res;
	return res;
}

//乘法
string multiply(string num1, string num2) {
    int size_1 = num1.size(),size_2 = num2.size();
    string res(size_2+size_1,'0');
    for (int i=size_1-1;i>=0;--i) {
        for (int j = size_2 -1; j>=0;--j) {
            int _t = res[i+j+1]-'0' + (num2[j]-'0') * (num1[i]-'0');
            res[i+j+1] = _t%10 + '0';
            res[i+j]  += _t/10;
        }
    }
    for (int i=0,n=res.size(); i<n;++i) {
        if (res[i]!='0') return res.substr(i);
    }
	return {'0'};
}

//除法
不想写
8.线性表
#include <iostream>
using namespace std;

// 定义结点结构
struct node{
    int data;  // 数据域
    node * next;  //指针域,指向下一个结点
};

node *insertTail(node *h, node *t){ //尾插法
    // 请在此添加代码,补全函数insertTail
    if(h==NULL) return t;
    node *p=h;
    while(p->next!=NULL) p++;
    p->next = t;
    return h;
}

node * insertHead(node *h, node *t){//不带头结点的头插法
    t->next = h;
    h=t;
    return h;
}

node * insertSort(node *h, node *t){ //插入时即链表升序
    if(h==NULL) return t;
    node *pre =NULL, *p=h;
    if(p->data >= t->data){ //特判第一个结点
        t->next = p;
        return t;
    }
    pre = p;
    p=p->next;
    while(p!=NULL){
        if(p->data >= t->data){ //中间插入
            pre -> next = t;
            t->next = p;
            return h;
        }
        pre = p;
        p = p->next;
    }
    //尾插
    pre ->next = t;
    return h;
}

node * delAt(node * h, int i){ //删除第i个位置的结点,以0开始
    int cnt = 0;
    //特判头结点位置
    if(cnt==i){
        return h->next;
    }
    cnt++;
    node *pre = h,*p=h->next;
    //删除中间位置
    while(p!=NULL){
        if(cnt==i){
            pre->next = p->next;
            return h;
        }
        cnt++;
        pre = p;
        p = p->next;
    }
    //不合法位置
    if(cnt<i) return h;
}

// 函数delList:删除链表,释放空间
void delList(node *h){ 
	node *p=h;  // 指针p指向头结点,第一个要删除的结点
	while(p)  // 这个结点是存在的
	{
		h = h->next;  // 头指针h指向下一个结点(下一个结点的地址存在当前结点的指针域中,即h->next中
		delete p;  // 删除p指向的结点
		p = h;  // p指向当前的头结点,即下一个要删除的结点
	}
}
// 函数printList:输出链表,每个数据之间用一个空格隔开
void printList(node *h){ //输出
	cout<<"List:"; 
	while(h)
	{// h为真,即h指向的结点存在,则输出该结点的数据
		cout<<" "<<h->data;  // 输出结点数据
		h=h->next;  // 将该结点的指针域赋值给h,h就指向了下一个结点
	}
	cout<<endl; // 输出换行符
}


int main(){
	int n,i;
	node *t;
	node *head=NULL; // 头指针为NULL,表示线性表为空,结点数为0
	// 输入结点数
	cin>>n;
	for(i=0;i<n;i++){
		// 为新节点动态分配空间
		t = new node;
		cin>>t->data;  // 输入结点数据
		t->next=NULL;  // 结点指针域值为空
		// 调用函数插入结点
		head = insertTail(head, t);
	}
	// 输出链表
	printList(head);
	// 删除结点,释放空间
	delList(head);

	return 0;
}

【注意】:我犯的错(在链表里,指针指向下一个位置应该是p=p->next,而不是p++)
写指针写多了,下次不许再犯辣。

9.文件题目
读文本文件

​ 1.从文本文件中读取一个字符可以使用 fgetc 函数:

int fgetc(FILE *stream);

该函数表示从文件指针 stream 指向的文件的当前位置读取一个字符,并以 int 类型返回。

​ 2.从文本文件读取一行可以使用 fgets 函数:

char *fgets(char *string, int n, FILE *stream);

该函数表示从文件指针 stream 指向的文件的当前位置开始读取字符串,直到遇到换行符(读入该换行符),或到达文件结束位置,或读取了 n-1 个字符。读取的字符串存入 string 所指的内存单元中,并在所有读取的字符之后添加字符串结束标记\0

如果读取成功,函数返回 string,如果出错或读取前已经到达了文件结束的位置,将返回 NULL。

​ 3.从文本文件中进行格式化读取可以使用 fscanf 函数:

int fscanf(FILE *stream, const char *format [,argument]...);

该函数的功能是从指定文件中将数据按照格式控制串 format 读出并转换成相应的类型以存入对应的参数中。如果读取成功,该函数返回转换成功的参数的个数,如果出错或读取前已经到达了文件结束的位置,将返回文件结束标志 EOF。

函数 fscanf 与 scanf 函数非常相似,只是 fscanf 函数多了一个参数 stream 以指向要读取数据的文件。

​ 4.输出格式化数据到文本文件中可以使用 fprintf 函数:

int fprintf(FILE *stream, const char *format [,argument]);

该函数的功能是将数据按照格式控制串 format 写入到文件指针 stream 指向的文件中。如果写入成功,函数返回写入的字节数,否则返回一个负数表示错误。

函数 fprintf 与 printf 函数相似,只是 fprintf 函数多了一个参数 stream 以表示要写入数据的文件。

例题1:

要求:

  1. 文件a.txt中包含各种字符,但只有数字字符是有效的,提取其中的数字字符,将每 3 个数字组成一个整数。
  2. 写到文件b.txt中,每个整数之间用一个空格分开。读取过程中,如果a.txt中最后剩下不到3个数字字符,则将剩下的1个或者2个数字字符组成一个整数。

测试输入:q12h44h67k854ksd923823sf83wd38457sd433ds,
预期输出:124 467 854 923 823 833 845 743 3

#include <stdio.h>

void extractDigit(){
    FILE *fp1 = fopen("a.txt","r");
    char s[1024];
    fgets(s,1023,fp1);
    fclose(fp1);
    char ans[1024];
    int j=0;
    for(int i=0; s[i]!='\0'; i++){
        if(s[i]>='0'&& s[i]<='9'){
            ans[j++] = s[i];
        }
    }
    int a[500],cnt=0;
    int i=0; //ans的下标
    int t=1; //每三个一个循环
    int m =0; 
    while(i<j){
        m = m*10 + ans[i]-'0';
        i++;
        t++;
        if(t>3 || i>=j){
            t=1;
            a[cnt]=m;
            cnt++;
            m=0;
        }
    }
    FILE *fp2 = fopen("b.txt","w");  
    for(i=0; i<cnt; i++){
        fprintf(fp2,"%d ",a[i]);
    }
    fclose(fp2);
}

int main()
{
	//准备文件a.txt的内容
	FILE *fp = fopen("a.txt","w");  //打开文件a.txt用于写
	char s[1000];
	fgets(s, 999, stdin);  //从键盘读取一行字符
	fputs(s,fp);  //将这一行字符写入文件a.txt中
	fclose(fp);   //关闭fp关联的文件a.txt
	extractDigit();  //调用函数,抽取数字写入文件b.txt中
	FILE *f = fopen("b.txt","r");  //以读的方式打开文件b.txt
	if(f==NULL)  //打开失败则返回
		return 0;
	int n,k=0; 
	fscanf(f,"%d",&n);  //从文件b.txt中读出一个整数到变量n中
	while(!feof(f))  //如果文件没结束(读出的不是EOF)
	{
		k++;
		printf("%d ",n);  //输出该整数到屏幕
		if(k%10==0)   //每十组一换行
			printf("\n");
		fscanf(f,"%d",&n);  //读取下一个整数
	}
	if(k%10!=10)  //最后一行没有换行符则补上
		printf("\n");
	return 0;
}
读二进制文件

二进制文件的可以使用 fread 和 fwrite 函数。

fwrite 函数

函数 fwrite 的原型为:

size_t fwrite(const void *buffer, size_t size, size_t count, FILE *stream);
  • size_t 为类型 long 的别名。函数 fwrite 实现把内存中从指定位置开始的指定个数的字节以二进制的方式写入文件。
  • 第一个参数 buffer 指向内存中要写入文件的数据的首地址。
  • 第二个参数 size 是要写入文件的数据对象的大小,一般使用运算符 sizeof 计算数据对象所占空间的字节数。
  • 第三个参数是要写入的数据对象的个数。
  • 第四个参数是文件指针,指向要写入数据的文件。函数 fwrite 可以一次将从 buffer 开始的,size*count 个字节的数据写入指针 stream 指向的文件中。

fread 函数

函数 fread 的原型为:

size_t fread(void *buffer, size_t size, size_t count, FILE *stream);
  • 与 fwrite 相反,函数 fread 的作用是从文件的当前位置读取指定字节数的数据放入到内存的指定位置。
  • 第一个参数 buffer 指向内存中要写入数据的位置。
  • 函数 fread 的后 3 个参数与函数 fwrite 的后 3 个参数的意义相同,给出了要读取数据对象的字节数、数目及被读取的文件。
  • 函数 fread 可以从指定文件的当前位置一次性读取 size*count 个字节的数据并存入 buffer 中。
例题2:

测试输入:

4
a0001  23
b0003  543
c0004  450
a0003  125

预期输出:

a0001 23
b0003 543
c0004 450
a0003 125
#include <stdio.h>

//声明结构clothing
struct clothing {
	char label[12]; //编号
	float price;    //价格
};
int readClothing(FILE *fp, clothing cloth[]){
    int n =0;
    fread(&n, sizeof(n),1,fp);
    fread(cloth,sizeof(clothing),n,fp);    
    return n;
}

int main(){
	clothing t;
	int n,i;
	//输入服装信息,存入文件a.dat
	FILE *fp = fopen("a.dat","wb");  //打开二进制文件a.dat用于写
	scanf("%d",&n); //输入服装种数
	fwrite(&n,sizeof(n),1,fp); //将n以二进制形式写入文件
	for(i=0;i<n;i++){
		scanf("%s %f",t.label,&t.price); //输入一种服装的编号和价格
		fwrite(&t,sizeof(t),1,fp); //将该服装信息以二进制形式写入文件
	}
	fclose(fp); //关闭文件
	//定义服装信息数组
	clothing cloth[100];
	//打开文件,以二进制方式打开用于读
	fp = fopen("a.dat", "rb");
	//从文件中读取服装信息到数组cloth中
	n = readClothing(fp, cloth);
	//关闭文件
	fclose(fp);
	//输出服装信息
	for(i=0;i<n;i++){
		printf("%s %d\n",cloth[i].label,(int)cloth[i].price);
	}
	return 0;
}
散题 1
①指针的相对位置:
int arr[3]={5,3,1};
int *p=&arr[1];
p[1]=*p-1+(p[-1]=3);
问arr中数组各个元素的值:
答案:3,3,5
指针p指向的是arr[1]。
那么p[1]指向的则是arr[2],p[-1]指向的则为arr[0]
p[-1]=3的返回值为赋值运算的右侧, *p为arr[1]
②a<b<c在判断语句中的运算顺序及中间结果
int a =1,b=2,c=2,t;
while(a<b<c){
    t=a;
    a=b;
    b=t;
    c--;
}
cout << a<<' '<<b<<' '<<c;
//答案为1 2 0
分析:
第一次:
a=1,b=2; 那么a<b返回值为true,其int值为1,c=21<c成立,进入循环
交换a和b,c--;此时a=2,b=1,c=1;
第二次:
a=2,b=1,那么a<b为false,其int值为0,c=10<c成立,进入循环
交换a和b,c--;此时a=1,b=2,c=0
第三次:
a=1,b=2,那么a<b成立,其int值为1,但c=01<c为false,不进入循环
故答案为1,2,0

③两个字符串的交换函数

要用strcpy(const char* str1, const char *str2);函数赋值,函数意义:将str2赋给str1。类似于int a, b。 a=b

典型错误写法:

void swap(char *p1, char *p2){
    char *temp = p1;
    p1 = p2;
    p2 = temp;
}

改正:

//正确代码1:
void swap(char *p1, char *p2){
    char temp[1024];
    strcpy(temp,p1);
    strcpy(p1,p2);
    strcpy(p2,temp);
}


//正确代码2:
void swap(char **p1, char **p2){
    char *t;
    t = *p1;
    *p1 = *p2;
    *p2 = t;
}
③浮点数输出格式
#define PI 3.1415926535
void main(){
    int n;
    scanf("%d",&n);
    //分别PI的输出小数点后n位,n+1位,n+2位,n+3位
    printf("%.*f\n",n,PI);
    printf("%.*f\n",n+1,PI);
    printf("%.*f\n",n+2,PI);
    printf("%.*f\n",n+3,PI);
    //输出格式化 型如%10.5f。总体占10格,保留5位小数
    printf("%*.*f\n",p,n+3,PI); //输出总体占p格,保留n+3位小数的PI
}
④内存泄露问题
int *p,*q;
p=(int*)malloc(sizeof(int)*20);
q=(int*)malloc(sizeof(int)*20);
p=q; //应该删去此行代码
free(p);
free(q);//若不删上面的p=q,那么p和q就指向同一地址,free(p)之后再free(q),就会重复释放同意内存,导致还剩一块内存没有释放从而引起内存泄漏

堆内存是指程序从堆中分配的,大小任意的,使用完必须显示释放的内存。应用程序一般使用malloc,realloc,calloc,new等函数从堆中申请一块内存,使用完后,必须使用free或delete释放响应申请的内存卡,否则这块内存就不能被再次使用,即内存泄漏。

⑤改错细节
//题目一:
void main(){
    char *src = "hello,world";
    char *dest,*d,*p;
    int len,i;
    len = strlen(src);
    dest = (char*)malloc(len); //这里应该是len+1,要多存一字符存'\0'
    p=&src[len]; 
    //此时的src[len]对应的字符并不是src的最后一个字符'd',而是'\0',所以应该是p=&src[len-1];
    d = dest;
    while(len--!=0) d++ = p--;//赋值赋的是字符,而不是地址,所以应该是*d++=*p--; 等价于*d=*p; d++,p--;
    //输出字符前要检查该字符末尾是不是'\0'
    所以本行应该增加:*d = '\0';
    printf("%s",dest);
}

//题目二:
void main(){
    char *src = "HELLO,UESTC";
    char *dest = NULL;
    int len = strlen(src);
    dest = (char*)malloc(len);//同上,改为len+1
    char *d = dest;
    char*s = &src[len]; //同上,改为&src[len-1]
    while(len--!=0) *d++ = *s--;
    //字符结尾要加结束符'\0'
    加一行:*dest= '\0';
    
    prinf("%s",dest);
    
    //由于dest用malloc函数申请了一段内存,使用完后需要自行释放该段内存
    加一行:free(dest);
}

此外:还有一些注意点:
Ⅰ 要使用指针时,一定要看该指针是否赋了初始地址

⑥浮点数精确度

void main(){
    float d;
    scanf("%f",&d);
    if(d==3.5) putchar('Y');
    else putchar('N');
}
问:输入3.5,输出结果为什么,为什么,如何修改?
//答案一:
输出结果为Y,因为浮点数3.5在转化为二进制时,是可以被精确表示的,所以在本题中输出为Y。
可以修改判断条件为 if(fabs(d-3.5) <0.0001),表示若两数之间精确到小数点后4位即为相等即可。
//答案二:
输出Y,因为恰好输入3.5,数位由0补齐,与3.5刚好相等,所以输出Y。
但是由于浮点数表示都是不精确的,所以不能用“==”判断相等,有几率出现错误。
修改方法为 if条件编程“d-3.5”的绝对值小于某一精度。如fabs(d-3.5<0.0001)
⑦递归过程树
int value(int n){
    if(n==0) return 0;
    else{
        int x;
        cin >> x;
        return (value(n-1)+x);
    }
}
问题:若该函数被调用,参数n的值为4,输入的x值依次是11223344,函数调用结束时的返回值是多少?并用图描述函数递归执行过程。
value(4)=value(3)+11 --> value(3) = value(2)+22 --> value(2) = value(1)+33 -->value(1) = value(0)+44 = 0+44 = 44value(2) = 44+33 = 77
    value(3) = 77+22 = 99
    value(4) = 99+11 = 110
 所以返回值为110

递归过程树

⑧数组作为函数参数的三种形式

问题:数组作为函数参数有三种形式:
1)实参为数组元素;2)形参为指针,实参为数组;3)函数的形参和实参都是数组;
分别采用什么参数传递方式?

答:1)实参为数组元素(如a[2])采用的是数组元素的值; 2)形参为指针,实参为数组——传数组的起始地址;3)传递数组的起始地址;

⑨C语言中的选择/循环语句用显示结构表示
//题目一:
do{
    S;
}while(B);

显示结构:(label为自定义命名)
lable: S;
if(B) goto label;

//题目二: 选择结构
if(B) s1;
else s2;

条件跳转:
Begin
if B!=0
DO s1;
否则 Do s2;

显示结构://强制跳转
if(B) goto lable1;
else goto lable2;
label1: s1;
label2: s2;

//题目三:
for(int i=1; i<n; i++)
    S;
问这是什么结构: //循环判断选择结构

显示结构语言:
i=1;

S_for:
if(i<n) 
    goto S_do;
goto S_exit;

S_do:
   S;
   i=i+1;
   goto S_for;
S_exit: 结束

另一种显示结构语言写法:
Label1: if(i<n) goto S;
if(i==n) goto S1;
S:执行程序; i++,goto Label1;
S1: 结束

//题目四:
switch(E){
	case N1: 
		S1;
		break;
	case N2:
		S2;
		break;
	default:
		S3;
}

显示控制结构:
		t=E;
m: if t = N1 goto m+2
m+1:  goto n+1
m+2:  ...S1对应的代码
n: goto S.next
n+1: if t=N2 goto n+3
n+2: goto k+1
n+3: ...S2对应的代码
k:  goto S.next
k+1 ...S3对应的代码
S.next
⑩从程序执行效率方面考虑,C语言采取的一些措施和原因。

1.指针,可以操作内存。
因为指针可以用于类似于汇编的寻址方式,可以通过指针直接访问硬件,所以可以使程序更高效。

2.位运算,可以作位运算
位运算可以减少除法和模运算的运算。位是计算机程序中可以操作的最小数据单位。一般位操作是用来控制硬件的,灵活的位操作可以有效提高程序运行的效率。

3.API,可以调用系统API,接近底层,从而程序执行效率就高。

4.宏define可以编译的时候替换
宏函数占用大量空间, 而函数占用大量时间。函数调用是要使用系统的栈来保存数据,CPU要在函数调用时保存和恢复当前的现场,进行压栈和弹栈曹排长,所以函数需要一些CPU时间;宏函数仅仅作为预先写好的代码嵌入当前程序,不会产生函数调用,仅占用了空间,使程序高效运行。当频繁调用同一个宏函数时,效果很明显。

5.循环嵌套中将长循环设位内置循环,短循环设置位外置循环,以减少cpu跨切循环层的次数,提高程序的运行效率。

散题2
①C语言存储区

局部变量——栈区;
局部静态变量——静态区;
全局变量——静态区的常量区;
全局静态变量——静态区;

栈区:
存放函数的参数值,局部变量;

堆区:
由程序员自行(new分配的内存块,要对应delete)分配,与数据结构中的堆不一样,分配方式类似于链表;

自由存储区:
malloc分配的内存块,用free来结束,与堆相似。

全局区(静态区static):
存放全局变量,静态(static)变量。未初始化的全局变量和静态变量在相邻的区域。 程序结束后系统释放

文字常量区:
存放常量、字符串。

程序代码区:
存放函数体的二进制代码。

②宏定义替换
#define SQUARE(x) ((x)*(x))
int a=5,b;
执行:
b=SQUARE(a++);
问:a和b各为何值?
扩展宏定义:
b=(a++)*(a++);
所以b=25,a=7
③C语言的隐式类型转换发生的四种情况

1.算术运算符中,低类型能够转换为高类型;
2.赋值表达式中,右边表达式的值自动隐式转换成左边变量的类型,并赋值给它
3.函数调用中参数传递时,系统隐式地将实参转换为形参地类型后,赋值给形参
4.函数由返回值时,系统隐式地将返回表达式地类型转换成返回值类型,赋给调用函数。

④C语言中,除了关键字,还有哪些C的语法符号?C的存储类型关键字有哪四个?

还有标识符、运算符、分隔符、常量、注释符。

C的存储类型关键字:auto、extern、register、static

⑤C语言的数据类型分类(出过填空题4个空6分)

数据类型分类

⑥在函数体中如何使用与局部变量同名的全局变量

使用 "::"作用域区分符

⑦数组越界检查

若不检查,可能会导致运行出错,访问到不可访问的存储单元,或者修改其他非数组元素的数据

⑧读程序片段题

常量区填数字,全局数据区填变量,静态存储区填变量,main主函数填变量,自定义函数填变量。

要注意题目要求,看整数是不是平时看到的占4字节,指针是不是平时看到的8字节,字符是不是平时看到的1字节。

往往会给出大小,千万不要答错了。

在函数体内直接确定数组大小的就说明已经开辟了这些内存,所以不要以为填了多少数,才算多少。除非是malloc的,就看具体size大小。

⑨C语言网络编程(C语言+计算机网络综合)

题目:用c语言网络编程,你将使用http还是TCP/IP协议来进行网络连接,为什么?
http协议何TCP协议的区别是:
http协议是应用层协议,TCP协议是传输层协议,http协议是建立在TCP协议之上的,http是无状态的段连接,而TCP是有状态的长连接。
像java这类语言比较适合应用层http,而c语言更适合传输层的TCP/IP。

⑩static全局变量和普通的全局变量的区别

static全局变量只初始化一次,防止在其他文件单元中被引用;
static变量存放在静态数据区中。

全局变量可以进行重复赋值操作,自增操作等。 全局变量存放在静态区的常量区中。

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值