C语言基础(七)

1、二维数组:

C语言中的数组是一种基本的数据结构,用于在计算机内存中连续存储相同类型的数据。
数组中的每个元素可以通过索引(或下标)来访问,索引通常是从0开始的。数组的大小在声明时确定,并且之后不能改变(除非使用动态内存分配技术,如指针和malloc/free等)。如果初始化时省略数组的大小,编译器会自动根据初始化列表中元素的数量确定数组的大小。

数组索引越界是C语言中常见的错误。如果尝试访问数组边界之外的元素,程序会崩溃或产生不可预测的行为。
数组的大小在编译时确定,且固定不变。如果需要动态改变数组大小,应考虑使用指针和动态内存分配。
数组名在表达式中通常被当作指向数组首元素的指针。但是,数组名本身并不是一个指针变量,而是一个常量表达式,其值为数组首元素的地址。


测试代码1:

#include <stdio.h>  
int main() {  
    // 定义一个6x3的二维数组并初始化  
    int arr[6][3] = {  
        {1, 2, 3},  
        {4, 5, 6},  
        {7, 8, 9},  
        {10, 11, 12},  
        {13, 14, 15},  
        {16, 17, 18}  
    };  
  
    // 遍历二维数组  
    for (int i = 0; i < 6; i++) { // 外层循环遍历行(i从0到5)
        for (int j = 0; j < 3; j++) { // 内层循环遍历列(j从0到2)
            // 打印当前元素的值及其下标  
            printf("arr[%d][%d] = %d\n", i, j, arr[i][j]);  
        }  
    }  
    return 0;  
}

运行结果如下:

 

测试代码2:

#include <stdio.h>  
#include <stdlib.h>  
#include <time.h>  
// 函数声明  
void fillRandomArray(int arr[][8], int rows, int cols);  
int searchArray(int arr[][8], int rows, int cols, int target);  
  
int main() {  
    int arr[3][8]; // 定义一个3x8的二维数组  
    int target; // 需要查找的目标值  
    int result; // 查找结果  
  
    // 初始化随机数生成器  
    srand(time(NULL));  
  
    // 填充随机数到二维数组中  
    fillRandomArray(arr, 3, 8);  
  
    // 显示数组内容  
    printf("数组内容:\n");  
    for (int i = 0; i < 3; i++) {  
        for (int j = 0; j < 8; j++) {  
            printf("%d ", arr[i][j]);  
        }  
        printf("\n");  
    }  
  
    // 获取查找的目标值  
    printf("请输入要查找的目标值: ");  
    scanf("%d", &target);  
  
    // 在数组中查找目标值  
    result = searchArray(arr, 3, 8, target);  
  
    // 输出查找结果  
    if (result != -1) {  
        printf("找到目标值 %d 在位置 [%d][%d].\n", target, result / 8, result % 8);  
    } else {  
        printf("未找到目标值 %d.\n", target);  
    }  
  
    return 0;  
}  
  
// 填充随机数到二维数组中  
void fillRandomArray(int arr[][8], int rows, int cols) {  
    for (int i = 0; i < rows; i++) {  
        for (int j = 0; j < cols; j++) {  
            arr[i][j] = rand() % 100; // 随机数的范围是0到99  
        }  
    }  
}  
  
// 在二维数组中查找指定的数据  
int searchArray(int arr[][8], int rows, int cols, int target) {  
    for (int i = 0; i < rows; i++) {  
        for (int j = 0; j < cols; j++) {  
            if (arr[i][j] == target) {  
                return i * cols + j; // 返回元素的线性索引,可以根据需要调整为返回行列索引  
            }  
        }  
    }  
    return -1; // 如果没有找到,返回-1  
}

运行结果如下:

 

测试代码3:

#include <stdio.h>  
#include <stdlib.h>  
#define MAX_PER_LINE 10   
int main() {  
    int n, i, j, countEven = 0;  
    printf("请输入整数的数量: ");  
    scanf("%d", &n);  
  
    // 使用malloc分别为原始整数数组和偶数数组动态分配内存  
    int *nums = (int *)malloc(n * sizeof(int));  
    int *evenNums = NULL;  
  
    // 读取整数  
    printf("请输入 %d 个整数:\n", n);  
    for (i = 0; i < n; i++) {  
        scanf("%d", &nums[i]);  
    }  
  
    // 计算偶数数量并分配偶数数组内存  
    for (i = 0; i < n; i++) {  
        if (nums[i] % 2 == 0) {  
            countEven++;  
        }  
    }  
    evenNums = (int *)malloc(countEven * sizeof(int));  
  
    // 分离偶数,遍历原始数组,将偶数存入另一个数组。 
    j = 0;  
    for (i = 0; i < n; i++) {  
        if (nums[i] % 2 == 0) {  
            evenNums[j++] = nums[i];  
        }  
    }  
    // 输出原始数组  
    printf("原始数组:\n");  
    for (i = 0; i < n; i++) {  
        printf("%d ", nums[i]);  
        if ((i + 1) % MAX_PER_LINE == 0) {  
            printf("\n");  
        }  
    }  
  
    // 输出偶数数组  
    printf("\n偶数数组:\n");  
    for (i = 0; i < countEven; i++) {  
        printf("%d ", evenNums[i]);  
        if ((i + 1) % MAX_PER_LINE == 0) {  
            printf("\n");  
        }  
    }  
    // free释放动态分配的内存。
    free(nums);  
    free(evenNums);  
    return 0;  
}

运行结果如下:

 

.......................................................................................................................................................... 

2、 字符数组:

测试代码:

#include <stdio.h>  
#include <string.h>  
int main() {  
    // 静态定义并初始化字符数组  
    // 编译器会自动为字符串字面量添加\0。 
    // 字符串在C语言中是通过字符数组实现的,但字符数组并不等同于字符串。
	// 字符数组可以包含任何字符,包括\0,而字符串是以\0结尾的字符序列。
    char str1[] = "Hello, Static Initialization!";  //自动添加'\0'  
    printf("Static Initialization: %s\n", str1);  

    char str2[13] = {'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '\0'}; // 显式添加'\0'
    printf("%s\n", str2);  
    // 动态定义后逐个初始化字符数组(包括显式添加'\0')  
    char str3[50];  
    int i;  
    for(i = 0; i < 26; i++) {  
        str3[i] = 'A' + i; // 使用ASCII码初始化大写字母A到Z  
    }  
    str3[i] = '\0'; // 显式添加字符串结束符  
    printf("Manual Initialization: %s\n", str3);  
  
    // 使用strcpy函数初始化字符数组  
    char str4[10];  
    strcpy(str3, "Hello, strcpy Initialization!"); 
    printf("strcpy Initialization: %s\n", str4);  
    return 0;  
}

运行结果如下:

 

测试代码2:

#include <stdio.h>  
#include <string.h> 
int main() {  
    int n = 5; // 有5个字符串要处理  
    char strs[n][100]; // 字符串数组,每个字符串最多99个字符加上一个'\0'  
    // 输入循环  
    printf("请输入%d个字符串(每个字符串后按Enter键):\n", n);  
    for (int i = 0; i < n; i++) {  
        fgets(strs[i], sizeof(strs[i]), stdin);  
       
		// strcspn(strs[i], "\n")函数用于找到strs[i]中第一个换行符(\n)的位置(如果不存在,则返回strs[i]的长度)。
		// 然后将该位置上的字符替换为字符串终止符'\0',以移除可能由fgets()读取并存储的换行符。
		// fgets读取换行符,fgets()会将换行符(如果它存在且缓冲区足够大)也读取到字符串中。 
        strs[i][strcspn(strs[i], "\n")] = 0;  
    }   
    // 输出循环  
    printf("你输入的字符串是:\n");  
    for (int i = 0; i < n; i++) {  
        printf("%s\n", strs[i]);  
    }  
    return 0;  
}

运行结果如下:

 

........................................................................................................................................................... 

3、 字符串处理函数:

处理字符串主要依赖于标准库 string.h,常用的字符串处理函数及其功能:

strlen(const char str)
功能:计算字符串 str 的长度(不包括结尾的空字符 '\0')。
返回值:返回字符串的长度。

strcpy(char dest, const char src)
功能:将字符串 src(包括终止的空字符)复制到字符串 dest 所指向的数组中。
返回值:返回 dest 的指针。
使用时要确保 dest 指向的数组有足够的空间来存放 src 字符串。

strncpy(char dest, const char src, size_t n)
功能:将字符串 src 的前 n 个字符复制到 dest 指向的数组中。如果 src 的长度小于 n,则在 dest 的剩余部分填充空字符。
返回值:返回 dest 的指针。
与 strcpy 不同,strncpy 不会自动添加终止的空字符,除非 src 的长度小于 n。

strcat(char dest, const char src)
功能:将字符串 src 连接到 dest 字符串的末尾,并包括 src 的终止空字符。
返回值:返回 dest 的指针。
使用时要确保 dest 指向的数组有足够的空间来存放结果字符串。

strncat(char dest, const char src, size_t n)
功能:将字符串 src 的前 n 个字符(不包括终止的空字符)连接到 dest 字符串的末尾。如果 src 的长度小于 n,则只连接 src 的内容,并且不会自动添加终止的空字符。
返回值:返回 dest 的指针。
strncat 不会添加终止的空字符,除非有足够的空间并且 src 的长度小于 n。

strcmp(const char str1, const char str2)
功能:比较字符串 str1 和 str2。
返回值:如果 str1 和 str2 字符串相等,则返回 0;如果 str1 在字典序上小于 str2,则返回负数;如果 str1 在字典序上大于 str2,则返回正数。

strncmp(const char str1, const char str2, size_t n)
功能:比较字符串 str1 和 str2 的前 n 个字符。
返回值:与 strcmp 相同,但只比较前 n 个字符。

strchr(const char str, int c)
功能:在字符串 str 中查找第一次出现的字符 c。
返回值:返回指向第一次出现的字符 c 的指针;如果未找到,则返回 NULL。

strrchr(const char str, int c)
功能:在字符串 str 中查找最后一次出现的字符 c。
返回值:与 strchr 类似,但查找方向相反。

strstr(const char str1, const char str2)
功能:在字符串 str1 中查找第一次出现的子串 str2。
返回值:如果找到,则返回指向 str1 中子串 str2 的第一个字符的指针;如果未找到,则返回 NULL。
 

测试代码1:

#include <stdio.h>  
#include <string.h>  
  
int main() {  
    char str1[] = "Hello, World!";  
    char str2[] = "World";  
    char dest[50];  
    char *found;  
  
    // strlen  
    printf("Length of '%s' is %zu\n", str1, strlen(str1));  
  
    // strcpy  
    strcpy(dest, str1);  
    printf("Copied string: '%s'\n", dest);  
  
    // strcat  
    strcat(dest, " Again!");  
    printf("Appended string: '%s'\n", dest);  
  
    // strcmp  
    if (strcmp(str1, "Hello, World!") == 0) {  
        printf("'%s' is equal to 'Hello, World!'\n", str1);  
    }  
  
    // strncmp  
    if (strncmp(str1, "Hello", 5) == 0) {  
        printf("'%s' starts with 'Hello'\n", str1);  
    }  
  
    // strchr  
    found = strchr(str1, ',');  
    if (found) {  
        printf("Found ',' at position: %ld\n", (long)(found - str1 + 1));  
    }  
  
    // strrchr  
    found = strrchr(str1, 'o');  
    if (found) {  
        printf("Last 'o' found at position: %ld\n", (long)(found - str1 + 1));  
    }  
  
    // strstr  
    found = strstr(str1, str2);  
    if (found) {  
        printf("'%s' found in '%s'\n", str2, str1);  
    }  
  
    // strncpy (不会添加空字符,除非有足够的空间)  
    char buffer[6];  
    strncpy(buffer, str1, 5);  
    buffer[5] = '\0'; // 手动添加空字符  
    printf("Copied first 5 characters: '%s'\n", buffer);  
  
    // strncat (假设dest有足够的空间)  
    char dest2[50] = "Start: ";  
    strncat(dest2, str1, 5); // 追加前5个字符  
    printf("Appended first 5 characters: '%s'\n", dest2);  
  
    return 0;  
}

运行结果如下:

 

测试代码2:

#include <stdio.h>  
#include <string.h>  
#include <stdbool.h> // 使用bool
int countWords(const char *str) {  
    int count = 0;  
	//使用bool类型跟踪当前是否在处理一个单词。
    bool inWord = false; // 标记当前是否在单词中。  
  
    // 遍历字符串中的每个字符  
    for (int i = 0; str[i] != '\0'; i++) {  
        // 如果当前字符不是空格且之前不在单词中,则开始一个新单词  
        if (str[i] != ' ' && !inWord) {  
            inWord = true;  
            count++;  
        }  
        // 如果当前字符是空格且之前在单词中,则结束当前单词 
        // 假设单词之间仅由空格分隔,并且不考虑标点符号作为单词的一部分。
		// 如果需要更复杂的处理(例如,将标点符号视为单词的一部分或忽略某些特定的分隔符),需要调整逻辑以满足需求。		
        else if (str[i] == ' ' && inWord) {  
            inWord = false;  
        }  
        // 省略其他情况的实现,如:连续空格或字符串末尾  
    }  
    // 如果字符串以单词结束,则最后一个单词的计数会在循环中被增加  
    // 无需在循环外再次增加  
    return count;  
}  
int main() {  
    char text[1000]; // 输入的文本不超过999个字符  
  
    printf("请输入一段文字(不超过999个字符):");  
    fgets(text, sizeof(text), stdin); // 使用fgets,以避免溢出  
  
    // 去除fgets读取的换行符  
    size_t len = strlen(text);  
    if (len > 0 && text[len - 1] == '\n') {  
        text[len - 1] = '\0';  
    }  
    int wordCount = countWords(text);  
    printf("单词数量为:%d\n", wordCount);  
    return 0;  
}

运行结果如下:

 

 

 

 

 

 

 

 

 

  • 11
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值