Linux和C语言(Day07)

一、学习内容

  1. 字符数组和字符串

    1. 字符数组

      1. 用于存储多个字符的数组。

        1. char a[5]={'h','q','y','j'};

    2. 字符串

      1. 用""引起来0个或多个字符。使用指针或者数组存储。计算机会自动添加结束标志'\0'。

        1. char *s="hqyj";

        2. char s[]="hqyj";

        3. 空串:0个字符。 ""

        4. 空格串:只存储空格的串。 " "

        5. 子串:从主串中分离出的1个或多个连续的字符。

    3. 关于字符数组和字符串的初始化

      1. 全部初始化
        1. char a[5]={'h','q','y','j','6'};

        2. char a[5]={"hqyj"};

        3. char a[5]="hqyj";

        4. char a[5]="hqyj6"; //错误的

      2. 部分初始化
        1. char a[5]={'h','q'};

        2. char a[5]="hq";

      3. 特殊初始化
        1. 殊初始化

        2. char a[]={'h','q','y','j','6','6','6'}; //字节为 7

        3. char a[]="hqyj666"; //字节为 8

      4. 错误初始化
        1. char a[5];

        2. a={'h','q','y','j'}; 错误

        3. a="hqyj"; 错误

    4. 关于字符数组和字符串的输出

      1. 字符数组的输出
        1. char a[5]={'h','q','y','j','6'}; //存储多个单字符 for(i=0; i<5; i++){ printf("%c",a[i]); putchar(a[i]); } //不常用

      2. 字符串的输出
        1. char a[]="hqyj666"; //存储 1个字符串 printf("%s" , a); puts(a);

        2. 特殊情况

          1. char a[5]={'h','q','y','j','\0'}; 该数组可以 printf("%s" , a);

          2. char a[5]={'h','q','y','j', 0}; 该数组可以 printf("%s" , a);

          3. char a[5]={'h','q','y','j','0'}; 该数组不可以 不可以 不可以 printf("%s" , a);

      3. 字符串的输入
        1. char a[20];//可以存储多个单字符 也可以存储 1 个字符串

        2. scanf("%s" , a); //%s输入时,不加 &

        3. gets(a); //gets可以输入空格 scanf()不可以输入空格

  2. 字符串处理函数 #include <string.h>

    • strlen函数

      • 功能:求一个字符串的长度

      • 原型:size_t strlen(const char *s);

      • 分析:size_t 是返回值【64位返回值是long int %ld 32位系统返回值是int %d】 const char *s是参数 const表示不可变 char *s 传字符串首地址【字符串名/数组名】

      • 使用:char a[]="hqyj66"; strlen(a);

    • strcat函数

      • 功能:将一个字符串连接/追加到另一个字符串的后面

      • 原型:char *strcat(char *dest, const char *src);

      • 分析:char *返回值 【字符串首地址】 第一个参数char *dest目标字符串,追加到TA后面【定义要尽量大】 第二个参数const char *src源字符串

      • 使用:strcat("hyqj" , "666"); 结果是"hqyj666"

    • strcmp函数

      • 功能:strcmp 函数逐个比较两个字符串 str1 和 str2 中的字符,直到遇到不同字符或到达字符串的结尾。比较时是按照字符的 ASCII 码值进行的。

      • 原型:int strcmp(const char *s1, const char *s2);

      • 分析:返回值 int 【>0 <0 ==0】 参数1:const char *s1 字符串1 参数2:const char *s2 字符串2

      • 使用:strcmp(s1,s2)>0 说明s1>s2 strcmp(s1,s2)<0 说明s1<s2 strcmp(s1,s2)==0 说明s1==s2

    • strcpy函数

      • 功能:拷贝/复制/赋值

      • 原型:char *strcpy(char *dest, const char *src);

      • 使用:strcpy(s , "hqyj"); strcpy(name , "孙文雅"); strcpy(s , name);

  3. 二维字符数组

    • char a[5][100]; 表示存储5个字符串 其中5表示 5行 5个字符串 100表示 100列 1个字符串的最大长度

    • 初始化

      • char a[3][5]={'a','b','c','d','e',\ '1','2','3','4','5',\ 'a','b','c','d','e'}; 【一般不用】 char a[3][5]={"hqyj","1234","hqyj"};

    • 按字符串输出

      • for(i=0; i<3; i++){ printf("%s " , a[i]); }

  4. 脑图

二、作业

        1.下列对 C 语言字符数组的描述中错误的是 ( ) (鲁科安全)

A. 字符数组可以存放字符串

B. 字符数组中的字符串可以整体输入、输出

C. 不可以用关系运算符对字符数组中的字符串进行比较

D. 可以在赋值语句中通过赋值运算符 "=" 对字符数组整体赋值

 解析:

A: 正确。字符数组可以存放字符串。

B: 正确。字符数组中的字符串可以整体输入、输出(例如 scanf("%s", array)printf("%s", array))。

C: 正确。不能用关系运算符 ==> 等直接比较字符数组中的字符串。字符串比较应使用函数如 strcmp()

D: 在 C 语言中,字符数组不能直接通过 = 运算符整体赋值。你需要逐个字符进行赋值或者使用函数,如 strcpy() 来实现字符串的拷贝.

解答:
D

        2.下列描述中不正确的是( )(华三外协)

A.字符型数组中可以存放字符串

B.可以对字符型数组进行整体输入、输出

C.可以对整型数组进行整体输入、输出

D.不能在赋值语句中通过赋值运算符"="对字符型数组进行整体赋值

解析:

A: 正确。字符型数组(char array[])可以存放字符串,字符串实际上是以 \0 结尾的字符数组。

B: 正确。字符型数组可以整体输入输出,使用 scanf("%s", array)printf("%s", array) 进行处理。

C: 不正确。整型数组(int array[])不能像字符数组一样使用 scanfprintf 一次性输入输出整个数组。整型数组的输入和输出需要逐个元素处理,或者通过循环。

D: 正确。不能通过 = 运算符直接对字符型数组进行整体赋值,需要使用字符串操作函数,如 strcpy()

解答:

 C

3.下列代码片段执行的结果是: (云尖软件开发)

char szTest[] = "ABCDEF";

strncpy(szTest, szTest, 4);

printf("%s", szTest);
A.ABCD         B. ABCDE   C. ABCDEF        D. 以上都不对

解析:

初始字符串 szTest"ABCDEF",它包含 6 个字符,再加上字符串结束符 \0,因此整个数组的内容是 {'A', 'B', 'C', 'D', 'E', 'F', '\0'}

strncpy(szTest, szTest, 4):因为源和目标是相同的地址,strncpy 会从 szTest 的开始复制 4 个字符到同样的位置,但这是一个没有效果的操作,因为它本质上是将数组的一部分内容覆盖到相同的地方。换句话说,szTest 的内容不会发生任何变化。

输出:printf("%s", szTest) 将会输出原始的字符串 "ABCDEF",因为没有任何修改。

解答:

A

4.以下对字符数组test 赋值方式错误的是( )。 (智洋)

A. char test[10]; strcpy(test, "test");

B. char test[10]; test="test";

C. char test[]={'t', 'e', 's', 't’};

D. char test[10]={'t', 'e', 's', ‘t’};

解析:

A: 正确。strcpy(test, "test"); 正确地将字符串 "test" 复制到字符数组 test 中。

B: 错误。test = "test"; 是非法的,因为数组名不能用 = 运算符赋值。

C: 正确。字符数组的初始化可以通过列表的方式赋值,如 {'t', 'e', 's', 't'},尽管这样没有自动添加 \0 结束符。

D: 正确。字符数组可以显式初始化部分或全部元素,{'t', 'e', 's', 't'} 是有效的方式,数组的剩余部分将被初始化为 0(包括 \0)。

解答:

B

5.以下语句不能正确赋值的是( ) (杭州快越科技, 神州安付)

A. char *s = "China";

B. char s3[20] = "China";

C. char s2[]={'C', 'h', 'i', 'n', 'a'};

D. char s1[10]; s1="China";

解析:

A: 正确。char *s = "China"; 创建了一个指针 s,指向常量字符串 "China",这是合法的。

B: 正确。char s3[20] = "China"; 将字符串 "China" 赋值给字符数组 s3,并且数组大小足够,这也是合法的。

C: 正确。char s2[] = {'C', 'h', 'i', 'n', 'a'}; 将字符逐个赋值给数组 s2,这也是合法的,尽管没有自动添加字符串结束符 \0

D:在 C 语言中,字符数组 s1 的名称是一个常量指针,指向数组的第一个元素。你不能使用赋值运算符 = 给数组名赋值。即数组名不能改变指向,因此 s1 = "China"; 是非法的。

解答: 

D

6.以下程序运行后输出结果是( ) (杭州快越科技)

main()

{

    char ch[2][5] = {"693", "825"}, p[2][5];

    int i, j, s = 0;

    for(i=0;i<2;i++) p[i]=ch[i];

   

    for(i=0;i<2;i++)

    for(j=0;p[i][j]>='0' && p[i][j]<='9';j+=2)

s=10*s+p[i][j]-'0';  

    printf("%d\n", s);

}

A.6385   B. 33        C. 693825        D. 22

解析:

这个双重循环用于处理每个字符,并每次加到 s 中。j0 开始,每次递增 2。因此,p[i][0]p[i][2] 这些字符会被处理。对于 p[0],即 "693"p[0][0]'6'p[0][2]'3'。所以 s 将会是 63,计算为 63。对于 p[1],即 "825"p[1][0]'8'p[1][2]'5'。所以 s 将会是 6385,计算为 6385

解答:

 A

7.为了比较两个字符串s1和s2是否相等,应当使用( ) (杭州快越科技)

A. if(s1 = s2)                                         B. if(s1==s2)

C. if(strcmp(&s1, &s2)==0)              D. if(strcmp(s1, s2)==0)

解析:

A. 这是一个赋值语句,不是比较操作。s1 = s2 会将 s2 的地址赋给 s1,这会导致编译错误,因为 s1 是一个数组名,不能被赋值。

B. 这是一个地址比较操作。s1s2 是字符数组名,它们表示数组的首地址。s1 == s2 比较的是这两个数组的地址,而不是它们的内容。因此,这不会正确比较两个字符串的内容。

C. 这是错误的用法。strcmp 函数的参数应该是两个字符串,而不是字符串的地址。因此,&s1&s2 是错误的参数类型,会导致编译错误或不正确的结果。

D. 这是正确的用法。strcmp 函数用于比较两个字符串的内容。如果两个字符串相等,strcmp 返回 0。因此,这种写法是正确的。

解答:

 D

8.编写一个程序。输入一个字符串,将其逆序后输出?(电工时代)

代码解答:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
	char a[100]={0};
	scanf("%s",a);
	int len=strlen(a);
	int i,j;
	printf("%d\n",len);
	j=len;
	for(i=0;i<len;i++){
		char temp=0;
		temp=a[i];
		a[i]=a[len-1];
		a[len-1]=temp;
		len--;
	}
	printf("%s",a);
	return 0;
}

结果展示:

 

9.编写一个程序。负责将一个字符串拷贝到另一个字符串,不调用 C++/C 的字符串库函数。(电工时代,泰华智慧,智洋,中安云科,北京拓普空间科技,登虹科技,杭州快越科技,鲁科安全)

代码解答:

#include <stdio.h>

int main() {
    char a[100];
    char b[100];
    
	printf("请输入原有的字符串a:\n");
	scanf("%s",a);
    // 输入字符串 b
    printf("请输入要复制的字符串 b:\n");
    scanf("%s", b);
	printf("输入的字符串a为:%s   需要复制的字符串b为:%s\n",a,b);
    
    // 将字符串 b 完全拷贝到 a
    int i = 0;
    while (b[i] != '\0') {
        a[i] = b[i];  // 将 b 中的字符复制到 a
        i++;
    }
    
    // 添加字符串结束符
    a[i] = '\0';
    
    // 输出拷贝后的字符串 a
    printf("字符串 a 复制后的内容是: %s\n", a);
    
    return 0;
}

结果展示:

 

10.编写一个程序。不使用字符串连接函数strcat,实现两个字符串的链接 (若临视讯,福建新大陆) 

代码解答:

#include <stdio.h>

int main() {
    char a[100];
    char b[100];
    
    // 输入字符串 a 和 b
    printf("请输入第一段字符:\n");
    scanf("%s", a);
    printf("请输入第二段字符:\n");
    scanf("%s", b);
    
    // 复制字符串 b 到 a 的末尾
    int i = 0, j = 0;
    
    // 找到字符串 a 的末尾
    while (a[i] != '\0') {
        i++;
    }
    
    // 将字符串 b 拷贝到 a 的末尾
    while (b[j] != '\0') {
        a[i] = b[j];
        i++;
        j++;
    }
    
    // 添加字符串结束符
    a[i] = '\0';
    
    // 输出结果
    printf("结果字符串是: %s\n", a);
    
    return 0;
}

结果展示:        

11.编写一个程序。请实现输入一个字符串,这个字符串字符串包含一个或多个数字,把这些数字字符转换为整数,如果字符串参数包含了非数字字符,置零,不必担心算数溢出。(泰华智慧,紫光云数,H3C,拓仓科技)

输入:123abc456

输出:printf(“%d\n” , num);  num=123000456

代码解答:

#include <stdio.h>

int main() {
    char input[100];
    int result = 0;
    int i = 0;
    
    // 输入字符串
    printf("请输入一个包含数字的字符串:\n");
    scanf("%s", input);
    
    // 遍历字符串,检查是否包含非数字字符
    while (input[i] != '\0') {
        if (input[i] < '0' || input[i] > '9') {
            input[i] = '0';  // 包含非数字字符,置为0
        }
        result = result * 10 + (input[i] - '0');  // 将字符转换为数字并累加
        i++;
    }
    
    // 输出结果
    printf("转换后的整数是: %d\n", result);
    
    return 0;
}

结果展示:

12.编写一个程序。实现输入N个字符串,输出这N个字符串中的最大字符串和最长字符串,可以调用字符串处理函数。

代码解答:

#include <stdio.h>
#include <string.h>

#define MAX_STRINGS 100
#define MAX_LENGTH 100

int main() {
    int N;
    printf("请输入字符串的数量 N: ");
    scanf("%d", &N);

    char strings[MAX_STRINGS][MAX_LENGTH];  // 用来存储输入的字符串
    char max_string[MAX_LENGTH];            // 用来存储最大字符串
    char longest_string[MAX_LENGTH];        // 用来存储最长字符串

    int max_length = 0;                     // 记录最长字符串的长度

    // 输入 N 个字符串
    printf("请输入 %d 个字符串:\n", N);
    for (int i = 0; i < N; i++) {
        scanf("%s", strings[i]);
    }

    // 初始化最大字符串和最长字符串为第一个字符串
    strcpy(max_string, strings[0]);
    strcpy(longest_string, strings[0]);
    max_length = strlen(strings[0]);

    // 遍历比较所有字符串
    for (int i = 1; i < N; i++) {
        // 比较最大字符串
        if (strcmp(strings[i], max_string) > 0) {
            strcpy(max_string, strings[i]);
        }

        // 比较最长字符串
        if (strlen(strings[i]) > max_length) {
            strcpy(longest_string, strings[i]);
            max_length = strlen(strings[i]);
        }
    }

    // 输出结果
    printf("最大字符串是: %s\n", max_string);
    printf("最长字符串是: %s\n", longest_string);

    return 0;
}

结果展示:

三、总结

 1. 学习内容概述:

字符数组与字符串

学习了如何使用字符数组存储字符串,以及字符串的初始化、长度计算、拼接、比较等操作。

二维字符数组

掌握了如何定义和操作二维字符数组,这部分重点在于理解每一行都是一个字符串,如何遍历和输出二维字符数组中的内容。

字符串处理函数

学习了`<string.h>`头文件中的常用字符串处理函数,包括`strlen`、`strcat`、`strcmp`、`strcpy`等,了解了每个函数的作用、参数和返回值。

2. 学习难点

字符串数组与二维字符数组的区别

字符数组存储的是单个字符串,而二维字符数组可以存储多个字符串。区分这两者的初始化方式和访问方式是学习中的难点。

字符串的自动初始化与手动初始化

通过`char str[] = "hello"`和`char str[] = {'h', 'e', 'l', 'l', 'o', '\0'}`的不同初始化方式理解字符串在内存中的存储结构,注意字符串必须以`'\0'`结尾。

`strcat`的拼接操作

在进行字符串拼接时,理解目的字符串必须有足够的空间来存放拼接后的内容,否则会引发内存溢出问题。

`strcmp`函数的返回值

理解该函数比较字符串时返回的三种结果:`0`表示相等,正值表示字符串1大于字符串2,负值表示字符串1小于字符串2。这对于字符串的排序和查找功能至关重要。

`strcpy`的内存操作

该函数直接将源字符串复制到目标位置,学习时需要注意目标数组要有足够的空间,否则可能会发生溢出。

3. 注意事项

二维字符数组的遍历

在操作二维字符数组时,需要通过双层循环来访问每个字符串的每一个字符,要小心避免越界。

字符串操作函数的安全性

使用`strcat`、`strcpy`等函数时,需要确保目标数组有足够的空间。可以考虑使用`strncat`、`strncpy`等带有长度限制的函数,来避免内存安全问题。

字符串输入

在使用`scanf`读取字符串时,必须注意到它默认会忽略空格,可以使用`gets`函数来读取含有空格的字符串,但`gets`有安全隐患,因此建议使用更安全的`fgets`函数。

 4. 未来学习的重点

字符串的动态内存管理

接下来可以学习如何动态分配内存存储字符串,比如使用`malloc`来创建字符串缓冲区,以及如何正确释放内存以避免内存泄漏问题。

更复杂的字符串操作

深入学习更复杂的字符串处理函数,如`strtok`进行字符串的分割,`strchr`和`strrchr`用于查找字符的位置等。

字符编码与本地化处理

理解C语言中不同字符编码(如ASCII和Unicode),以及如何处理多字节字符,这对于处理不同语言的文本至关重要。

  • 25
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux中,`cal`是一个内建的命令行工具,用于显示日历。虽然它的核心是用C语言实现的,但作为系统的一部分,直接查看源码并不常见,因为这些通常由操作系统内核维护,且不公开。然而,如果你想了解如何编写一个简单的C语言日历程序,我可以给你提供一个基础的示例。 这是一个简单的C程序,使用了`ncurses`库(一个用于终端界面的库)来模拟一个基本的日历: ```c #include <stdio.h> #include <ncurses.h> #define MONTHS 12 #define DAY_OF_WEEK 7 void draw_month(int year, int month) { initscr(); // 初始化ncurses环境 cbreak(); // 使输入非阻塞 noecho(); // 隐藏用户输入 curs_set(0); // 关闭光标 int days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int current_day = 1; int row = 1; for (int i = 0; i < DAY_OF_WEEK; ++i) { mvprintw(row++, 0, "%2d ", i + 1); } int days_left = DAY_OF_WEEK - 1; for (int day = 1; day <= days_in_month[month-1]; ++day) { if (current_day == 1 && month == 2 && is_leap_year(year)) { days_in_month[month-1]++; } if (days_left > 0) { mvprintw(row++, 0, "%2d ", current_day++); --days_left; } else { for (int j = 0; j < DAY_OF_WEEK - 1; ++j) { mvprintw(row++, 1 + j * 3, " "); } mvprintw(row++, 1, "%2d ", current_day++); days_left = DAY_OF_WEEK - 1; } } getch(); // 等待用户按键 endwin(); } bool is_leap_year(int year) { return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); } int main() { int year, month; printf("Enter year and month: "); scanf("%d %d", &year, &month); draw_month(year, month); return 0; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值