入门C语言,看这篇就够了

C语言中的基础概念

该文章将会把C语言基础语法梳理一遍,主要记录帮助理解相关知识点的代码示例和重要或容易忽略的面试知识,将会陆续发布系类文章.

1. 程序1 putchar(),getchar()函数的使用.

/*接收和显示一个字符*/
#include<stdio.h>
void main(){
    char ch;
    ch = getchar();
    putchar(ch);
}

2. 重要的面试题

是否可以在C代码的一个注释中嵌套另外一个注释?
答: 不行,不能在一条注释中嵌套另外一个注释。

3.程序2 gets(),puts()函数.

 /* 读取并显示一个人名*/
 #include<stdio.h>
 void main(){
     char str[20];
     puts("Type your name: ");
     gets(str);
     puts(str);
 }

4. 重要的面试题

在C语言中,如何从输入中读取十六进制整数?
在Scanf()函数中,在格式中包含‘%x’用于读取十六进制整数,如下所示:

 int num;
 scanf("%x",&num);

类似的,可以使用格式串“%o”从scanf()中读取一个八进制整数.

5. 程序3 printf()函数,scanf().

#include<stdio.h>
void main(){
    char name[20];
    printf("Your good name please: ");
    scanf("%[^\n]",name);
    printf("Hello %s",name);
    printf("\n Happy Birth day to you!");
}

6.程序 4 计算两数之和

/*计算两数之和 */
#include<stdio.h>
 void main(){
     int n1,n2;
     printf("\n Enter two numbers: ");

     scanf("%d%d",&n1,&n2);
     printf("\n Sum = %d",n1+n2);
 }

数据类型与操作符

1. 程序1:计算圆面积时使用常量pi

/*本程序演示const关键词*/
   #define PI 3.14159  /* 声明常量PI*/
   #include <stdio.h>
   void main(int argc, char const *argv[])
   {
       float radius,area;
       printf("\n Entre radius: ");
       scanf("%f",&radius);
       area = PI*radius*radius;
       printf("\nArea of circle: %f",area);
       return 0;
   }


另外一种方式定义常量是使用预处理宏定义命令‘#define’,好处是常量不占用内存.示例代码为:

#define PI 3.14159  /* 声明常量PI*/
#include <stdio.h>
void main(int argc, char const *argv[])
{
    float radius,area;
    printf("\n Entre radius: ");
    scanf("%f",&radius);
    area = PI*radius*radius;
    printf("\nArea of circle: %f",area);
    return 0;
}

程序3 操作符

  • 1.算数操作符(+,—,*,/,%);
  • 2.赋值(=);
  • 3.一元操作符(- 一元减法操作符,–,++);
  • 4.三元操作符(?:);
  • 5.关系操作符(<,<=,>,>=,==,!=);
  • 6.逻辑操作符(&&,||,!);
  • 7.位操作符(~,&,|,^, <<,>>)
/* 理解各种操作符*/
#include <stdio.h>
void main(int argc, char const *argv[])
{
    int x,y;
    /* 将数字10,12分别保存至变量雄,x,y中*/
    x = 10;
    y = 12;
    printf("\nn~x = %d",(~x));
    printf("\nx&y = %d",(x&y));
    printf("\nx|y = %d",(x|y));
    printf("\nx^y = %d",(x^y));
    printf("\nx<<2 = %d",(x<<y));
    printf("\nx>>2 = %d"(x>>2));
    return 0;
}

程序4 sizeof()操作符

/* 了解如何使用sizeof()操作符*/
#include<stdio.h>
void main()(int argc, char const *argv[])
{
    int a;
    long int b;
    printf("\nsize of a = %d",sizeof(a));
    printf("\nsize of b = %d",sizeof(b));
    printf("\nsize of int = %d",sizeof(int));
    printf("\nsize of long int = %d",sizeof(long));
    return 0;
}

输出:

size of a = 2
size of b = 4
size of int = 2
size of long int = 4

程序5 取地址操作符&

/* 获取变量x的十六进制的内存地址*/
#include<stdio.h>
void main(int argc, char const *argv[])
{
    int x;
    printf("Memory address = %x", &x);
    return 0;
}

输出为:

Memory address = fff4

程序6 指针操作符

/* 获取变量的内存地址*/
#include<stdio.h>
void main(int argc, char const *argv[])
{
    int x = 100;
    int *p; // 声明指针变量
    p = &x; // 将变量x的地址保存到p中
    // p代表变量x的内存地址
    printf("Memory address = %x",p);
    // *p代表变量x的值
    printf("\nPointer refers to %d",*p);
    return 0;
}

输出:

Memory address = fff4
Pointer refers to 100

程序7 操作符优先级

示例代码1:

/* 用来演示两个整数相除,结果仍然为整数*/
#include<stdio.h>
void main(int argc, char const *argv[])
{
    int x = 3,y = 2;
    float z = x/y;
    printf("\n Result of division = %f",z);
    return 0;
}

输出:

Result of division = 1.000000

示例代码2:
两个整数相除时使用类型转换

#include<stdio.h>
void main(int argc, char const *argv[])
{
    int x = 3,y = 2;
    float z = (float)x/y;
    printf("\n Result of division = %f",z);
    return 0;
}

输出:

Result of division = 1.500000

控制语句

1.程序 顺序执行

/* 计算一个三角形的面积,其中三角形三条边一知 */
#include <stdio.h>
#include "math.h"
int main(int argc, char const *argv[])
{
    float a,b,c,s,area;
    /* 输入三条边的边长*/
    printf("\n Enter the three sides: ");
    scanf("%f%f%f",&a,&b,&c);
    s = (a+b+c)/2;
    area = sqrt(s*(s-a)*(s-b)*(s-c));
    printf("\nArea of triangle: %f\n",area); 
}

输出:

Enter the three sides: 10 9.2 3.5
Area of triangle: 16.081221
Program ended with exit code: 0

2.程序 if···else

/* 判断一个数字是正数还是负数 */
#include <stdio.h>
int main(int argc, char const *argv[])
{
    int num;
    printf("\nType an integer number: ");
    scanf("%d",&num);
    if (num==0) {
        printf("\nIt is zero.");
    } else if(num>0){
        printf("\n%d is positive.\n");
    }else{
        printf("\n%d is negative.\n");
    }
}

输出:

Type an integer number: 5
0 is positive.

3.程序 判断某年是否为闰年.

/* 判断某年是否为闰年.*/
#include <stdio.h>
int main(int argc, char const *argv[])
{
    int year;
    printf("\nEnter a year: ");
    scanf("%d",&year);

    if (year % 100 != 0 && year % 4 == 0 || year % 400 ==0) {
        printf("\n%d is leap year.\n",year);
    } else {
        printf("\n%d is not leap year.\n",year);
    }
}

输出;

Enter a year: 2012
2012 is leap year.

4.程序 计算二次方程的根

/* 计算二次方程的根 */
#include <stdio.h>
#include <math.h>
int main(int argc, char const *argv[])
{
    int a,b,c;
    float x1,x2,x,d,r,r1;
    printf("\nType the values of a,b,c: ");
    scanf("%d%d%d",&a,&b,&c);

    /* 计算判别式*/
    d = b*b-4*a*c;
    if (d>0) {
        printf("\nRoots are unequal and real:\n");
        x1 = (-b+sqrt(d))/(2*a);
        x2 = (-b-sqrt(d))/(2*a);
        printf("Root1 = %.2f\n",x1);
        printf("Root2 = %.2f\n",x2);
    } else if(d==0){
        printf("\nRoots are equal and real:\n");
        x = -b/(2*a);
        printf("Root1 = %.2f\n",x);
        printf("Root2 = %.2f\n",x);
    }else{
        printf("Roots are complex and imaginary:\n");
        d = -d;
        r = -b/(2*a);
        r1 = sqrtf(d)/(2*a);
        printf("Root1 = %.2f+%.2fi\n",r,r1);
        printf("Root2 = %.2f-5.2fi\n",r,r1);
    }
}

输出:

Type the values of a,b,c: 1 2 -63
Roots are unequal and real:
Root1 = 7.00
Root2 = -9.00

5.程序 do···while循环

/* 计算一个整数中的各位数字之和 */
#include <stdio.h>
int main(int argc, char const *argv[])
{
    int num,digit,sum = 0;
    printf("Enter a number: ");
    scanf("%d",&num);
    do {
        digit = num % 10;
        sum += digit;
        num /= 10;
    } while (num>0);
    printf("The sum of dights= %d.\n",sum);
}

输出:

Enter a number: 1037
The sum of dights= 11.

6.程序1 while循环

/* 计算给定整数的阶乘 */
#include <stdio.h>
int main(int argc, char const *argv[])
{
    int i,n;
    long int fact = 1;
    printf("Enter a positive integer: ");
    scanf("%d",&n);

    i = 1;
    while(i<=n) {
        fact*=i;
        i++;
    }
    printf("Factorial of %d is %ld.\n",n,fact);
}

输出:

Enter a positive integer: 5
Factorial of 5 is 120.

7.程序2 while循环

/* 计算一个数值的乘方 */
#include <stdio.h>
#include <math.h>
int main(int argc, char const *argv[])
{
    int number,power,counter = 1;
    long int result1 = 1;
    long int result2 = 1;

    printf("Enter number,power: ");
    scanf("%d,%d",&number,&power);

    while (counter <= power) {
        result1 *=number;
        ++counter;
    }
    printf("%d rised to the power of %d = %d",number,power,result1);
    result2 = pow(number,power);
    printf("\n%d rised to the power of %d = %d\n",number,power,result2);
}

输出:

Enter number,power: 5,4
5 rised to the power of 4 = 625
5 rised to the power of 4 = 625

8.程序 for 循环 生成斐波那契序列

* 生成斐波那契序列 */
#include <stdio.h>
int main(int argc, char const *argv[])
{
    int i,n;
    long unsigned int f1,f2,f;
    printf("How many Fibonaccis you want? ");
    scanf("%d",&n);
    f1 = 0;
    f2 = 1;
    if(n==1) printf("%lu",&f1);
    else if (n==2){
        printf("%lu ",f1);
        printf("%lu ",f2);
    }else{
        printf("%lu ",f1);printf("%lu ",f2);
        for (i=3; i<=n; i++) {
            f = f1+f2;
            printf("%lu ",f);
            f1 = f2;
            f2 = f;
        }
    }
}

输出:

How many Fibonaccis you want? 10
0 1 1 2 3 5 8 13 21 34 

9.程序 continue语句

/* continue语句 */
#include <stdio.h>
int main(int argc, char const *argv[])
{
    int i;
    for (i=10; i>=1; i--) {
        printf("\nBefore continue: ");
        if (i>5)
            continue;
            printf("%d",i);
    }
}

输出:

Before continue: 
Before continue: 
Before continue: 
Before continue: 
Before continue: 
Before continue: 5
Before continue: 4
Before continue: 3
Before continue: 2
Before continue: 1

10. break语句和continue语句的区别是什么?

(重要的面试题) break语句径直跳到当前代码快=块的末尾,而continue语句会跳过当前循环的剩余代码,回到循环开始处.

11. 程序1 return语句

/* 调用一个函数,被调用的这个函数计算给定值的平方根并返回该值. */
#include <stdio.h>
#include <math.h>
/* 该函数接收参数y的值,返回他的平方根*/
double squareroot(double y){
    double x = sqrt(y); // 将与的平方根保存在变量x中
    return x; //返回y的平方根
}

int main(int argc, char const *argv[])
{
    double y,result;
    printf("Enter a number: ");
    scanf("%lf",&y);

    /*调用squareroot()函数,计算y的平方根*/
    result = squareroot(y);
    printf("Sequare root value= %lf.\n",result);
}

输出:

Enter a number: 16.9
Sequare root value= 4.110961.

12. 程序2 return语句

/* 计算正弦级数*/
#include <stdio.h>
#include <math.h>
int main(int argc, char const *argv[])
{
    int n,i,j = 1;
    double x,r,t,sum;

    printf("Enter no. of interations: ");
    scanf("%d",&n);
    printf("Enter the value of angle: ");
    scanf("%lf",&x);

    /* 将角度转化为弧度*/
    r = (x*3.14159)/180;
    /*用变量t保存级数第1项*/
    t = r;
    /*到目前为止所有项之和*/
    sum = r;
    /*显示要迭代的次数以及到当前为止所有项之和*/
    printf("Iteration = %d\tSum = %lf",j,sum);
    /*第2项的分母*/
    i = 2;
    /*循环计算第2项至第n项*/
    for (j=2; j<=n; j++) {
        /*计算下一项*/
        t = (-1)*t*r*r/(i*(i+1));
        /*将该项累加*/
        sum = sum+t;
        /*显示要迭代的次数以及到当前为止所有项之和*/
        printf("\nIteration = %d\tSum = %lf",j,sum);
        /* 将变量加2,用于下一项的分母中*/
        i = i+2;
    }
}

输出:

Enter no. of interations: 10
Enter the value of angle: 60
Iteration = 1   Sum = 1.047197
Iteration = 2   Sum = 0.855800
Iteration = 3   Sum = 0.866295
Iteration = 4   Sum = 0.866021
Iteration = 5   Sum = 0.866025
Iteration = 6   Sum = 0.866025
Iteration = 7   Sum = 0.866025
Iteration = 8   Sum = 0.866025
Iteration = 9   Sum = 0.866025
Iteration = 10  Sum = 0.866025

12. 程序3 return语句

/* 计算指数级数*/
#include <stdio.h>
int main(int argc, char const *argv[])
{
    int n,j = 1;
    double x,t,sum;

    printf("Enter no. of iterations: ");
    scanf("%d",&n);
    printf("Enter the power value: ");
    scanf("%lf",&x);

    // 第一项等于1
    t = 1;
    /*到目前为止所有项之和*/
    sum = t;
    /*显示要迭代的次数以及到当前为止所有项之和*/
    printf("\nIteration = %d\tSum = %lf",j,sum);
    /*迭代计算第2项至第n项*/
    for (j = 1; j < n; j++) {
        /*计算下一项*/
        t = t * x/j;
        /*将该项累加*/
        sum = sum+t;
        /*显示要迭代的次数以及到当前为止所有项之和*/
        printf("\nIteration = %d\tSum = %lf",j+1,sum);
    }  
}

输出:

Enter no. of iterations: 15
Enter the power value: 2.0
Iteration = 1   Sum = 1.000000
Iteration = 2   Sum = 3.000000
Iteration = 3   Sum = 5.000000
Iteration = 4   Sum = 6.333333
Iteration = 5   Sum = 7.000000
Iteration = 6   Sum = 7.266667
Iteration = 7   Sum = 7.355556
Iteration = 8   Sum = 7.380952
Iteration = 9   Sum = 7.387302
Iteration = 10  Sum = 7.388713
Iteration = 11  Sum = 7.388995
Iteration = 12  Sum = 7.389046
Iteration = 13  Sum = 7.389055
Iteration = 14  Sum = 7.389056
Iteration = 15  Sum = 7.389056

数组

1.程序 创建一个整型数组,使用多种方式访问数组元素

/* 使用多种方式来访问数组元素*/
#include <stdio.h>
int main(int argc, char const *argv[])
{
    int arr[] = {10,11,12,13,14};
    int i;
    // 使用数组下标访问数组元素-方法1
    for (i = 0; i<5; i++)
        printf("%d\t",arr[i]);
    printf("\n");   // 将光标移到下一行
    // 使用数组下标访问数组元素-方法2
    for (i = 0; i<5; i++)
        printf("%d\t",i[arr]);
    printf("\n");
    // 使用指针访问数组元素-方法3
    for (i = 0; i<5; i++)
        printf("%d\t",*(arr+i));
    printf("\n");
     // 使用指针访问数组元素-方法4
    for (i = 0; i<5; i++)
        printf("%d\t",*(i+arr));
}

输出:

10    11    12    13    14    
10    11    12    13    14    
10    11    12    13    14    
10    11    12    13    14

2.重要的面试题

为什么数组下标从0开始计数?
答:数组元素可以通过arr[i]形式来访问,而arr[i]在底层实现中被编辑器转换为arr+i.当i的值为0.arr+i即数组名本身.数组名代表第一个数组元素的地址.当i的值为1.arr+1代表第二个数组元素的地址.以此类推,因此,数组下标是从0开始计数.

3.程序 计算某学生5门功课的总分数及平均分.

/* 使用多种方式来访问数组元素*/
#include <stdio.h>
int main(int argc, char const *argv[])
{
    int marks[5];
    int i,tot = 0;
    float percent;
    /* 将数据元素存入数组*/
    for (i = 0; i<5; i++) {
        printf("Enter ,marks: ");
        scanf("%d",&marks[i]);
        tot += marks[i];
    }
    printf("\nToal marks = %d",tot);
    percent = tot/5;
    printf("\nPercentage = %.2f",percent);
}

输出:

Enter ,marks: 45
Enter ,marks: 50
Enter ,marks: 55
Enter ,marks: 60
Enter ,marks: 72

Toal marks = 282
Percentage = 56.00

3.重要的面试题

如何在C语言中定义常量?
答:方法一,使用const关键字,如下所示

const float PI = 3.14159;

方法二,使用#define指令,如下所示

#define MAX 50;

出现MAX的地方,使用文本“50”替换.

4.程序 使用线性搜索方法在数组中搜索某个数据元素

/* 使用线性搜索方法在数组中搜索某个数据元素 */
#include <stdio.h>
#define MAX 50
int main(int argc, char const *argv[])
{
    /* 声明一个大小为50的数组*/
    float number[MAX];

    float search;
    int i,n,location = 0;

    /* 将数字存入数组*/
    printf("How many number?\n");
    scanf("%d",&n);

    for (i = 1; i<=n; i++) {
        printf("Type the number: ");
        scanf("%f",&number[i]);
    }

    /* 接收将被搜索的数据元素*/
    printf("\nWhich number to search: ");
    scanf("%f",&search);
    /* 在数组中线性搜索该数据元素*/
    for (i = 1; i<=n; i++) {
        if (search == number[i]) {
            printf("Number found at location: %d\n",i);
            /* 在location变量中存储匹配元素的下标*/
            location = i;
        }
    }

    /* 如果location的值没有改变,那么该元素没有找到.*/
    if (location == 0)
        printf("Number not found in the list.\n");
}

输出:

How many number?
5
Type the number: 11
Type the number: 22
Type the number: 45
Type the number: -12.5
Type the number: 90

Which number to search: 22
Number found at location: 2

5.程序 将人名保存到一个字符型数组中然后再显示它

/* 将人名保存到一个字符型数组中然后再显示它 */  
#include <stdio.h>
int main(int argc, char const *argv[])
{
    /* 申明字符型数组保存人名*/
    char name1[20],name2[20];
    /* 使用%[^\n]格式串接收人名*/
    printf("Enter a name: ");
    scanf("%[^\n]",name1);

    /* 使用%s格式串接收人名*/
    printf("Enter another a name: ");
    scanf("%s",name2);

    printf("Hello %s\n",name1);
    printf("Another hello to %s\n",name2);
}

输出:

Enter a name: vijay kumar
Enter another a name: vinay Ganesh
Hello vijay kumar
Another hello to vinay

6.程序1 接收不同类型数据并显示

/* 接收一个学生的id,性别,姓名并显示它们 */
#include <stdio.h>
int main(int argc, char const *argv[])
{
    int id;
    char sex;
    char name[20];

    printf("Enter id: ");
    scanf("%d",&id);

    printf("Enter sex: ");
    sex = getchar();

    printf("\nEnter name: ");
    scanf("%[^\n]",name);

    printf("\nId = %d\n",id);
    printf("Sex = %c",sex);
    printf("Name = %s\n",name);
}

输出:

Enter id: 11
Enter sex: 
Enter name: zhxiong

Id = 11
Sex = 
Name = zhxiong

sex的信息并没有接收到,这是什么原因呢?
当id 号输入以后,用户会按下enter键,enter键对应的字符是‘\n’,会被当成字符保存到sex中,因此没有接收到性别信息,解决方法为使用fflush(stdin)语句,清空键盘的缓存区,如下7.程序所示.

7.程序2 接收一个学生的id,性别,姓名并显示它们

/* 接收一个学生的id,性别,姓名并显示它们 */
#include <stdio.h>
int main(int argc, char const *argv[])
{
    int id;
    char sex;
    char name[20];

    printf("Enter id: ");
    scanf("%d",&id);

    fflush(stdin);
    printf("Enter sex: ");
    sex = getchar();

    fflush(stdin);
    printf("\nEnter name: ");
    scanf("%[^\n]",name);

    printf("\nId = %d\n",id);
    printf("Sex = %c",sex);
    printf("Name = %s\n",name);
}

输出:

Enter id: 11
Enter sex: M
Enter name: zhxiong

Id = 11
Sex = M
Name = zhxiong

8.程序 二维数组

创建并初始化一个3行5列的二维数组并以矩阵形式显示该数组.

/* 矩阵形式显示一个外围数组 */
#include <stdio.h>
int main(int argc, char const *argv[])
{
    int i,j;

    int marks[][5] = {
        {50,60,70,80,90},
        {55,65,75,85,95},
        {59,69,79,89,99}
    };

    /* 矩阵显示二维数组,外围循环b代表行,里层循环代表列*/
    for (i = 0; i<3; i++) {
        for (j = 0; j<5; j++) {
            printf("%d\t",marks[i][j]);
        }
        /*显示新的一行s需要输出换行符*/
        printf("\n");
    }
}

输出:

50    60    70    80    90    
55    65    75    85    95    
59    69    79    89    99

9.程序 矩阵转置

/* 矩阵转置*/
#include <stdio.h>
int main(int argc, char const *argv[])
{
    // 声明变量
    int i,j,r,c;
    int mat[50][50];
    // 输入矩阵
    printf("Enter rows,cols: ");
    scanf("%d,%d",&r,&c);

    printf("Enter matrix: \n");
    for (i = 0; i<r; i++)
        for (j = 0; j<c; j++)
            scanf("%d",&mat[i][j]);
    // 显示转置矩阵
    printf("\nTranspose matrix is: \n");
    for (i = 0; i<c; i++) {
        for (j = 0; j<r; j++) {
            printf("%d\t",mat[j][i]);
        }
        printf("\n");
    }
}

输出:

Enter rows,cols: 3,4
Enter matrix: 
1 2 3 4
5 6 7 8
9 10 11 12

Transpose matrix is: 
1    5    9    
2    6    10    
3    7    11    
4    8    12    

10.程序 矩阵求和

/* 矩阵求和*/
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
    // 矩阵最大大小为10,10
    float a[10][10],b[10][10],c[10][10];
    int i,j,r1,r2,c1,c2;

    // 检查两个矩阵的行和列数
    printf("Enter no.of rows,cols of matrix1: ");
    scanf("%d,%d",&r1,&c1);
    printf("Enter no.of rows,cols of matrix2: ");
    scanf("%d,%d",&r2,&c2);

    // 检查两个矩阵是否可以相加
    if ((r1 != r2) || (c1 != c2)){
        printf("\nAddition cannot be done");
        exit(0);
    }

     // 从键盘读入matrix1的数据元素
    printf("\nEnter elements of matrix1: \n");
    for (i = 0; i<r1; i++)
        for (j = 0; j<c1; j++)
            scanf("%f",&a[i][j]);

    // 从键盘读入matrix2的数据元素
    printf("\nEnter elements of matrix2: \n");
    for (i = 0; i<r2; i++)
        for (j = 0; j<c2; j++)
            scanf("%f",&b[i][j]);

    // 对两个矩阵求和
    for (i = 0; i<r1; i++)
        for (j = 0; j<c1; j++)
            c[i][j] == a[i][j] + b[i][j];

    // 显示矩阵求和结果
    printf("\nThe sum matrix is: \n");
    for(i = 0; i<r1; i++) {
        for (j = 0; j<c1; j++) {
            printf("%.2f\t",c[i][j]);
        }
        printf("\n");
    }
}

输出:

Enter no.of rows,cols of matrix1: 2,3
Enter no.of rows,cols of matrix2: 2,3

Enter elements of matrix1: 
1.1 2.2 3.3
4 5 6

Enter elements of matrix2: 
1.1 2.2 3.3
4.1 5.0 6

The sum matrix is: 
2.20    4.40    6.60    
8.10    10.00    12.00    

11.程序 三维数组

/* 矩阵求和*/
#include <stdio.h>
int main(int argc, char const *argv[])
{
    int i,j,k;
    // 三个二维数组,每个二维数组3行5列
    int marks[3][3][5] ={
            {{11,12,13,14,15},
            {16,17,18,19,20},
            {21,22,23,34,25}},

            {{26,27,28,29,30},
            {31,32,33,34,35},
            {36,37,38,39,40}},

            {{41,42,43,44,45},
            {46,47,48,49,50},
            {51,52,53,54,55}},
    };
    // 读取并显示
    for (i = 0; i<3; i++) {
        for (j = 0; j<3; j++) {
            for (k=0; k<5; k++)
            printf("%d\t",marks[i][j][k]);
        printf("\n");
        }
        printf("\n");
    }
}

输出:

11    12    13    14    15    
16    17    18    19    20    
21    22    23    34    25    

26    27    28    29    30    
31    32    33    34    35    
36    37    38    39    40    

41    42    43    44    45    
46    47    48    49    50    
51    52    53    54    55

12.重要的面试题

数组在内存中是如何存储的?
答:不论是一维,二维或n维数组,它们的数据元素都是在内存中连续存储的,这意味着在系统底层会为数组分配连续的内存块.

函数

1.重要的面试题

scanf()和printf()函数的返回值是什么?
答:scanf()函数返回传递给函数的变量个数.例如,

scanf("%d%d",&x,&y);    // 返回2.

printf()函数返回显示为输出的字节数.例如,

printf("Hello"); // 返回5

2.程序 函数的形式(此处仅列举一种)

/* sum函数不需要传值也没有返回值*/
#include <stdio.h>
void sum(){
    int x = 10,y = 25;
    int z = x+y;
    printf("Result = %d.\n",z);
}
int main(){
    sum();
}

输出:

Result = 35.

3.程序 函数的定义

/* 用square()函数计算整数的平方*/
#include <stdio.h>
int square(int num){
    int result;
    result = num*num;
    return result;
}
int main(){
    int x,res;
    printf("Enter an integer: ");
    scanf("%d",&x);
    // 调用函数并传递参数x,同时保存返回值
    res = square(x);
    printf("Square value = %d\n",res);
}

输出:

Enter an integer: 16
Square value = 256

4.程序

/* 两个整数的最大公约数*/
#include <stdio.h>
// 函数原型声明
int gcd(int u,int v);
int main(){
    int x,y;
    printf("Type two integer values: ");
    scanf("%d,%d",&x,&y);
    printf("GCD value = %d\n",gcd(x, y));
}

int gcd(int u,int v){
    int r;
    while (v!=0) {
        r = u%v;
        u = v;
        v = r;
    }
    return u;
}

输出:

Type two integer values: 150,35
GCD value = 5

5.程序

/* 判断是否为d素数*/
#include <stdio.h>
int isprime(int n){
    int i,flage = 1;
    for (i=2; i<n; i++) {
        if (n%i == 0) {
            flage = 0;
            break;
        }
    }
    return flage;
}

int main(){
    int num,result;
    printf("Enter number: ");
    scanf("%d",&num);

    result = isprime(num);
    if (result == 1)
        printf("%d is prime\n",num);
    else printf("%d is not prime\n",num);
}

输出:

Enter number: 11
11 is prime

6.程序 向函数传递数组

#include <stdio.h>
// 输入数组存储到一维数组中
void getarr(int arr[],int n){
    int i;
    printf("\n");
    for (i=0; i<n; i++) {
        printf("Enter element: ");
        scanf("%d",&arr[i]);
    }
}

// 显示数组中的元素
void disparr(int arr[],int n){
    int i;
    for (i=0; i<n; i++)
        printf("%d\t",arr[i]);
}

int main(){
    int  x[50];
    int n;
    printf("How many elements? ");
    scanf("%d",&n);
    /*读取数组, 传递h数组名和数据元素个数给函数*/
    getarr(x,n);
    // 显示数组
    disparr(x,n);
}

输出:

How many elements? 5

Enter element: 44
Enter element: 55
Enter element: 66
Enter element: 77
Enter element: 88
44    55    66    77    88

7.程序 冒泡排序算法

/* 冒泡排序*/
#include <stdio.h>
#define MAX 50
void sorting(float arr[],int n){
    float t;
    int i,pass;
    for (pass = 0; pass<=n-2; pass++) {
        for (i = 0; i<=n-2; i++) {
            if (arr[i]>arr[i+1]) {
                //交换元素
                t = arr[i];
                arr[i]>arr[i+1];
                arr[i+1]=t;
            }
        }
    }
}
int main(){
    float x[MAX];
    int i,n;
    printf("How many elements? ");
    scanf("%d",&n);
    // 向数组中存储h数字
    for (i=0; i<n; i++) {
        printf("Enter number: ");
        scanf("%f",&x[i]);
    }
    // 调用排序函数,传递数组参数
    sorting(x, n);
    printf("\nSorted elements:\n");
    for (i=0; i<n; i++) {
        printf("%.2f\t",x[i]);
    }
}

输出:

How many elements? 5
Enter number: 11
Enter number: 23
Enter number: 45
Enter number: 66
Enter number: 37

Sorted elements:
11.00    23.00    45.00    66.00    66.00

8.程序 编写一个函数读取并显示它

#include <stdio.h>
#define ROWS 50
#define COLS 50
void getarr(int arr[ROWS][COLS],int r,int c){
    int i,j;
    for (i=0; i<r; i++) {
        for (j=0; j<c; j++) {
            scanf("%d",&arr[i][j]);
        }
    }
}

void disparr(int arr[ROWS][COLS],int r,int c){
    int i,j;
    for (i=0; i<r; i++) {
        for (j=0; j<c; j++) {
            printf("%d\t",arr[i][j]);
        }
        printf("\n");
    }
}

int main(){
    int x[ROWS][COLS];
    int r,c;
    printf("How many row,cols? ");
    scanf("%d,%d",&r,&c);

    // 使用getarr()函数读取二维数组并制定数组名,列数以及行数
    printf("\nEnter matrix:\n");
    getarr(x, r, c);
    printf("\nYour matrix:\n");
    // 使用disparr()函数显示二维数组传递数组名,行数,列数
    disparr(x, r, c);
}

输出:

How many row,cols? 2, 3

Enter matrix:
1 2 3
4 5 6

Your matrix:
1    2    3    
4    5    6    

9.递归函数

/* 一个计算阶乘的递归函数*/
#include <stdio.h>
long int factorial(int n){
    long int result;
    if (n == 0)
        result = 1;
    else
        result = n*factorial(n-1);
    return result;
}

int main(){
    int j;
    for (j = 0; j<10; j++) {
        printf("Factorial(%d) = %ld\n",j,factorial(j));
    }
}

输出:

Factorial(0) = 1
Factorial(1) = 1
Factorial(2) = 2
Factorial(3) = 6
Factorial(4) = 24
Factorial(5) = 120
Factorial(6) = 720
Factorial(7) = 5040
Factorial(8) = 40320
Factorial(9) = 362880

10.程序 理解函数变量的作用域

/* 演示函数变量的作用域*/
#include <stdio.h>
void funct(){
    /* 块作用域,临时变量*/
    int x = 1;
    /* 块作用域,永久变量*/
    static int y = 1;
    printf("x = %d\ty = %d",x,y);
    x++;
    y++;

}

int main(){
    // 调用四次函数
    funct();
    funct();
    funct();
    funct();
}

输出:

x = 1    y = 1
x = 1    y = 2
x = 1    y = 3
x = 1    y = 4

11.重要的面试题

什么是库;形参和实参有什么区别?
答:对于程序而言,库就是一个语言或者软件对非常有用的内置资源的封装,例如,C标准库包含了许多内置函数.
形参是函数定义中变量,实参表示函数在调用时传递的参数值.

12.重要的面试题

函数声明和函数定义有什么区别?
答:函数的定义指的是函数的具体实现,内存分配,而函数声明或原型表示的是函数的引用,它告诉编辑器函数在程序某处已经被定义,在链接对的时候会被找到,通常,函数声明写在main()函数之前,而函数的定义则在main()之后.

13.重要的面试题

什么是静态函数?
答:静态函数就是其作用域被限定在当前程序文件中的一个函数.静态函数可以被同一个程序文件的代码看见和使用,而不能被文件外的函数使用,静态函数对于解决函数名冲突非常有用.

14.重要的面试题

除.h之外,其他类型文件可以被#include语句包含吗?
答:可以将任意的文件当作头文件来包含.例如,

#include <myfile.txt>

myfile.txt文件可能包含其他头文件或者函数原型.

15.重要的面试题

C里面的函数可以重载吗?
答:编写有相同的名字但是参数列表各不相同的函数叫做函数重载.C语言部分支持函数重载,例如,printf()函数:

printf("%d",x); // 两个参数
printf("%d,%d",x,y); // 三个参数

在C内置函数里面可以这样做函数重载,但是其他地方不支持函数重载,用户自定义函数不可以重载.

字符与字符串

1.重要的面试题

字符串和字符类型数组的区别是什么?
答:在默认情况下,字符串内存是静态分配的,因此它由NULL初始化.而字符数组的内存不是静态分配的,因此字符数组默认由垃圾数据填充;
两个相同的字符串有相同的内存地址,而两个内容一样的字符数组的内存地址却不一样.

2.重要的面试题

为什么字符串以‘\0’字符作为结尾?
答:字符串在内存中是逐字符顺序存储的,因此,在读取字符串时,需要知道字符串在何处结尾,处于这个目的,编译器会自动在字符串尾部追加‘\0’字符作为字符串结束的标志.

3.重要的面试题

长度为20的字符数组能存储多少个字符?
答:在C语言中,字符串以附加的‘\0’字符结尾,即最后一个字符空间留给‘\0’,所以只能存储19个字符.

3.程序 strcy()与strncpy()

/* 拷贝某字符串的前若干个字符串至s1中*/
#include <stdio.h>
#include <string.h>
int main(int argc, const char * argv[]) {
    char s1[10],s2[50];
    int n;

    puts("Enter a string: ");
    gets(s2);

    puts("How many chars to copy?");
    scanf("%i",&n);
    strncpy(s1, s2, n);
    printf("The first %d chars are:%s",n,s1);
}

输出:

Enter a string:
Nageswara Rao
How many chars to copy?
3
The first 3 chars are: Nag

4.程序 strchr()

// 在字符串中查找指定字符串第一次出现的位置
#include <stdio.h>
#include <string.h>
int main(int argc, const char * argv[]) {
    char str[100],ch;
    char *n;

    printf("Enter a string: ");
    gets(str);
    printf("Enter a character: ");
    ch = getchar();

    n = strchr(str, ch);
    if (n == NULL)
        printf("The character is not found");
    else
        printf("The first occurrence is %d",n-str);
}

输出:

Enter a string: Bottle
Enter a character: t
The first occurrence is 2

5.程序

// 在一个字符串中查找指定字符串首次出现的位置
// 在字符串中查找指定字符串第一次出现的位置
#include <stdio.h>
#include <string.h>
int main(int argc, const char * argv[]) {
    char str[100],sub[20];
    char *n;

    printf("Enter main string: ");
    scanf("%[^\n]",str);
    fflush(stdin);

    printf("Enter sub string: ");
    scanf("%[^\n]",sub);

    n = strstr(str, sub);
    if (n == NULL)
        printf("sub string not found");
    else printf("Sub string is found at position %d",n-str);
}

输出:

Enter main string: This is book
Enter sub string: is
Sub string is found at position 2

6.程序

//  向函数传递一组字符串并在函数内显示它们
// 在字符串中查找指定字符串第一次出现的位置
#include <stdio.h>
#define MAX 50
void myfunction(char arr[MAX][MAX],int n){
    int i;
    for (i = 0; i<n; i++) {
        puts(arr[i]);
    }
}
int main(int argc, const char * argv[]) {
    char str[MAX][MAX];
    int i,n;
    printf("How many strings?");
    scanf("%i",&n);
    fflush(stdin);

    printf("Enter strings: \n");
    for (i = 0; i<n; i++) {
        gets(str[i]);
    }
    printf("Entered strings are: \n");
    myfunction(str, n);

}

存储类型

C中包含4种存储类型:自动存储类型(auto),寄存器存储类型(register),静态存储类型(static),外部存储类型(extern).

1.程序 帮助理解块或函数中变量的作用域

#include <stdio.h>
void function(){
    // 在函数中声明变量j,因此该变量仅在函数内部可见
    int j = 100;
    printf("\n%d",j);
}

int main(int argc, const char * argv[]) {
    {
        // 在块中声明变量i,因此,该变量仅在函数内部可见
        int i = 10;
        printf("\n%d",i);
    }
    printf("\n%d",i);   // 这里变量i不可见
    printf("\n%d",j);   // 这里变量j不可见
}

2.程序 auto存储类型 帮助理解自动变量的作用域

#include <stdio.h>
int main(int argc, const char * argv[]) {
    {
        // 代码块1开始
        auto int i = 100;
        {
            // 代码块2开始
            printf("\n%d",i);
        }   // 代码块2结束
        printf("\n%d",i);
        // 代码块2结束
    }
    printf("\n%d",i);   // 未定义符号i
}

3.程序 register 存储类型

// register存储类型
#include <stdio.h>
int main(){
    register int i;
    for(i = 0;i<10;i++){
        printf("%d ",i);
    }
}

输出:

0 1 2 3 4 5 6 7 8 9

4.重要的面试题

寄存器变量是什么,它有什么优势?
答:寄存器变量是变量值存储于CPU寄存器中的变量.寄存器变量访问速度快于其他变量,因为保存在CPU中,处理器可以即刻使用.

5.程序 static 存储类型

// 静态存储类型
#include <stdio.h>
void test(){
    static int i = 1;
    auto int j = 1;
    printf("\n%d\t%d",i++,j++);
}
int main(){
    test();
    test();
    test();
}

输出:

1    1
2    1
3    1

6.重要的面试题

static关键字的作用?
答:当使用关键字‘static’声明变量时,变量值会在函数调用之前保留;
当使用关键字“static”声明函数时,那么这个函数对其他源文件不可用;
一般而言,全局变量对于其他源文件可用,但是当声明为static时,对其他源文件不可用.

7.程序 extern 存储类型 帮助理解外部变量特性

// 外部存储类型
#include <stdio.h>
int x;  // 这是一个全局变量
void one(){
    x++;
    printf("\nx in one = %d",x);
}
void two(){
    x++;
    printf("\nx in main = %d",x);
}
int main(){
    printf("\nx in main = %d",x);
    one();
    two();
}

输出:

x in main = 0
x in one = 1
x in main = 2

8.程序 为了使用全局变量,在函数中使用关键字“extern”

// 外部存储类型
#include <stdio.h>
int x = 10;  // 这是一个全局变量
void one(){
    extern int x;
    x++;
    printf("\nx in one = %d",x);
}
void two(){
    extern int x;
    x++;
    printf("\nx in main = %d",x);
}
int main(){
    extern int x;
    printf("\nx in main = %d",x);
    one();
    two();
}

输出:

x in main = 10
x in one = 11
x in main = 12

9.程序 局部变量

// 外部存储类型
#include <stdio.h>
int x = 10;  // 这是一个全局变量
void one(){
    int x = 20;
    printf("\nx in one = %d",x);
}
void two(){
    extern int x;   // 这是一个全局变量
    printf("\nx in two = %d",x);
}
int main(){
    extern int x;   // 引用全局变量
    printf("\nx in main = %d",x);
    one();
    two();
}

输出:

x in main = 10
x in one = 20
x in two = 10

10.重要的面试题

局部变量与全局变量之间的区别是什么?
答:局部变量是声明在块或函数内部的变量.局部变量的作用域局限于该块或者函数.局部变量如果没有初始化,将包含垃圾数据;
全局变量在所以块和函数之前声明的变量.全局变量对所有在它之后声明的函数有效.全局变量使用默认值初始化,如0;

指针

1.程序 指针

// 如何使用指针
#include <stdio.h>
int main(int argc, const char * argv[]) {
    int v = 15;
    // 声明一个int类型指针
    int *pv;
    // 将V的内存地址保存到pv中
    pv = &v;

    printf("Value of v = %d",v);
    printf("\nValue of pv = %u",pv);
    printf("\nValue of *pv = %d",*pv);
}

输出:

Value of v = 15
Value of pv = 4022334908
Value of *pv = 15

2.重要的面试题

什么是间接引用?
答:当声明一个变量时,变量名是对变量值的直接引用,而声明一个指针时,是对其指向变量的间接引用,如果prt代表一个指针,那么可以使用*prt来访问指针prt指向的变量的值.

3.程序 指针运算

// 不使用指针对两个整数变量的值进行互换
// 不使用指针对两个整数变量的值进行互换
#include <stdio.h>
void swap(int x,int y);
int main(int argc, const char * argv[]){
    int a,b;
    a = 10;
    b = 5;
    printf("Before swapping => a = %d,b = %d",a,b);
    swap(a, b);
    printf("\nAfter swapping => a = %d,b = %d",a,b);
}
void swap(int x,int y) {
    int t;
    t = x;
    x = y;
    y = t;
}

输出:

Before swapping => a = 10,b = 5
After swapping => a = 10,b = 5

4.程序 指针运算

// 使用指针对两个整数变量的值进行互换
#include <stdio.h>
void swap(int *x,int *y);
int main(int argc, const char * argv[]){
    int a,b;
    a = 10;
    b = 5;
    printf("Before swapping => a = %d,b = %d",a,b);
    swap(&a, &b);
    printf("\nAfter swapping => a = %d,b = %d",a,b);
}
void swap(int *x,int *y) {
    int t;
    t = *x;
    *x = *y;
    *y = t;
}

输出:

Before swapping => a = 10,b = 5
After swapping => a = 5,b = 10

5.程序 数组与指针

// 使用指针计算数组大小及显示数组元素
#include <stdio.h>
int main(int argc, const char * argv[]){
    int x[50];
    int i = 0;
    char resp = 'y';
    int *p1,*p2;

    p1 = &x[0];
    while (resp=='y'||resp=='Y') {
        printf("\nEnter an element: ");
        scanf("%d",&x[i]);
        printf("\nEnter one more?(y/n:) ");
        fflush(stdin);
        resp = getchar();
        i++;
    }
    p2 = &x[i];
//    printf("\nNo of elements in arry = %ld",p2-p1);

    printf("\nDisplaying elements through pointers:\n");
    for (; p1<p2; )
        printf("%d\t",*p1++);
}

6.程序 使用指针查找数组中最小元素

// 使用指针查找数组中最小元素
#include <stdio.h>
int main(int argc, const char * argv[]){
    int i,n,small,*ptr,a[50];
    printf("How many elements? ");
    scanf("%d",&n);
    printf("Enter elements: \n");
    for (i = 0; i<n; i++)
        scanf("%d",&a[i]);
    ptr = a;
    small = *ptr;
    // 对ptr进行递增操作使其引用数组第二个元素
    ptr++;
    for (i = 1; i<n-1; i++) {
        if (*ptr<small)
            small = *ptr;
            ptr++;
    }
    printf("Smallest element = %d\n",small);
}

输出:

How many elements? 5
Enter elements: 
5 -10 25 -15 13
Smallest element = -15

7.程序 使用指针访问一维数组中的数据元素

// 使用指针访问一维数组中的数据元素
#include <stdio.h>
int main(int argc, const char * argv[]){
    int arr1[5] = {10,11,12,13,14};
    // 将数组起始地址保存到指针ptr1中
    int *ptr1 = arr1;
    int i;

    printf("Accessing elements through arrayname:\n");
    for (i = 0; i<5; i++)
        printf("%d\t",*(arr1+i));

    printf("\nAccessing elements through pointer: \n");
    for (i = 0; i<5; i++)
        printf("%d\t",*ptr1++);
}

输出:

Accessing elements through arrayname:
10    11    12    13    14    
Accessing elements through pointer: 
10    11    12    13    14

8.程序 使用指针访问二维数组中的数据元素

// 使用指针访问二维数组中的数据元素
#include <stdio.h>
int main(int argc, const char * argv[]){
    int arr2[][4] = {
        {1,2,3,4},
        {5,6,7,8},
        {9,10,11,12}
    };

    int *ptr2 = &arr2[0][0];
    int i,j;

    printf("\nAccessing elements using array name: \n");
    for (i = 0; i<3; i++) {
        for (j = 0; j<4; j++) {
            printf("%d\t",*(*(arr2+i)+j));
        }
        printf("\n");
    }
    printf("\nAccessing elements using pointer: \n");
    for (i = 0; i<3; i++) {
        for (j = 0; j<4; j++) {
            printf("%d\t",*ptr2++);
        }
        printf("\n");
    }
}

输出:

Accessing elements using array name: 
1    2    3    4    
5    6    7    8    
9    10    11    12    

Accessing elements using pointer: 
1    2    3    4    
5    6    7    8    
9    10    11    12

9.程序 静态内存和动态内存

// 静态内存和动态内存
#include <stdio.h>
int main(int argc, const char * argv[]){
    int num;
    int *ptr;

    printf("\nStatic memory allocation: ");
    printf("\nEnter a number: ");
    scanf("%d",&num);
    printf("You entered: %d",num);

    printf("\n\nDynamic memory allocation: ");
    printf("\nenter a number: ");

    // 动态分配内存,并使用指针ptr引用该内存块
    ptr = (int*)malloc(sizeof(int));
    // 存储数据到ptr所引用的内存块中
    scanf("%d",ptr);
    printf("You entered: %d",*ptr);
}

输出:

Static memory allocation: 
Enter a number: 100
You entered: 100

Dynamic memory allocation: 
enter a number: 200
You entered: 200

10.程序 为两个浮点数分配动态内存并求和

// 使用指针为两个浮点数分配动态内存并求和
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char * argv[]){
    float *n1,*n2,*sum;
    // 动态分配内存
    n1 = (float*)malloc(sizeof(float));
    n2 = (float*)malloc(sizeof(float));
    sum = (float*)malloc(sizeof(float));

    printf("Enter two number: ");
    scanf("%f%f",n1,n2);
    *sum = *n1+*n2;
    printf("Sum of two numbers: %.2f",*sum);
}

输出:

Enter two number: 10.5 22.57
Sum of two numbers: 33.07

11.程序 指针数组

// 为一维整型数组分配动态内存
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char * argv[]){
    int *arr[50];
    int i,n;
    printf("How many elements? ");
    scanf("%d",&n);

    printf("Enter elements: \n");
    for (i = 0; i<n; i++) {
        arr[i] = (int*)malloc(sizeof(int));
        scanf("%d",arr[i]);
    }
    printf("\nThe elements of array: \n");
    for (i = 0; i<n; i++)
        printf("%d\t",*arr[i]);
}

输出:

How many elements? 5
Enter elements: 
22 23 44 55 78

The elements of array: 
22    23    44    55    78    

12.重要的面试题

函数malloc()与函数calloc()有什么区别?
答:malloc()函数用于从堆上分配指定字节数的内存,而calloc()函数用于从堆上分配若干个指定字节数的内存块.

指针

1.程序 使用指针实现了一个参数和返回值q均为字符串的函数

// 使用指针实现了一个参数和返回值q均为字符串的函数
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *function(char *n){
    char *s1 = "Hello";
    // 将n指向的字符串追加到s1尾部
    strcat(s1, n);
    return  s1;
}

int main(int argc, const char * argv[]){
    char *name;
    name = (char*)malloc(20);
    printf("Enter your name: ");
    gets(name);
    printf("%s",function(name));
}

输出:

Enter your name: Nihaar Chandra
Hello  Nihaar Chandra

2.程序 使用指针和函数传递一位数组并返回它

// 使用指针和函数传递一维数组并返回f它
#include <stdio.h>

int *get(int n){
    int i;
    int *x;     // 该指针指向一个数组
    // 动态内存分配n个内存块
    x = (int*)malloc(n*sizeof(int));
    printf("Enter elements: \n");
    for (i = 0; i<n; i++)
        scanf("%d",x+i);
        return x;
}

// 接收一个一维数组并显示它
void display(int *x,int n){
    int i;
    printf("\n1D array elements: \n");
    for (i = 0; i<n; i++)
        printf("%d\t",*(x+i));
}
int main(int argc, const char * argv[]){
    int *a;
    int n;
    printf("How many elements? ");
    scanf("%d",&n);
    a = get(n);     // get()函数创建并返回一个数组
    display(a, n);  // 传递指针参数并显示数组元素
}

输出:

How many elements? 5
Enter elements: 
11 22 33 44 60

1D array elements: 
11    22    33    44    60    

3.程序 使用指针和函数来接收和显示一个二维数组

/ 使用指针和函数来接收和显示一个二维数组
#include <stdio.h>
// 将数据元素保存至二维数组
void get(int *x[],int r,int c){
    int i,j;
    printf("Enter elements: \n");
    for (i = 0; i<r; i++) {
        for (j = 0; j<c; j++)
            scanf("%d",(*(x+i)+j));
    }
}

// 该函数以矩阵形式显示一个二维数组
void display(int *x[],int r,int c){
    int i,j;
    printf("\nThe array elements are: \n");
    for (i = 0; i<r; i++){
        for (j = 0; j<c; j++) {
            printf("%d\t",*(*(x+i)+j));
        }
        printf("\n");
    }
}
int main(int argc, const char * argv[]){
    int *a[50];
    int i,r,c;
    printf("Enter rows cols: ");
    scanf("%d%d",&r,&c);
    // r行c列的二维数组分配动态内存
    for (i = 0; i<r; i++)
        a[i] = (int*)malloc(c*sizeof(int));
    // 读入数据元素
    get(a, r, c);
    // 显示数组元素
    display(a, r, c);
}

输出;

Enter rows cols: 3 4
Enter elements: 
1 2 3 4 5 6 7 8 9 10 11 12 

The array elements are: 
1    2    3    4    
5    6    7    8    
9    10    11    12    

4.程序 使用指针数组来表示一组字符串

/ 对字符串排序-冒泡排序
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 50
void sorting(char *arr[],int n){
    int i,pass;
    char *t = (char*)malloc(20);    // 临时字符串
    for (pass = 0; pass<=n-2; pass++) {
        for (i = 0; i<=n-2; i++) {
            if (stricmp(arr[i],arr[i+1])>0) {
                strcpy(t,arr[i]);
                strcpy(arr[i], arr[i+1]);
                strcpy(arr[i+1], t);
            }
        }
    }
}
int main(int argc, const char * argv[]){
    char *city[MAX];
    int i,n;
    printf("How many strings? ");
    scanf("%d",&n);
    // 分配动态内存存储字符串
    for (i = 0; i<n; i++) {
        printf("Enter city name: ");
        city[i] = (char*)malloc(20);
        gets(city[i]);
    }
    sorting(city, n);
    // 显示已排序的字符串数组
    printf("Sorted city names:\n");
    for (i = 0; i<n; i++) {
        puts(city[i]);
    }
}

输出:

How many strings? 5
Enter city name: Hyderabad
Enter city name: Delhi
Enter city name: Kolkata
Enter city name: Bangalore
Enter city name: Beijing
Sorted city names:
Bangalore
Beijing
Hyderabad
Delhi
Kolkata

5.重要的面试题

什么是指针数组?它们有什么用途?
答:单个指针在引用单个数组元素时非常有用,而一个指针数组能代表一组指针,指针数组在处理二维数组或一组字符串时非常有用.

6.重要的面试题

指针与数组之间有什么区别?
答:数组创建在静态内存上,并且数组元素是连续分布的,数组元素通过“数组名+下标”来写读,而指针引用的时堆内存空间随机分配的内存块,只能通过内存地址来访问;
数组容量是在编译期确定的,而指针引用的内存大小可以在运行时更改.

7.程序 创建和 使用函数指针

// 帮助理解创建使用函数指针
#include <stdio.h>
void sum(int a,int b){
    printf("sum = %d\n",a+b);
}

int main(int argc, const char * argv[]){
    void (*fp)(int a,int b);
    fp = sum;
    (*fp)(5,10);
    fp(5,10);
}

输出:

sum = 15
sum = 15

8.重要的面试题

什么是回调函数机制?
答:通过传递函数地址的方式调用一个函数叫做回调函数机制,为了向函数传递函数地址,需要使用函数指针.

9.程序 回调函数机制动态调用函数

// 回调函数机制动态调用函数
#include <stdio.h>
#include <string.h>
// 按AP邦法规计算税额的函数
float ap_tax(float salesamt){
    printf("According to AP Govt rules");
    // 税率为25%
    return salesamt*0.25;
}
// 按karnataka邦法规计算税额的函数
float karnataka_tax(float salesamt){
    printf("According to Karnataka rules");
    // 税率为20%
    return salesamt*0.20;
}
// 该函数中实现了回调机制,使用传入的函数指针及销售额参数
float cac_tax(float salesamt,float(*fp)(float)){
    // 调用fp代表的函数
    return (*fp)(salesamt);
}

int main(int argc, const char * argv[]){
    float salesamt;
    char state[20];

    printf("\nEnter sales amount: ");
    scanf("%f",&salesamt);
    fflush(stdin);

    printf("\nEnter the state (AP/Karnataka): ");
    gets(state);

    // 用户输入AP,调用calc_tax函数时传递的参数为ap_tax函数的地址
    if (strcmp(state, "AP")==0)
        printf("\nState tax = %.2f",calc_tax(salesamt,ap_tax));

    // 用户输入karnatake,调用calc_tax函数时传递的参数为karnatake_tax函数的地址
    else if (strcmpi(state, "karnatake")==0)
        printf("\nState tax = %.2f",calc_tax(salesamt,karnatake_tax));

    else printf("\nWrong state name entered.");
}

输出:

Enter sales amount: 100000.00
Enter the state (AP/Karnataka): ap
According to AP Govt rules
State tax = 25000.00 

10.程序 near,far,huge指针

// 指向指针的指针
#include <stdio.h>
int main(int argc, const char * argv[]){
    int var =100;   // 变量
    int *p1;     // 指针
    int **p2;   // 指向指针的指针

    p1 = &var;  // p1中存储变量的地址
    p2 = &p1;   // p2中存储指针变量的地址

    // p1的值为变量的地址.而*p1代表变量的值
    printf("Value through p1 = %d",*p1);
    // p2的值为p1 的地址,*p2 为p1的值.即变量的地址,因此**p代表变量的值
    printf("\nValue through p2 = %d",**p2);
}

输出:

Value through p1 = 100
Value through p2 = 100

11.重要的面试题

什么是null指针,什么是野指针?
答:null指针指的是不指向任何对象的指针,可以用常量NULL来初始化nill指针,使该指针不指向如何内存地址;
野指针,被声明但是没有被初始化的指针,一个野指针里存的是垃圾数据.

12.重要的面试题

指针常量和常量指针有什么区别?
答:指针常量,指的是指针的值是常量,其值不能被改变,例如:

int *const ptr1;

这意味着ptr只能指向一个整型变量,而不能在后续操作中指向另外一个整型变量.尽管指针常量指向的整型变量的值是可以改变的;
常量指针,代表一个指针指向其变量的值不能改变,例如:

const int*ptr2;

在这里,ptr引用的变量的值不能改变,尽管该指针可以指向其他整数.

结构体和联合体

1.程序 声明并初始化结构体

// 使用结构体显示电子账单
#include <stdio.h>
#include <string.h>
int main(int argc, const char * argv[]){
    // 创建一个结构体
    struct ebill{
        int mno;
        char name[20];
        int previous;
        int present;
        int units;
        float charge;
    };
    // 声明ebill类型变量eb
    struct ebill eb;

    // 将数据存储到结构体变量的数据成员中
    eb.mno = 1005;
    strcpy(eb.name, "Raj Kumar");
    eb.previous = 500;
    eb.present = 750;
    eb.units = eb.present - eb.previous;
    eb.charge = eb.units*4.50;

    // 从结构体实例中读取并显示数据
    printf("Meter no: %d\n",eb.mno);
    printf("Customer name: %s\n",eb.name);
    printf("Previous reading: %d\n",eb.previous);
    printf("Present reading: %d\n",eb.present);
    printf("Total units: %d\n",eb.units);
    printf("Total charge: %8.2f\n",eb.charge);
}

输出:

Meter no: 1005
Customer name: Raj Kumar
Previous reading: 500
Present reading: 750
Total units: 250
Total charge:  1125.00

2.程序 结构体指针

// 使用结构体指针访问和显示结构体实列的数据成员
#include <stdio.h>
#include <string.h>
int main(int argc, const char * argv[]){
    // 创建一个结构体
    struct ebill{
        int mno;
        char name[20];
        int previous;
        int present;
        int units;
        float charge;
    };
    // 声明一个结构体指针
    struct ebill *ptr = NULL;

    // 使用->操作符向结构体传值
    ptr->mno = 1005;
    strcpy(ptr->name, "Raj Kumar");
    ptr->previous = 500;
    ptr->present = 750;
    ptr->units = ptr->present - ptr->previous;
    ptr->charge = ptr->units*4.50;

    // 使用->从结构体实例中读取并显示数据
    printf("Meter no: %d\n",ptr->mno);
    printf("Customer name: %s\n",ptr->name);
    printf("Previous reading: %d\n",ptr->previous);
    printf("Present reading: %d\n",ptr->present);
    printf("Total units: %d\n",ptr->units);
    printf("Total charge: %8.2f\n",ptr->charge);
}

输出:

Meter no: 1005
Customer name: Raj Kumar
Previous reading: 500
Present reading: 750
Total units: 250
Total charge:  1125.00

3.程序向函数传递结构体参数

// 使用结构体变量向函数传递参数
#include <stdio.h>
#include <string.h>
// 全局声明一个结构体
struct student{
    int rno;
    char name[20];
};

// 用于显示结构体的函数
void display(struct student st);
int main(int argc, const char * argv[]){
    // 声明结构体变量
    struct student s;

    // 存储数据至结构体成员变量
    s.rno = 10;
    strcpy(s.name, "Priya");
    // 调用函数,传递结构体变量
    display(s);
}

// 用于显示结构体成员的函数
void display(struct student st){
    printf("rno = %d\n",st.rno);
    printf("Name = %s\n",st.name);
}

输出:

rno = 10
Name = Priya

4.程序 结构体指针传参

// 使用结构体变量向函数传递参数
#include <stdio.h>
#include <string.h>
// 全局声明一个结构体
struct student{
    int rno;
    char name[20];
};

// 用于显示结构体的函数
void display(struct student *ptr);
int main(int argc, const char * argv[]){
    // 声明结构体变量
    struct student *s;

    // 存储数据至结构体成员变量
    s->rno = 10;
    strcpy(s->name, "Priya");
    // 调用函数,传递结构体变量
    display(s);
}

// 用于显示结构体成员的函数
void display(struct student *ptr){
    printf("rno = %d\n",ptr->rno);
    printf("Name = %s\n",ptr->name);
}

5.程序 拷贝结构体变量

// 将一个结构体变量的数据拷贝到另一个结构体中
#include <stdio.h>
int main(int argc, const char * argv[]){
    // 定义结构体
    struct employee{
        int id;
        char name[20];
    };
    // 初始化e1
    struct employee e1 = {10,"Venu"};
    // e2也是结构体变量
    struct employee e2;
    // 讲e1n的内容拷贝至e2
    e2 = e1;

    // 显示
    printf("Id = %d\n",e2.id);
    printf("Name = %s\n",e2.name);
}

输出:

// 将一个结构体变量的数据拷贝到另一个结构体中
#include <stdio.h>
int main(int argc, const char * argv[]){
    // 定义结构体
    struct employee{
        int id;
        char name[20];
    };
    // 初始化e1
    struct employee e1 = {10,"Venu"};
    // e2也是结构体变量
    struct employee e2;
    // 讲e1n的内容拷贝至e2
    e2 = e1;

    // 显示
    printf("Id = %d\n",e2.id);
    printf("Name = %s\n",e2.name);

}

6.程序 嵌套结构体

// 嵌套结构体
#include <stdio.h>
// 存储生日信息
struct dob{
    int dd;
    int mm;
    int yy;
};

// 存储雇员数据
struct employee{
    int id;
    char name[20];
    struct dob d;   // d是一个dob结构体变量
};

int main(int argc, const char * argv[]){
    struct employee e;

    printf("Enter employee id: \n");
    scanf("%d",&e.id);
    fflush(stdin);

    printf("Enter employee name: \n");
    gets(e.name);
    printf("Enter date of birth (dd/mm/yyyy): \n");
    scanf("%d%d%d",&e.d.dd,&e.d.mm,&e.d.yy);

    printf("Id = %d\n",e.id);
    printf("Name = %s\n",e.name);
    printf("Date of birth: %d/%d/%d\n",e.d.dd,e.d.mm,e.d.yy);
}

输出:

Enter employee id: 
1001
Enter employee name: DaWei
Enter date of birth (dd/mm/yyyy): 
22/06/1988
Id = 1001
Name = DaWei
Date of birth: 22/06/1988

6.程序 查找系统日期和时间

// 联合体的行为
#include <stdio.h>
int main(int argc, const char * argv[]){
    // 定义一个联合体
    union mixed{
        char ch;
        int in;
    };
    // 声明联合体变量u
    union mixed u;
    // 将字符A保存至u的数据成员ch中
    u.ch = 'A';
    // 显示该联合体实例的两个数据成员
    printf("ch value = %c\n",u.ch);
    printf("in value = %i\n",u.in);
}

输出:

ch value = A
in value = 65

7.重要的面试题

何时为结构体分配内存?
答:声明结构体类型时并不会为结构体分配内存,只有当声明结构体变量时才会为其分配内存.

8.重要的面试题

结构体和数组有什么区别?
答:数组只能存储同一类型的数据,结构体可以存储不同类型的数据;
如果将一个数组的元素拷贝至另外一个数组,则需要逐个元素拷贝,而讲一个结构体实列中的数据拷贝至另外一个结构体实列,只需要逐个拷贝或直接将结构体变量赋值给另外一个结构体变量.

9.重要的面试题

结构体变量是否可以当左值来处理?
答:可以,当表达式左边变量为结构体变量是,例如,

struct dob{
    int dd;
    int mm;
    int yy;
};

现在,我们写下这行代码:

date1 = data2;

变量date2中date,month,year数据都会被赋给date1相关数据元素.因此结构体既可以当成左值,也可以是右值.

10.重要的面试题

是否可以在结构体或联合体中定义一个函数?
答:不可以,在结构体或联合体中定义一个函数,但是可以在结构体或联合体的定义中声明一个函数指针数据成员,该函数指针可以调用一个在结构体或联合体外定义的函数.

宏与枚举

1.重要的面试题

什么是预处理,什么是宏?
答:预处理是C编译器的一个组件,用于处理在实际编译动作发生之q ai的头文件包含或宏处理等任务;
宏是一个记号,用来代表一个常量或者一组固定的程序语句,最后将会被预处理器替换为真实的值或程序语句。

2.重要的面试题

什么是内联操作?
答:预处理器将宏替换为真实的值或程序语句的操作被称为内联操作。

3.程序 计算圆面积,定义宏PI

#include <stdio.h>
#define PI 3.14159   // 用于定义PI的宏
int main(int argc, const char * argv[]) {
    double r = 15.5;
    double area = PI*r*r;
    printf("Area of circle = %.4lf\n",area);
}

4.程序 查找两个数中的最值

#include <stdio.h>
// 用于查找最大值的宏
#define MAX(a,b) (a>b)?a:b
int main(int argc, const char * argv[]) {
    int a,b;
    printf("Enter two numbers: ");
    scanf("%d%d",&a,&b);
    printf("Maximum = %d",MAX(a, b));
}

输出:

Enter two numbers: 18 55
Maximum = 55

4.程序 条件编译

#include <stdio.h>
// 条件编译
#define FIRST
int main(int argc, const char * argv[]) {
    int a,b;
#ifdef FIRST
    a = 1,b = 2;
#else
    a = 10,b = 20;
#endif
    printf("a = %d\tb = %d\n",a,b);
}

输出:

a = 1    b = 2

5.枚举

宏可以表示一个常量,而枚举则可以代表一组常量。

#include <stdio.h>
int main(int argc, const char * argv[]) {
    // 定义枚举,枚举值从0-4
    enum week{
      Sunday,
      Monday,
      Tuesday,
      Wednesday,
      Thursday
    };
    // 创建枚举变量
    enum week day;
    // 循环显示枚举成员
    for (day = Sunday; day<=Thursday; day++) {
        printf("%d ",day);
    }
}

输出:

0 1 2 3 4

6.枚举 为枚举成员赋不同的值

#include <stdio.h>
int main(int argc, const char * argv[]) {
    // 创建枚举并赋值,值分别为0,3,4,5···
    enum week{
      Sunday,
      Monday = 3,
      Tuesday,
      Wednesday,
      Thursday
    };
    // 显示枚举变量
    printf("%d ",Sunday);
    printf("%d ",Monday);
    printf("%d ",Tuesday);
    printf("%d ",Wednesday);
    printf("%d ",Thursday);
}

输出:

0 3 4 5 6 

6.枚举

#include <stdio.h>
int main(int argc, const char * argv[]) {
   // 声明颜色名称枚举
    enum Colors{
        White = 1,
        Black,
        Red,
        Green,
        Blue,
    };
    enum Colors C = Red;
    // 根据c的值显示颜色的十六进制编码
    switch (C) {
        case 1:
            printf("#ffffff");
            break;
        case 2:
            printf("#000000");
            break;
        case 3:
            printf("#ff0000");
            break;
        case 4:
            printf("#ff00ff");
            break;
        case 5:
            printf("#0000ff");
            break;
    }
}

输出;

#ff0000

7.枚举与数组结合

#include <stdio.h>
int main(int argc, const char * argv[]) {
    // 创建月份枚举
    enum montns{
        Jan,Feb,Mar,Apr,May,Jun
    };

    // 创建月名称数组
    char *name[] = {
        "January","February","March","April","May","June"
    };

    // 创建月份日期数组
    int day[] = {
        31,28,31,30.31,30
    };

    // 声明枚举变量
    enum montns m;
    // 显示月份名称与天数
    for (m = Jan; m<Jun; m++) {
        printf("Month = %s\t  Days = %d\n",name[m],day[m]);
    }
}

输出:

Month = January      Days = 31
Month = February      Days = 28
Month = March      Days = 31
Month = April      Days = 30
Month = May      Days = 30

在C语言中,枚举是一种非常原始的类型,并不是非常有用,而在其他语言中,枚举被添加了许多额外的特性,会更加好用。

完结闲聊

至此,C语言的大部分重要基础知识点就归纳完了(细心的读者会发现文件操作和命令行参数知识并不再范围内),后续还会更新C语言与数据结构的相关知识点梳理,会陆续发布,算法是程序的灵魂,也值得花精力去掌握它。

在该系列文章中的代码部分不支持C99,(目前貌似已经C十几了)不过并不妨碍我们进一步的去理解C语言。由于笔者水平有限,在梳理中难免出现有误的地方,还望多多包含,并恳请指正,会在后续中完善这些问题,感谢你的阅读。


 上一篇
你来人间一趟 你要看看太阳 你来人间一趟 你要看看太阳
你来人间一趟,你要看看太阳,和你的心上人,一起走在街上
2019-03-26
下一篇 
你会安然 你会无恙 你会安然 你会无恙
如果,一分钟的旅程,你让60秒充满奇迹和欢欣,那么,海阔天空都是你的,天地万物都是你的 你会安然 你会无恙@来源作者:Celia 如果你总清醒 当周围 众人均已迷糊,咒你骂你 如果你总自信能淡定 当所有人怀疑你 你尚能容他们的怀疑 如果
2019-03-19
  目录