美文网首页
04.C(数组字符串和函数)

04.C(数组字符串和函数)

作者: 任振铭 | 来源:发表于2018-03-30 11:24 被阅读41次

    1.水仙花数

    #include<stdio.h>
    int main() {
        int i;
        for ( i = 100; i < 1000; i++)
        {
            int i1 = i % 10;
            int i2 = i / 10 % 10;
            int i3 = i / 100;
            if ((i1*i1*i1 + i2*i2*i2 + i3*i3*i3) == i)
                printf("%d\n",i);
        
        }
        return 0;
    }
    
    

    2.二维数组

    #include<stdio.h>
    
    int main()  
        int arrary[2][3];
        printf("%d\n", sizeof(arrary));  //6个元素,6个int元素,每个int 4个字节,所以答案是24
        return 0;
    }
    
    

    3.二维数组赋值

    
    #include<stdio.h>
    
    int main() {
        int arrary[2][3];
        printf("%d\n", sizeof(arrary));
        arrary[0][0] = 0;//给第0行第0列的元素赋值
        arrary[0][1] = 0;//给第0行第1列的元素赋值
        return 0;
    }
    
    #include<stdio.h>
    
    int main() {
        int arrary[2][3] = { {1,2,3},{2,3,4} };//创建的同时赋值
        return 0;
    }
    
    #include<stdio.h>
    
    int main() {
        int arrary[2][3]=0;//将数组中每一个元素都赋值为0
        return 0;
    }
    
    

    4.输出二维数组的值

    #include<stdio.h>
    
    int main() {
        int arrary[2][3] = { {1,2,3},{4,5,6} };
        int i;
        int j;
        for ( i = 0; i < 3; i++)
        {
            for ( j = 0; j < 4; j++)
            {
                printf("array[%d][%d] = %d\n",i,j,arrary[i][j]);
            }
        }
        return 0;
    }
    

    这里存在数组越界的情况,但是c 与 Java不同,不会崩溃,只是越界位置输出的值毫无章法可言

    输出结果

    array[0][0] = 1
    array[0][1] = 2
    array[0][2] = 3
    array[0][3] = 4
    array[1][0] = 4
    array[1][1] = 5
    array[1][2] = 6
    array[1][3] = -858993460
    array[2][0] = -858993460
    array[2][1] = 4193644
    array[2][2] = 15343566
    array[2][3] = 1

    5.冒泡排序

    #include<stdio.h>
    
    int main() {
        int array[10]{34,32,67,18,23,90,56,82,39};
        int i;
        int j;
    
        for ( i = 0; i < 9; i++)                  //控制数据个数
        {
            for ( j = 0; j < 9 - i-1; j++)        //控制每次比较的次数,-1是为了防止最后一个数组越界
            {
                if (array[j] > array[j+1])        //前一个数字和后一个数字比较大小
                {
                    int temp = array[j];
                    array[j] = array[j + 1];
                    array[j+1] = temp;
                }
            }
    
        }
    
        for ( i = 0; i < 9; i++)
        {
            printf("%d\n", array[i]);
        }
        return 0;
    }
    

    简单解释冒泡排序的含义:一组数字,从第一个开始一次跟后便的数字比较大小,大的放后边,小的放前边,
    第一次比较第一个和第二个比较,如果第一个大于第二个,交换两者位置,否则不变,直到比较到最后一个数字,此时,最大的值已经排在了最后边
    第二次比较,第一个和第二个比较,重复第一步的操作,此时结果第二大的数字排在了右数第二个位置
    。。。
    直到最后一次比较

    6.int arr [2][3][4][5]..支持多维数组,但是不建议使用,理解难度大。

    7.字符数组和字符串

    #include<stdio.h>
    
    int main() {
        char array[1000] = {'a','b','c','d'};
        printf("%s\n",array);
        return 0;
    }
    

    结果:abcd

    
    #include<stdio.h>
    
    int main() {
        char array[] = "abcd";
        printf("%s\n",array);
        printf("%d\n",sizeof(array));
        return 0;
    }
    

    结果:
    abcd
    5 //字符串默认以0结尾,所以末尾还有个零,sizeof 为5
    请按任意键继续. . .

    #include<stdio.h>
    
    int main() {
        char array[100] = "abcd";
        printf("%s\n",array);
        printf("%d\n",sizeof(array));
        return 0;
    }
    
    

    结果:
    abcd
    100 //字符数组为abcd 大小为100
    请按任意键继续. . .

    C语言中数组长度这样表示sizeof(arrary)

    8.c语言编译器不会检查数组脚标是否越界

    9.c语言中字符串是一个在内存中以0结尾的字符数组,必须以0结尾,否则不是字符串

    比如下边这个不是字符串

    #include<stdio.h>
    int main() {
        char s[5] = { 0 };
        s[0] = 'a';
        s[1] = 'b';
        s[2] = 'c';
        s[3] = 'd';
        s[4] = 'e';
        return 0;
    }
    

    下边这个是字符串,因为char数组最后一个值默认为0

    
    #include<stdio.h>
    int main() {
        char s[5] = { 0 };
        s[0] = 'a';
        s[1] = 'b';
        s[2] = 'c';
        s[3] = 'd';
        printf("%s\n",s);
        return 0;
    }
    
    

    打印结果为abcd ,注意后边是有0的,c语言不同于Java的一个地方,如果打印Java中一个数组的话,得到的是地址值,而C语言直接就把字符串打印出来了

    10.英文倒叙打印

    #include<stdio.h>
    int main() 
    {
        char buf[100] = "hello world";
        int len = 0;
        while (buf[len++]) {};
        len--;
        int min = 0;
        int max = len - 1;
        while (min < max)
        {
            int temp = buf[min];
            buf[min] = buf[max];
            buf[max] = temp;
            min++;
            max--;
        }
        printf("%s\n",buf);
        return 0;
    }
    
    
    

    11.中文倒叙打印
    汉字倒叙打印不同于英文,跟存储方式有关,直接使用以上方式会出现乱码现象
    一个汉子为两个字节,一个英文字母为一个字节,正确交换的方式是第一个字节和倒数第二个字节交换
    第二个字节和最后一个字节交换,这样就达到了将第一个汉字和最后一个汉字交换,以此类推。
    这是windows系统下,如果是linux系统下汉字使用的是utf8的编码,每个汉字占三个字节

    #include<stdio.h>
    int main() 
    {
        char buf[100] = "你好世界";
        int len = 0;
        while (buf[len++]) {};
        len--;    //char默认以0字符结尾,这样做是去掉了0的长度
        int min = 0;
        int max = len - 1;
        while (min < max)
        {
            char temp = buf[min];
            buf[min] = buf[max-1];
            buf[max-1] = temp;
    
            temp = buf[min + 1];
            buf[min + 1] = buf[max];
            buf[max] = temp;
    
            min += 2;
            max -= 2;
        }
        printf("%s\n",buf);
        return 0;
    }
    
    

    12.中英混合打印
    a.求中英混合长度(一个汉字占一个)

    #include<stdio.h>
        int main()
        {
            char buf[100] = "你好世界abc";
            int len = 0;
            int i = 0;
            while (buf[i]) 
            {
                if (buf[i] < 0)  //如果是汉字的话,满足小于0的条件,英文大于0,如果0表示是汉字,所以向前跳一个位置
                    i++;        
                i++;
                len++;
            }
            printf("%d\n",len);
            return 0;
        }
    
    
    #include<stdio.h>
    int main() 
    {
        char s[100] = "hello world";
        s[4] = 0;
        printf("%s\n",s);
        return 0;
    }
    
    

    输出结果hell char默认以0结尾,将数组中的第四个设置为0相当于在那个位置结尾了,后边就没了

    14.去除字符串尾部的空格

    #include<stdio.h>
    int main() 
    {
        char s[100] = "hello world  ";
        int len = 0;
        while (s[len++]);                  //这里的分号必不可少,不然有问题,可以运行试试
            len--;
        for (int i = len - 1; i >= 0; i--) //从后往前找,当找到一个不是空格的字符时,将其后的一个位置设置为0,就相当于在此作为尾部
        {
            if (s[i] != ' ')
            {
                s[i + 1] = 0;
                break;
            }
        }
        printf("(%s)\n",s);            //(%s)表示将打印的用括号括起来
        return 0;
    }
    

    15.去除字符串头部的空格
    a.

    #include<stdio.h>
    int main() 
    {
        char s[100] = "    hello";
        int len = 0;
        while (s[len++] == ' ');
            len--;            //得到空格的数量
        printf("%d\n", len);
        int i = len;            //从第一个不是空格的位置开始,将这个位置的字符移动到第一个位置
        while (s[i])
        {
            s[i-len]=s[i];
            i++;
        }
        printf("(%s)\n",s);
        return 0;
    }
    

    结果为(helloello)  //由于将字符串整体前移后,还需要将后边遗留的字符去掉,所以如下程序
    b.

    #include<stdio.h>
    int main() 
    {
        char s[100] = "    hello";
        int len = 0;
        while (s[len++] == ' ');
            len--;
        printf("%d\n", len);
        int i = len;
        while (s[i])
        {
            s[i-len]=s[i];
            i++;
        }
        s[i - len] = 0;         //将最后一位设置为尾部,置0去除多余字符
        printf("(%s)\n",s);
        return 0;
    }
    
    

    16.随机数产生函数 rand 和 srand,可以对比java中的random函数学习 需要引入stdlib.h

    #include<stdio.h>    //没有引用stdlib.h但是也没有出错,?
    int main() 
    {
        int i = 0;
        for ( i = 0; i < 10; i++)
        {
            int value = rand();
            printf("%d\n",value);
        }
        return 0;
    }
    

    产生了随机数,但是每次得到的随机数都是相同的,所以rand称为伪随机数生成器,要生成每次不同的怎么做呢?

    使用srand函数,设置种子值

    #include<stdio.h>
    #include<stdlib.h>    //经测试在vs中即使不引用这两个头文件,同样可以运行
    #include<time.h>
    int main() 
    {
        time_t tm = time(NULL);  //得到系统时间
        srand(tm);          //种子发生器,只要每次修改srand函数的参数,就可一达到每次产生不同随机数的效果
        int i = 0;
        for ( i = 0; i < 10; i++)
        {
            int value = rand();
            printf("%d\n",value);
        }
        return 0;
    }
    
    

    17。字符串的输入操作

    #define  _CRT_SECURE_NO_WARNINGS
    
    #include<stdio.h>
    int main() 
    {
        char s[100] = {0};  //将数组大小设置为2048,就可以防止键盘输入溢出了
        scanf("%s",s);      //输入一个字符串,以回车键作为输入完成的标识,但是回车键本身不会作为字符串的一部分
        printf("%s\n",s);    //scanf存在安全问题,加入用户在键盘输入的内
                            //容超过scanf参数中的数组长度,就会内存溢出,发生奔溃
                            //这也就是微软在使用scanf函数时需要加上顶部#define  _CRT_SECURE_NO_WARNINGS的原因
        return 0;
    }
    

    18.字符串的结束标识
    scanf将回车空格都当作字符串结束的标志
    继续使用以上的程序,运行输入
    abc ddd
    输出结果是:abc
    请按任意键继续. . .
    可见空格后的ddd没有了

    19.gets函数(用这个可以实现输出带空格的字符串,但是gets也存在缓冲区溢出的问题)gets参数只能接受一个数组

    #include<stdio.h>
    int main() 
    {
        char s[100] = {0};
        //scanf("%s",s);    
        gets(s);
        int i = 0;
        for ( i = 0; i < 10; i++)
        {
            printf("%d\n",s[i]);
        }
                        
        return 0;
    }
    
    

    运行输入hello world
    输出
    hello world
    104
    101
    108
    108
    111
    32
    119
    111
    114
    108
    请按任意键继续. . .
    可见,gets函数解决了scanf的问题,gets函数是以回车为尾部标识的

    20.gets实现整数加法

    #include<stdio.h>
    #include<stdlib.h>
    int main() 
    {
        char a[100] = { 0 };
        char b[100] = {0};
        gets(a);
        gets(b);
        int i1 = atoi(a);
        int i2 = atoi(b);
        printf("%d\n",i1+i2);
        return 0;
    }
    
    

    由于gets无法接收整数作为参数,只能接收数组,所以使用atoi函数将字符串转化为一个整数 后实现加法
    gets不能用类似“%d”或者“%s”之类的字符串转义

    21.fgets函数

    #include<stdio.h>
    int main() 
    {
        char a[10] = { 0 };
        fgets(a,10,stdin); 
        //fgets(a, sizeof(a), stdin);        //第一个参数是char的数组,第二个参数是数组的大小,单位:字节,第三个参数stdin
        printf("%s\n",a);                    //代表标准输入,fget是安全的,不存在缓冲区溢出的问题,只要能保证第二个参数小                                    //于(不能等于(也不是绝对的,最好小于),char以0结尾)数组实际的大小
        return 0;
    }
    

    22.puts函数

    #include<stdio.h>
    int main() 
    {
        char a[10] = { 0 };
        fgets(a,10,stdin); 
        puts(a);                              //只能打印字符串,并且会在输出完成后再后边打印一个'\n'(换行)
        return 0;
    }
    
    

    输出结果

    hello //输入后回车,可以看到换了两行
    hello

    请按任意键继续. . .

    23.字符串操作函数(需要包含头文件 #include<string.h>)

    a.获取有效长度

    #include<stdio.h>
    #include<string.h>
    int main() 
    {
        char a[100] = "hello world";
        int len = strlen(a);    //得到字符串长度,返回一个字符串中有效字符的数量(不包含字符串结尾的0),sizeof是获取到数组的大小,概念是不同的
        printf("%d\n", len);
        return 0;
    }
    

    b.字符串的追加

    #define _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    #include<string.h>
    int main() 
    {
        char a[100] = "hello world";
        char a2[100] = "abcd";
        strcat(a, a2);                //将两个字符串合并,结果放在第一个参数里边,存在缓冲区溢出的问题(当第一个数组不够大                            //到足以装的下两个数组中的东西的时候,所以需要第一个数组容量足够大)
        printf("%s\n", a);
        return 0;
    }
    

    安全追加

    #define _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    #include<string.h>
    int main() 
    {
        char a[100] = "hello world";
        char a2[100] = "abcd";
        strncat(a, a2,3);                //合并的时候可以限制追加多少个字符,可以防止溢出
        printf("%s\n", a);
        return 0;
    }
    

    c.字符串的比较

    #include<stdio.h>
    #include<string.h>
    int main() 
    {
        char a[100] = "abcd";
        char a2[100] = "abcd";
        //if (a == a2);                错误的模型,字符串不能通过==比较
        if (strcmp(a, a2) == 0)    //这个函数比较的是ASCII码,如果第一个参数的码值小于第二个
                                    //返回值为-1,反之则返回值为1
        {
            printf("相同\n");
        }
        else
        {
            printf("不相同\n");
        }
        return 0;
    }
    
    

    只比较指定数量的字符

    #include<stdio.h>
    #include<string.h>
    int main() 
    {
        char a[100] = "abcd";
        char a2[100] = "abcdef";
        //if (a == a2);                错误的模型,字符串不能通过==比较
        if (strncmp(a, a2,5) == 0)  //只比较前5个字符
        {
            printf("相同\n");
        }
        else
        {
            printf("不相同\n");
        }
        return 0;
    }
    

    d.字符串的拷贝

    #define _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    #include<string.h>
    int main() 
    {
        char a[100] = "abcd";
        char a2[100] = "abcdef";
        strcpy(a, a2);                //将a2的内容拷贝到a中,注意缓冲区溢出的问题
        printf("%s\n", a);
        return 0;
    }
    

    拷贝指定数量的字符

    #define _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    #include<string.h>
    int main() 
    {
        char a[100] = "kkjedftk";
        char a2[100] = "abcdef";
        strncpy(a, a2,3);                //将a2的内容拷贝到a中,注意缓冲区溢出的问题
        printf("%s\n", a);
        return 0;
    }
    

    结果:
    abcedftk
    请按任意键继续. . .

    e.sprintf函数,格式化字符串

    #define _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    #include<string.h>
    int main() 
    {
        char a[100] = {0};
        int i = 200;
        sprintf(a,"i = %d",i);    //将格式化后的字符串输出到第一个参数中去
        printf("%s\n", a);
        return 0;
    }
    
    

    f.字符串和整数的转换
    整数转字符串 atoi函数
    字符串转整数 (itoa函数不是标准的C语言库函数),可以使用sprintf就可以转换了

    g.sscanf函数

    #define _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    #include<string.h>
    int main() 
    {
        char a[100] = "56+98=";
        int c = 0;
        int b = 0;
        sscanf(a, "%d+%d", &c, &b);                    //从一个字符串中接收内容,对比scanf函数学习
        printf("%d\n", c+b);
        return 0;
    }
    
    

    h.strchr 查找字符

    #define _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    #include<string.h>
    int main() 
    {
        char a[100] = "56+98=";
        int c = 0;
        int b = 0;
        strcpy(a, "hello world");                //当一个字符数组已经初始化后,重新给他复制不能直接使用=
                                                //,而应该使用这种方式
        
        const char *buf = strchr(a, 'o');        //在都吐个参数a中查找指定字符,找到后返回从这个字符开始的知道结尾的字符
                                                //找不到返回null
    
        printf("%s\n",buf);
        return 0;
    }
    
    

    输出结果

    o world
    请按任意键继续. . .

    i.strstr函数,原理同上,只不过查找的内容换成了字符串

    
    #define _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    #include<string.h>
    int main() 
    {
        char a[100] = "56+98=";
        int c = 0;
        int b = 0;
        strcpy(a, "hello world");
        const char *buf = strchr(a, 'o');
        buf = strstr(a, "wor");
        printf("%s\n",buf);
        return 0;
    }
    

    j.strtok字符串分割函数

    #define _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    #include<string.h>
    int main() 
    {
        char a[100] = "abc_12345_efg";
        const char *buf = strtok(a, "_");
        printf("%s\n", buf);
        buf = strtok(NULL, "_");              //没调用一次回得到第一个符合要求的字符串,从第二个开始参数要穿NULL
        printf("%s\n", buf);
        buf = strtok(NULL, "_");
        printf("%s\n", buf);
        return 0;
    }
    
    

    以循环的方式分割得到所有

    #define _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    #include<string.h>
    int main() 
    {
        char a[100] = "abc_12345_efg";
        const char *buf = strtok(a, "_");
        while (buf)        1                    //如果找不到buf,会返回null,如果以此为循环结束条件
        {
            printf("%s\n", buf);
            buf = strtok(NULL, "_");
        }
        return 0;
    }
    
    

    k.字符串转换为其他类型(stdlib.h)
    a. atoi -> int
    b. atof -> float
    c.atol -> long

    24.C语言自定义函数标准使用方式

    第一种方式

    #define _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    #include<string.h>
    
    int getMax(int a, int b)                //自定义函数在main函数的上方定义,也就是在使用之前就定义
    {                                        //在vs中,将自定义函数放在main函数的后边也是可以,但是会有警告  
                                            // warning C4013: “getMax”未定义;假设外部返回 int
        int c = a > b ? a : b;
        return c;
    }
    
    int main() 
    {
        int a = 10;
        int b = 20;
        int d = getMax(a, b);
        printf("%d\n", d);
        return 0;
    }
    
    

    第二种方式

    #define _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    #include<string.h>
    
    int getMax(int a,int b);                //先声明自定义函数,然后在后边定义函数结构,不会有警告,
    
    int main() 
    {
        int a = 10;
        int b = 20;
        int d = getMax(a, b);
        printf("%d\n", d);
        return 0;
    }
    
    int getMax(int a, int b)
    {
        int c = a > b ? a : b;
        return c;
    }
    
    

    如果C语言一个函数没有明确的返回类型,那么默认是int

    在C语言中实参与形参的数据传递是“值传递”,即单向传递,只有实参传递给形参,不能有形参传递给实参,如果参数是数组,那么是可以通过形参传递给实参的,和java中的基本数据类型传递和引用数据类型传递相同

    24.size_t的类型(表示unsigned int 是一种无符号整数,不是c语言的关键字,很多函数,如果确认不会返回负数,都可以用size_t类型接收)

    #include<stdio.h>
    #include<string.h>
    
    _ main() 
    {
        char s[100] = "hello world";
        size_t len = strlen(s);
        printf("%d\n", len);
        return;
    }
    

    25.将一个正数或者一个负数在不借助于C语言库函数的条件下转换为字符串

    
    #include<stdio.h>
    #include<string.h>
    
    void int2String(int n,char s[])
    {
        int status = 0;  //0 = 正数,1 = 负数
        if (n<0)  
        {
            status = 1;
            n = 0 - n;            //如果是负数,先把他转化为正数
        }
        else
        {
            status = 0;
        }
        int i = 0;
        while (n)
        {
            int a = n % 10;
            char c = a + '0';
            s[i] = c;
            i++;
            n /= 10;
        }
        int min = 0;
        int max = i - 1;
        while (min < max)
        {
            char temp = s[min];
            s[min] = s[max];
            s[max] = temp;
            min++;
            max--;
        }
    
        if (status == 1) 
        {
            for (int a = i-1; a >=0; a--)
            {
                s[a + 1] = s[a];
            }
            s[0] = '-';
        }
        printf("%s\n", s);
    }
    
    int main() 
    {
        char sa[100] = { 0 };
        int2String(1234567890, sa);
    }
    
    

    26.#include 与#define的意义

    #include就是简单的文件内容替换,使用这个引入头文件,在预编译阶段会将头文件中的内容替换到这个文件中
    #define就是简单的文本替换,假设你定义了一个常量代表一个数字,那么在预编译的阶段,会直接将这个常量表示的值替换到文件中

    27.#ifndef与#ebdif

    #ifndef的意思就是条件预编译如果#ifndef后面的条件成立,那么就预编译从ifndef开始到#endif之间的代码,否则不会去预编译这段代码 ,在一个头文件中都是这样的格式:是为了防止头文件被重复引用,如果不加这三行,那么如果重复引用了就会在预编译的时候引入好几次,造成不必要

    #ifndef RZM (宏的名字,由自己定义,保持唯一性,不与别的宏重复)
    #define RZM (这两句就是如果没有定义这个宏,那么就在本行定义一下)

    。。。

    #endif

    28.多文件编译

    第一种方式:创建一个a.c,里面定义一个方法

        #include<stdio.h>
    
                    int print(int num) {
                        printf("%d\n", num);
                    }
    
                在主函数中调用这个方法
    
                    #include<stdio.h>
    
                    int print(int num);  //将函数进行声明然后使用
    
                    int main() 
                    {
                        print(10);
                    }
    

    第二种方式:通过头文件的方式调用函数(推荐这种方式)

                同样创建一个a.c,里面定义一个方法
    
    
                    #include<stdio.h>
    
                    int print(int num) {
                        printf("%d\n", num);
                    }
    
                    创建一个b.h头文件
    
                    #ifndef __RZM__
                    #define __RZM__
    
                    int print(int num);    //在头文件中进行函数的声明
    
                    #endif
    
                    在主函数中调用这个方法,只需要引入这个头文集即可
    
                    #include<stdio.h>
    
                    #include "b.h"            //引入这个头文集
    
                    int main() 
                    {
                        print(10);
                    }
    
    

    相关文章

      网友评论

          本文标题:04.C(数组字符串和函数)

          本文链接:https://www.haomeiwen.com/subject/qknbcftx.html