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

简介: 1.水仙花数#includeint main() { int i; for ( i = 100; i < 1000; i++) { int i1 = i % 10; int i2 = i / ...

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);
                }

相关文章
字符串转数组、数组转字符串、给第一个单词色值
字符串转数组、数组转字符串、给第一个单词色值
|
8月前
|
JavaScript 前端开发 Java
数组转字符串( 字符串转数组~
数组转字符串可以使用不同的方法,具体取决于编程语言和上下文环境。以下是一些通用的示例:
|
8月前
|
存储 索引
函数与数组
函数(function),数学术语。其定义通常分为传统定义和近代定义,函数的两个定义本质是相同的,只是叙述概念的出发点不同,传统定义是从运动变化的观点出发,而近代定义是从集合、映射的观点出发。
|
8月前
|
JavaScript
js对象、数组转换字符串
js对象、数组转换字符串
93 0
|
9月前
|
JavaScript
常用的数组(字符串)方法有哪些?(一)
1.pop:末位删除,即删除数组的最后一项,返回值是被删除项。 2.shift:首位删除,即删除数组的第一项,返回值是被删除项。 3.splice:指定下标删除元素,返回被删除的元素。第一个参数是从下标几开始删除,第二个参数是删除几个,第三个参数是要插入的元素。splice方法是会改变原数组的。删除功能用的比较多,我个人更喜欢用filter来变相实现删除,splice是会改变原数组的,而filter不会
|
9月前
常用的数组(字符串)方法有哪些?(三)
some:判断数组中有没有符合条件的元素,一个符合的都没有返回false,有一个就是true。
|
9月前
常用的数组(字符串)方法有哪些?(二)
concat:合并数组或者字符串,concat在项目中用的还是比较多的,最经典的就是一个表格数据是有两个或者三个数组组成的时候会用到,watch监听数组和concat结合使用。下期做一个例子。
|
10月前
|
C语言
函数+数组
c语言学习第四弹
|
C语言 索引
从函数返回数组
从函数返回数组
90 0
写一个函数,可以逆序一个字符串的内容
写一个函数,可以逆序一个字符串的内容
80 0