C语言进阶教程之字符串&内存函数

C语言进阶教程之字符串&内存函数

字符串

字符串的定义

在C语言中,字符串是由一串字符组成的数组。数组中的元素都是字符类型,每一个字符都是占1个字节的ASCII码。字符串以'\0'结尾,'\0'称为空字符(null character),也就是字符串的结束标志。

下面是一个包含字符串的数组的定义:

char str[] = "Hello World!";

这个字符串由12个可见字符和一个隐藏的空字符('\0')组成,所以它的长度为13个字节。

字符串的读取

gets函数

在C语言中,可以通过调用gets()函数从标准输入中读取一个字符串,它的原型如下:

char *gets(char *s);

示例代码如下:

#include <stdio.h>

int main() {
    char str[50];

    printf("Enter a string: ");
    gets(str);

    printf("You entered: %s\n", str);

    return 0;
}

在运行时,会让用户输入一个字符串,然后将输入的字符串赋值给str,最后打印输入的字符串。

fgets函数

gets()函数已经被弃用,因为它存在安全问题,也就是它读取的字符串长度必须小于缓冲区长度,否则会发生缓冲区溢出。为了解决这个问题,C语言还提供了一个更安全的函数fgets()

fgets()函数可以读取指定长度的字符串,因此比gets()函数更安全。它的原型如下:

char *fgets(char *s, int size, FILE *stream);

其中,size表示允许读取的最大字节数,stream表示输入的数据流。如果读取成功,fgets()函数返回所读取的字符串,如果出现错误或者到达文件结尾,返回NULL

示例代码如下:

#include <stdio.h>

int main() {
    char str[50];

    printf("Enter a string: ");
    fgets(str, 50, stdin);

    printf("You entered: %s\n", str);

    return 0;
}

在运行时,它会让用户输入一个长度小于50字节的字符串,并将输入的字符串赋值给str,最后打印输入的字符串。

字符串的拼接

在C语言中,可以通过调用strcat()函数将两个字符串拼接在一起,它的原型如下:

char *strcat(char *dest, const char *src);

其中,dest表示拼接后的目标字符串,src表示需要拼接的源字符串。需要注意的是,dest字符串必须有足够的空间容纳src字符串,否则会发生缓冲区溢出。

示例代码如下:

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

int main() {
    char str1[20] = "Hello ";
    char str2[] = "World!";

    strcat(str1, str2);

    printf("The concatenated string is: %s\n", str1);

    return 0;
}

在运行时,它会将str2拼接到str1的末尾,最后打印拼接完成的字符串。

内存函数

内存函数的定义

在C语言中,有一些内存函数可以用来操作内存中的数据。这些函数通常被用来动态分配内存、释放内存、复制内存等。

内存分配函数

malloc函数

malloc()函数可以动态分配内存空间,它的原型如下:

void *malloc(size_t size);

其中,size表示需要分配的字节数,返回分配到的内存空间的起始地址。如果分配失败,则返回NULL

示例代码如下:

#include <stdio.h>
#include <stdlib.h>

int main() {
   int *ptr;
   int n = 5;

   ptr = (int*)malloc(n * sizeof(int));

   if (ptr == NULL) {
      printf("Memory allocation failed!\n");
      exit(0);
   }

   for (int i = 0; i < n; i++) {
      ptr[i] = i + 1;
   }

   printf("The elements of the array are: ");

   for (int i = 0; i < n; i++) {
      printf("%d ", ptr[i]);
   }

   free(ptr);

   return 0;
}

在运行时,它会分配5个整型变量大小的内存空间,然后将其中的值进行打印,并最后释放内存空间。

calloc函数

calloc()函数与malloc()函数类似,它也可以用来动态分配内存空间,不同之处在于calloc()在分配内存时会将内存空间初始化为0,而malloc()函数不会。它的原型如下:

void *calloc(size_t nmemb, size_t size);

其中,nmemb表示需要分配的元素个数,size表示每个元素的大小,返回分配到的内存空间的起始地址。如果分配失败,则返回NULL

示例代码如下:

#include <stdio.h>
#include <stdlib.h>

int main() {
   int *ptr;
   int n = 5;

   ptr = (int*)calloc(n, sizeof(int));

   if (ptr == NULL) {
      printf("Memory allocation failed!\n");
      exit(0);
   }

   for (int i = 0; i < n; i++) {
      printf("%d ", ptr[i]);
   }

   free(ptr);

   return 0;
}

在运行时,它会初始化5个整型变量大小的内存空间,然后将其中的值进行打印,并最后释放内存空间。

realloc函数

realloc()函数可以用来重新分配内存空间,它的原型如下:

void *realloc(void *ptr, size_t size);

其中,ptr表示需要重新分配内存空间的指针,size表示需要分配的新的内存空间大小。如果分配成功,则返回新的内存空间地址,否则返回NULL。需要注意的是,如果ptrNULL,则等价于调用malloc()函数。

示例代码如下:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *ptr;
    int n1 = 5, n2 = 10;

    ptr = (int*)malloc(n1 * sizeof(int));

    if (ptr == NULL) {
        printf("Memory allocation failed!\n");
        exit(0);
    }

    for (int i = 0; i < n1; i++) {
        ptr[i] = i + 1;
    }

    ptr = realloc(ptr, n2 * sizeof(int));

    if (ptr == NULL) {
        printf("Memory allocation failed!\n");
        exit(0);
    }

    for (int i = n1; i < n2; i++) {
        ptr[i] = i + 1;
    }

    printf("The elements of the array are: ");

    for (int i = 0; i < n2; i++) {
        printf("%d ", ptr[i]);
    }

    free(ptr);

    return 0;
}

在运行时,它会分配5个整型变量大小的内存空间,并将其中的值进行打印。接着,它通过调用realloc()函数重新将内存大小重新分配为10个整型变量大小,然后将其中的值进行打印,并最后释放内存空间。

内存释放函数

free函数

free()函数可以用来释放由malloc()calloc()realloc()函数动态分配的内存空间。它的原型如下:

void free(void *ptr);

其中,ptr表示需要释放的内存空间地址。

示例代码如下:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *ptr;
    int n = 5;

    ptr = (int*)malloc(n * sizeof(int));

    if (ptr == NULL) {
        printf("Memory allocation failed!\n");
        exit(0);
    }

    for (int i = 0; i < n; i++) {
        ptr[i] = i + 1;
    }

    printf("The elements of the array are: ");

    for (int i = 0; i < n; i++) {
        printf("%d ", ptr[i]);
    }

    free(ptr);

    return 0;
}

在运行时,它会分配5个整型变量大小的内存空间,并将其中的值进行打印。接着,它通过调用free()函数释放内存空间。

内存复制函数

memcpy函数

memcpy()函数可以用来复制内存空间中的数据,它的原型如下:

void *memcpy(void *dest, const void *src, size_t n);

其中,dest表示目标内存空间地址,src表示源内存空间地址,n表示需要复制的字节数。

示例代码如下:

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

int main() {
    char src[50] = "Hello World!";
    char dest[50];

    memcpy(dest, src, strlen(src) + 1);

    printf("The copied string is: %s\n", dest);

    return 0;
}

在运行时,它会将源字符串src复制到目标字符串dest中,然后打印复制完成的字符串。

memmove函数

memmove()函数与memcpy()函数类似,也可以用来复制内存空间中的数据,不同之处在于当源内存区域与目标内存区域重叠时,memmove()函数能够保证复制过程正确。它的原型如下:

void *memmove(void *dest, const void *src, size_t n);

其中,dest表示目标内存空间地址,src表示源内存空间地址,n表示需要复制的字节数。

示例代码如下:

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

int main() {
    char str[] = "memmove can work with overlapping areas!";

    memmove (str+20, str+15, 11);

    printf ("Result: %s\n", str);

    return 0;
}

在运行时,它会将源字符串中部分字符复制到目标字符串的后面,然后打印复制完成的字符串。

总结

本文介绍了C语言中的字符串和内存函数。字符串是由一串字符组成的数组,可以通过gets()或者fgets()函数读取字符串,通过strcat()函数拼接字符串。内存函数包括动态分配函数、内存释放函数、内存复制函数,可以通过malloc()calloc()realloc()函数动态分配内存空间,通过free()函数释放内存空间,通过memcpy()memmove()函数复制内存空间中的数据。这些函数在C语言程序中有着广泛的应用,能够提高程序的灵活性和效率。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言进阶教程之字符串&内存函数 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • 赌你会懵的C语言指针进阶数组场景解析

    下面我来详细讲解“赌你会懵的C语言指针进阶数组场景解析”的完整攻略。 概述 在C语言中,数组是非常常用的数据类型。但是对于数组的理解,不仅要理解数组的基本概念,还要深入理解数组和指针的关系。本文将通过两条示例来解析C语言指针进阶数组场景,并教会你如何正确地理解和使用指针和数组。 示例1:指针数组 假设我们有一个学生结构体,并且需要定义一个数组来存储多个学生的…

    other 2023年6月25日
    00
  • Android 检查更新、下载、安装功能的实现

    Android 检查更新、下载、安装功能的实现攻略 在 Android 应用中实现检查更新、下载和安装功能是一个常见的需求。下面是一个完整的攻略,包含了实现这些功能的步骤和两个示例说明。 步骤一:检查更新 首先,你需要在应用中添加一个检查更新的按钮或者在应用启动时自动检查更新。 当用户点击检查更新按钮或者应用启动时,应用会向服务器发送一个请求,检查是否有新版…

    other 2023年9月7日
    00
  • vgg网络

    vgg网络 VGG网络是深度学习领域中经典的卷积神经网络模型之一,由牛津大学的Simonyan和Zisserman在2014年提出。它的全称是Visual Geometry Group网络,旨在解决图像分类和图像识别任务。 架构 VGG网络的架构相对于之前的神经网络更加深层,其中的卷积层使用较小的3×3大小的卷积核,而不是之前常用的11×11或者7×7,这样…

    其他 2023年3月28日
    00
  • 透过Spring源码查看Bean的命名转换规则图文详解

    下面是透过Spring源码查看Bean的命名转换规则的详细攻略。 1. 确定Bean的命名转换规则 Spring中有两种常用的Bean命名转换规则,分别是默认的命名转换规则和自定义的命名转换规则。默认的命名转换规则是将Bean的名称转换成Java中的驼峰命名格式,而自定义的命名转换规则则允许用户通过实现接口来自定义Bean的命名转换规则。我们可以通过查看Sp…

    other 2023年6月27日
    00
  • The application has failed…(应用程序配置不正确)

    “The application has failed to start because the application configuration is incorrect” (“应用程序启动失败,因为应用程序的配置不正确”)是一个常见的错误消息,通常在用户尝试运行 .NET 应用程序时出现。这个问题可以由多种原因引起,包括库版本不兼容、运行时环境错误等等…

    other 2023年6月25日
    00
  • 电脑死机怎么办 电脑死机按什么键恢复

    针对“电脑死机怎么办 电脑死机按什么键恢复”这个问题,以下是完整的攻略。 1. 电脑死机的原因 电脑死机的原因一般分为硬件问题和软件问题: 硬件问题:指电脑内部硬件出现故障或者损坏,如内存条、硬盘、CPU等。 软件问题:指电脑系统或者应用程序出现异常或者错误,如无响应或卡顿等。 2. 处理电脑死机的步骤 在处理电脑死机问题时,一般可以采取以下的步骤: 步骤1…

    other 2023年6月27日
    00
  • html表格宽度固定

    HTML表格宽度固定 HTML表格在网页设计中扮演着非常重要的角色,但是表格太宽或太窄都可能影响到页面的美观和可读性,因此控制表格的宽度是一个必须要考虑的问题。本文将会介绍如何使用HTML和CSS来固定表格的宽度。 HTML 让表格自适应 在HTML中,表格的宽度默认是自适应的,也就是说表格的宽度会根据表格内容的多少自动调整。要指定表格的宽度,可以使用wid…

    其他 2023年3月28日
    00
  • 魔兽世界7.2.5踏风怎么堆属性 wow7.25踏风配装属性优先级攻略

    魔兽世界7.2.5踏风怎么堆属性 wow7.25踏风配装属性优先级攻略 作为一个踏风职业的玩家,在魔兽世界7.2.5版本时,如何堆属性是一个非常重要的问题。本篇攻略将帮助你更好地理解踏风职业的属性堆叠方法和优先级,帮助你更合理地配装。 1. 魔法发挥与速度 作为踏风职业的核心属性,魔法发挥和速度都非常重要。 魔法发挥越高,你的技能输出越强。而速度越高,则可以…

    other 2023年6月27日
    00
合作推广
合作推广
分享本页
返回顶部