开发者社区> 黑夜路口> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

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

简介: 1.水仙花数 #include int 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);
                }

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
C语言——字符串函数
对字符串函数知识进行分享
44 0
数组 - 字符数组
数组 - 字符数组
24 0
c/c++中与字符串处理相关的函数
void *memccpy (void *dest, const void *src, int c, size_t n); 从src所指向的对象复制n个字符到dest所指向的对象中。如果复制过程中遇到了字符c则停止复制,返回指针指向dest中字符c的下一个位置;否则返回NULL。
1061 0
C中运算符
01,条件表达式, int a = (b>118)?118:a = b; printf("%d\n",a);//指如果b的值是118,则就设置a的值为118,不然就将b的值赋值给a变量; 02,sizeof函数用来计算变量,常量,数据类型所占用内存空间的字节大小; sizeof(10);/...
685 0
c语言中的字符数组与字符串
1、字符数组的定义与初始化 字符数组的初始化,最容易理解的方式就是逐个字符赋给数组中各元素。 char str[10]={ 'I',' ','a','m',' ',‘h’,'a','p','p','y'}; 即把10个字符分别赋给str[0]到str[9]10个元素 如果花括号中提供的字符个数大于数组长度,则按语法错误处理;若小于数组长度,则只将这些字符数组中前面那些元素,其余的元素自动定为空字符(即 '\0' )。
725 0
+关注
黑夜路口
安卓高级工程师,目前任职于Wifi万能钥匙
152
文章
1
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载