数据结构与算法从零开始系列:C语言基础

数据结构与算法从零开始系列:C语言基础

前言

马上是就到大四的我,面临校招的我倍感压力,而且今年又是安卓的瓶颈期,外面对能力的要求特别的高,但是我看了很多面经之后,发现很多大公司注重的是数据结构与算法,所以我们不得不有两手准备,开始温习数据结构与算法

当然要学习算法和数据结构,那么C语言是必须先学习的,因为大部分算法和数据结构都是以C语言作为使用语言的,所以这篇文章是针对Android程序员的,由于有了Java的基础,所以有一些语法并没有介绍全面

一、常量与变量

① 常量:C语言常量的声明有两种方式

  1. 使用define关键字
  2. 使用const关键字

它们的区别是:

  1. define是在编译时,会自动将声明的变量替换到程序中
  2. const是在运行是,会自动将声明的变量替换到程序中,同时,const可以很容易知道常量的类型
#include<stdio.h>

#define YOU_AGE 23 
const int HIS_AGE = 25;

int main(){

    return 0;
}

② 变量

C语言基本数据类型有:short、int、long、char、float、double

int a = 10;
char b = 'A';
float c = 25.5;
double d = 25.5;

这里可以提前说(char *)这个类型,这个是字符指针,我们可以把它当作Java的String类型

③ 自定义变量类型名称

使用typedef关键字可以自定义数据类型的名称

typedef int my_int;

int main(){
    //相当于int b = 10
    my_int b = 10;
    return 0;
}

二、流程控制与循环

① if、if-else语句

int a = 10;
int b = 5;
if(a>b){

}else{

}

② switch语句

switch(表达式){ 
    case 常量表达式1:  语句1;
    case 常量表达式2:  语句2;
    … 
    case 常量表达式n:  语句n;
    default:  语句n+1;
}

③ goto语句

goto语句是跳转语句,可以将执行顺序跳转到指定的标签中

//实现1+2+3...+100的和
int i = 1;
loop: if(i<=100){
    sum=sum+i;
    i++;
    goto loop;
}

④ for语句

int i,sum;
for( i=1; i<=100; i++ ){  
    sum=sum+i;
}

⑤ while、do-while语句

  1. while语句是先判断循环条件之后,再决定执不执行循环体
  2. do-while语句是先执行一次循环体,再判断循环条件,决定执不执行循环体
int i=1,sum;
while(i<=100){
    sum=sum+i;
    i++;
}

do{
    sum=sum+i;
    i++;
}while(i<100);

三、运算符

① 算术运算符

<、<=、>、>=、==、!=、赋值运算符(=)

② 逻辑运算符

&&(与)、||(或)、!(非)

③ 位运算符

&(位与)、|(位或)、~(位反)、^(异或)、>>(右移)、<<(左移)

④ 三目运算符

条件表达式 ? 结果1 : 结果2

⑤ sizeof运算符

用来计算变量、常量、数据类型所占用存储空间的字节数

⑥ 自增自减运算符

++a,a++,–a,a–

四、输出和输入

① 输出

//输出字符
char ch = 'a';
putchar(ch);
//输出字符串
puts("hello word");
printf("hello c");

② 格式化输出

通过%+数据格式,进行格式化输出,常见的输出格式

//输出整型
printf("number is %d",23);
//输出十六进制
printf("%X",0xFF00FF);
//输出八进制
printf("%o",8);
//输出浮点型
printf("%f",3.14);
//输出字符
printf("%c",'A');
//输出字符串
printf("%s","Hello C");

③ 输入

//输入字符
char answer = getchar();
printf("%c",answer);

④ 格式化输入

//输入整型
int a;
scanf("%d",&a);
//输入字符
char c;
scanf("%c",&c);
//输入字符串
char buf[100];
scanf("%s",buf);

这里需要注意的是,scanf()函数第二个参数需要一个数据的内存地址,用&符号可以指向一个内存地址,而char[]类型,本身就是个地址,所以不用加&符号

五、数组

① 一维数组

//创建指定大小一维数组
int arr[10];
//创建自动指定大小一维数组
int arr[] = {5,6,8,9};

② 二维数组

int arr[3][4] = {
    {1,2,3,4},
    {5,6,7,8},
    {9,10,11,12}
};

③ 字符数组

char str[10] = {'H','e','l','l','o','/0'};

这里需要注意字符数组凡是遇到有 ‘/0’ 出现就判定该字符数组已经到结尾,默认结尾是会自动补上的

六、函数

① 无返回值的函数

void printfStr(){
    printf("Hello World");
}

② 有返回值的函数

int add(int a,int b){
    return a+b;
}

③ 可变参数函数

int sum(int n,...){
    int i;
    int all = 0;
    va_list args;
    va_start(args,n);
    for(i=0;i<n;i++){
        all+=va_arg(args,int);
    }
    va_end(args);
    return all;
}

完整代码如下

#include<stdio.h>
#include<stdlib.h>
#include<stdarg.h>
//函数需要声明才能调用
int add(int a,int b);
void printfStr();
int sum(int n,...);

int main(){
    int c = add(2,3);
    int d = sum(1,2,3);
    printfStr();
    return 0;
}
//有返回值的函数
int add(int a,int b){
    return a+b;
}
//无返回值的函数
void printfStr(){
    printf("Hello World");
}
//可变参数函数
int sum(int n,...){
    int i;
    int all = 0;
    va_list args;
    va_start(args,n);
    for(i=0;i<n;i++){
        all+=va_arg(args,int);
    }
    va_end(args);
    return all;
}

七、指针

① 变量指针

指针可以理解为Java里面数组,它指向数据存储的内存地址,默认指针是指向数组的第一个数据

int a = 10;
//定义指针,指向a的存储地址
int *pa = &a;
//获取数据的两种方式,输出都是10
printf("%d",*pa);
printf("%d",pa[0]);

② 无类型指针变量

无类型指针可以指向任何类型的变量

void *str = "hello world";
void *a = 5;

printf("%s",str);
printf("%d",a);

③ 函数指针

指针指向的是一个内存地址,不仅是变量内存地址,函数内存地址也可以

#include<stdio.h>
#include<stdlib.h>
void say(int a,int b){
    printf("Hello");
}
int main(){
    void(*method)(int,int) = &say;
    method(0,0);
}

④ 自定义函数名

使用typedef关键字自定义函数名

#include<stdio.h>
#include<stdlib.h>
void say(int a,int b){
    printf("Hello");
}
typedef void(*Func)(int ,int);
int main(){
    Func method = &say;
    method(0,0);
}

八、结构体和共同体

① 结构体

结构体就相当于Java的Bean对象,可以把(struct+结构体名)当作实体对象,进行对象的声明

struct File{
    char *name;
    int size;
};

int main(){
    //第一种赋值方式
    struct File file;
    file.name = "abc.txt";
    file.size = 10;
    //第二种赋值方式
    struct File file = {"abc.txt",10};
}

当然,还可以使用typedef关键字将结构体起个别名,使其更像Java的实体对象

struct _File{
    char *name;
    int size;
};

typedef struct _File File;

int main(){
    File file;
    file.name = "abc.txt";
    file.size = 10;
}

也有另一种简化的写法,效果是一样的,为了使代码更好看

typedef struct _File{
    char *name;
    int size;
}File;

int main(){
    File file;
    file.name = "abc.txt";
    file.size = 10;
}

② 指针结构体

#include<stdio.h>
#include<stdlib.h>
//实体对象
typedef struct{
    char *name;
    int size;
}File;
//创建文件
File * createFile(char *name,int size){
    File *f = malloc(sizeof(File));
    f->name = name;
    f->size = size;
    return f;
}
//删除文件
void deleteFile(File *file){
    free(file);
}

int main(){
    File *f = createFile("abc.txt",10);
    printf("%s,%d",f->name,f->size);
    deleteFile(f);
}

③ 共同体

共同体从字面上可以理解使用共同内存地址的一种结构,即共同体里面的属性所存储的值都是一样的,因为它们的内存地址都指向一个地方(共同体内存地址最大长度 = 所有属性中内存地址长度最大的那个属性)

typedef union _Fmaily{
    char a;
    int b;
}Fmaily;

int main(){
    Fmaily f;
    f.b = 97;
    //输出97的ASCLL值,即a
    printf("%c",f.a);
    //输出97
    printf("%d",f.b);
    return 0;
}

九、文件操作

① 写文件

//打开一个文件,参数一:文件名,参数二:读写模式(w表示写,r表示读)
FILE * f = fopen("abc.txt","w");
if(f != NULL){
    //写进字符
    fputc('A',f);
    //写进字符串
    fputs("Hello",f);
    //关闭文件流
    fclose(f);
}

② 读文件

int i;
//读文件
FILE * f = fopen("abc.txt","r");
if(f != NULL){
    char buf[100];
    //清空buf里面的内容
    memset(buf,0,100);
    for(i=0;i<100;i++){
        //读取字符
        char ch = fgetc(f);
        //如果ch不是End of FIle
        if(ch!=EOF){
            buf[i]=ch;
        }else{
            break;
        }
    }
    printf("%s",buf);
    fclose(f);
}
return 0;

当然还有其他常用的文件API

  1. fgets():读取字符串
  2. fprintf():格式化的写进文件的一句
  3. fscanf():格式化的读取文件的一句

基本的C语言基础就已经复习完了,这些基础知识已经够我们学习数据结构与算法了,更多可以查询API进行学习,这里提供C语言函数速查文档下载

你可能感兴趣的:(数据结构,算法,C语言)