真题44:【结构体定义】

#include <stdio.h>
#include <string.h>
struct student {
long sno;
char name[10];
float score[3];
};
/**********found**********/
__1__ fun(struct student a)
{ int i;
a.sno = 10002;
/**********found**********/
strcpy(__2__, "LiSi");
/**********found**********/
for (i=0; i<3; i++) __3__+= 1;
return a;
}
main()
{ struct student s={10001,"ZhangSan", 95, 80, 88}, t;
int i;
printf("\n\nThe original data :\n");
printf("\nNo: %ld Name: %s\nScores: ",s.sno, s.name);
for (i=0; i<3; i++) printf("%6.2f ", s.score[i]);
printf("\n");
t = fun(s);
printf("\nThe data after modified :\n");
printf("\nNo: %ld Name: %s\nScores: ",t.sno, t.name);
for (i=0; i<3; i++) printf("%6.2f ", t.score[i]);
printf("\n");
getchar();
}
struct student fun(struct student a)
//struct student fun(struct student a)
这里明确指定了返回值类型为 struct student{ int i;
a.sno = 10002;
/**********found**********/
strcpy(a.name, "LiSi");
/**********found**********/
for (i=0; i<3; i++) a.score[i]+= 1;
return a;
}
真题45:【分类思想】
#include <stdio.h>
#define max 100
int fun(int xxx[])
{
}
int main()
{
int xx[max],cnt;
void NONO(int xx[], int cnt);
cnt = fun(xx);
printf("符合条件的个数=%d\n", cnt);
NONO(xx, cnt);
return 0;
}
void NONO(int xx[], int cnt)
{
int i;
FILE *fp;
fp = fopen("out.dat", "w");
fprintf(fp, "%d\n", cnt);
for(i=0;i<cnt;i++)
fprintf(fp, "%d\n", xx[i]);
fclose(fp);
}
int fun(int xxx[]) {
int i, j, k;
int count = 0; // 独立计数器,记录有效数字的数量(作为数组下标)
// 三重循环遍历百位、十位、个位(1-4)
for (i = 1; i <= 4; i++) { // 百位
for (j = 1; j <= 4; j++) { // 十位
for (k = 1; k <= 4; k++) { // 个位
// 确保三个数字互不相同
if (i != j && i != k && j != k) {
// 组成三位数并存储到数组,计数器自增
xxx[count] = i * 100 + j * 10 + k;
count++;
}
}
}
}
return count; // 返回生成的三位数总数
}
多位数的核心是拆分各位
真题47:【字符串数组】

#include <stdio.h>
#include <string.h>
#define N 5
#define M 10
/**********found**********/
void fun(char (*ss) __1__, int k)
{ int i=0 ;
/**********found**********/
while(i< __2__) {
/**********found**********/
ss[i][k]=__3__; i++; }
}
main()
{ char x[N][M]={"Create","Modify","Sort","skip","Delete"};
int i;
printf("\nThe original string\n\n");
for(i=0;i<N;i++)puts(x[i]); printf("\n");
fun(x,4);
printf("\nThe string after deleted :\n\n");
for(i=0; i<N; i++) puts(x[i]); printf("\n");
getchar();
}
/**********found**********/
void fun(char (*ss)[M], int k)
{ int i=0 ;
/**********found**********/
while(i< N) {
/**********found**********/
ss[i][k]='\0'; i++; }
}
理解:
x[N][M]
是一个 二维字符数组 ,用于存储 N 个字符串(每个字符串最长 M-1 个字符,最后 1 个字节存字符串结束符 '\0'
)。从内存存储来看,二维数组本质是 "一维数组的数组":
- 整个
x
可以看作一个 "包含 N 个元素的一维数组"; - 这个一维数组的 每个元素 又是一个 "长度为 M 的字符数组"(即每个字符串的存储空间)。
例如代码中 x[0]
是第一个元素(对应字符串 "Create"
),其类型是 char [M]
(长度为 M 的字符数组);x[1]
是第二个元素("Modify"
),类型同样是 char [M]
。
常见错解:
形参写法 | 类型含义 | 是否正确?原因分析 |
---|---|---|
char (*ss)[M] |
指向 "长度为 M 的字符数组" 的指针 | ✅ 正确:与实参 x 退化后的类型完全匹配,能正确访问 ss[i][k] (第 i 个字符串的第 k 个字符) |
char *ss[M] |
存储 M 个 "字符指针" 的数组 | ❌ 错误:这是 "指针数组"(每个元素是 char* ),与二维数组 x 的类型完全不兼容,编译会报错 |
char ss[N][M] |
二维字符数组(固定 N 行 M 列) | ❌ 错误:虽然语法能通过,但函数会拷贝整个二维数组(内存开销极大),且无法适配不同 N 的数组,不符合参数传递逻辑 |
char **ss |
指向 "字符指针" 的指针(二级指针) | ❌ 错误:char** 用于指向 "指针数组"(如 char* arr[] = {"a","b"} ),无法访问二维数组的连续内存,会导致内存越界 |
真题48:

#include <stdio.h>
#include <string.h>
#define N 5
#define M 15
void fun(char (*ss)[M], char *substr)
{ int i,find=0;
/**********found**********/
for(i=0; i< __1__ ; i++)
/**********found**********/
if( strstr(ss[i], __2__) != NULL )
{ find=1; puts(ss[i]); printf("\n"); }
/**********found**********/
if (find==__3__) printf("\nDon't found!\n");
}
main()
{ char x[N][M]={"BASIC","C langwage","Java","QBASIC","Access"},str[M];
int i;
printf("\nThe original string\n\n");
for(i=0;i<N;i++)puts(x[i]); printf("\n");
printf("\nEnter a string for search : "); gets(str);
fun(x,str);
getchar();
}
void fun(char (*ss)[M], char *substr)
{ int i,find=0;
/**********found**********/
for(i=0; i< N ; i++)
/**********found**********/
if( strstr(ss[i], substr) != NULL )
{ find=1; puts(ss[i]); printf("\n"); }
/**********found**********/
if (find==0) printf("\nDon't found!\n");
}
strstr
是 "字符串找字符串" 的函数,两个参数必须都是指向完整字符串的指针(char*
),不能用单个字符(char
)作为参数。
注意不能写成strstr(ss[i], substr[i]) != NULL
分析 ss[i]
和 substr
的类型与作用
结合代码上下文,先明确两个变量的本质:
变量名 | 类型 | 作用 | 示例(代码中) |
---|---|---|---|
ss[i] |
char* (字符串指针) |
二维字符数组 ss 的第 i 个字符串(主串) |
ss[0] 是 "BASIC" ,ss[1] 是 "C langwage" |
substr |
char* (字符串指针) |
要查找的完整子串 (如用户输入的 "BAS" ) |
若用户输入 "BAS" ,substr 指向这个字符串首地址 |
substr[i] |
char (单个字符) |
子串 substr 的第 i 个字符 |
若 substr 是 "BAS" ,substr[0] 是 'B' ,substr[1] 是 'A' |
真题56:

#include <stdio.h>
typedef struct
{ char num[8]; /* 学号 */
double score[2]; /* 两门课成绩 */
/**********found**********/
} __(1)__ ;
int fun(STU std[ ], int n)
{ int i, k=0;
for(i=0; i<n; i++)
/**********found**********/
if( (std[i].score[0]<60) __(2)__ (std[i].score[1]<60) )
{ k++; printf("学号:%s ",std[i].num); }
/**********found**********/
return __(3)__ ;
}
main()
{ STU std[4]={ "N1001", 76.5,82.0 ,"N1002", 53.5,73.0,
"N1005", 80.5,66.0,"N1006", 81.0,56.0 };
printf( "\n共有%d位学生有不及格科目\n" , fun(std,4) );
getchar();
}
typedef struct
{ char num[8]; /* 学号 */
double score[2]; /* 两门课成绩 */
/**********found**********/
} STU ;
int fun(STU std[ ], int n)
{ int i, k=0;
for(i=0; i<n; i++)
/**********found**********/
if( (std[i].score[0]<60) || (std[i].score[1]<60) )
{ k++; printf("学号:%s ",std[i].num); }
/**********found**********/
return k ;
}
这段这段代码中结构体类型定义必须从 student
改为 STU
,核心原因是 C 语言中 "类型名必须与后续使用保持一致",具体分析如下:
1. 错误本质:类型名不匹配
typedef struct { ... } 类型名;
的作用是:给结构体定义一个 "别名"(类型名),后续可以用这个别名声明变量。- 代码中,函数
fun
的参数写的是STU std[]
,表示std
是 "STU
类型的数组"。 - 若结构体别名定义为
student
(即} student;
),则STU
是 未定义的类型 ,编译器会报错 "STU
未声明"。
2. 正确逻辑:类型名必须前后一致
- 结构体定义时用
STU
作为别名:} STU;
,则STU
成为一个合法的结构体类型名。 - 后续函数参数
STU std[]
、主函数中的STU std[4]
才能正确匹配,编译器会识别STU
代表该结构体类型。
3. 类比理解:变量名与类型名的绑定
这就像 "给人起名":
- 若结构体是一个 "人",
typedef
就是给这个人起 "别名"。 - 若起名
STU
(} STU;
),后续提到STU
时,大家才知道指的是这个结构体。 - 若起名
student
却叫STU
,就会出现 "名字不对应" 的错误。
修正后的关键代码对比
错误写法(typedef 别名) | 正确写法(typedef 别名) |
---|---|
} student; |
} STU; |