理解strcpy()、sprintf()、strncpy()函数在复制字符串的过程中空字符‘\0‘和换行符‘\n‘的使用


前言

《理解C语言编程中的空字符‘\0‘和换行符‘\n‘》
  上一篇中我们已经了解到编译系统会在字符串的末尾自动添加’\0’结束符作为结束标志,它也是判断一个字符串结束的标志。换行符’\n’是实现数据写入文本实现换行的关键,在数据的末尾添加换行符’\n’后可以实现在写入数据的下一行继续写入。
  本篇文章我们通过使用strcpy()、sprintf()、strncpy()替换字符串继续理解空字符’\0’和换行符’\n’。


一、fgets()函数

  在一个文本文件中那个,我们使用fgets()函数读取文本时,是如何判断读取1行的呢?
  fgets()函数原型如下:

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

  函数规定从一个FILE *stream指向的流文件读取字符串,从str指向的地址开始,依次存储,直到读取到换行符’\n’或者达到指定的字符数(size-1)为止。读取到的字符包括换行符,并在最后自动添加一个字符串结束标志’\0’。


二、fgets()函数使用说明

  首先我有一个demo.txt文件,其中显示有两行,第一行看到"012345678"共计10个字符和一个看不到的’\n’换行符,如下图所示:
在这里插入图片描述
  使用fgets()函数读取demo.txt文件第一行的数据,我们看看第一行字符串的长度,代码如下:

int main() 
{
    
    
    int size =1024;
    //创建一个大一点的空间存储字符串
    char arr[20];
    FILE* rFile = fopen("demo.txt","r");
    if(NULL == rFile)
    {
    
    
        printf("文件打开失败\n");
        return 0;
    }
    fgets(arr, size, rFile);
    printf("读取文件成功\n");
    printf("%s", arr);
    printf("字符串长度:%d\n", strlen(arr));
    fclose(rFile);
    return 0;
}

结果如下所示:
在这里插入图片描述
  结果显示此时打印出的字符串为"012345678",其长度为10,字符串"012345678"长度是9,那么为什么显示的是10呢?
  在上述代码中,打印字符串这一行写的是:

printf("%s", arr);

  我们并没有添加换行符,但是打印出来的时候依然实现了换行,所以读取的字符串实际为"012345678\n",字符串长度为10,‘\n’不显示,只是实现了换行。
  通过上述例子,我们知道使用fgets()函数读取文件,直到读取到换行符’\n’或者达到指定的字符数(size-1)为止。读取到的字符包括换行符,并在最后自动添加一个字符串结束标志’\0’。
  所以fgets()函数有以下几种情况:
  1)读取失败,fgets()函数返回NULL空指针;
  2)读取成功,读取到换行符’\n’结束,此时整体为(可显示的字符串+‘\n’+‘\0’),此时长度为(可显示的字符串+‘\n’)的长度。
  3)读取成功,读取到指定的字符数(size-1)结束,此时整体为(可显示的字符串+‘\0’),此时长度为(可显示的字符串)的长度。


三、strcpy()函数

  我们知道了使用fgets()函数读取一次文本数据所得到的字符串内容,那么在替换字符串中,我们要将一个短的字符串复制到长字符串中来实现替换,我们在看一下使用strcpy()、sprintf()、strncpy()函数复制字符串的不同。
  strcpy()函数原型如下:

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

  从源字符串(src)复制字符,直到遇到结束字符(‘\0’),并将它们依次存储在目标字符串(dest)中。复制完成后,目标字符串将成为一个以’\0’字符结尾的字符串。示例代码如下:

int main() 
{
    
    
    int size =1024;
    //创建一个大一点的空间存储字符串
    char arr[20];
    FILE* rFile = fopen("demo.txt","r");
    if(NULL == rFile)
    {
    
    
        printf("文件打开失败\n");
        return 0;
    }
    fgets(arr, size, rFile);
    printf("读取文件成功\n");
    printf("%s", arr);
    printf("读取的字符串长度:%d\n", strlen(arr));
    strcpy(arr, "demo");
    printf("%s", arr);
    printf("复制完成后字符串长度:%d\n", strlen(arr));
    fclose(rFile);
    return 0;
}

运行结果如下:
在这里插入图片描述
  分析一下代码,首先从demo.txt文件中读取一行文本存储到arr数组中,此时该字符串为:“012345678\n”,字符串长度为10,然后使用strcpy()函数将字符串"demo"复制到arr中,此时arr[0]到arr[3]位置依次存储’d’, ‘e’, ‘m’, ‘o’,arr[4]存储的是’\0’,所以此时arr中存储的字符串长度为4,直接将该字符串写入新文件时,只会将字符串"demo"写进去,同时不会移到下一行。代码如下:

扫描二维码关注公众号,回复: 17274653 查看本文章
int main() 
{
    
    
    int size =1024;
    //创建一个大一点的空间存储字符串
    char arr[20];
    FILE* rFile = fopen("demo.txt","r");
    if(NULL == rFile)
    {
    
    
        printf("文件打开失败\n");
        return 0;
    }
    FILE* wFile = fopen("demoput.txt","w");
    if(NULL == rFile)
    {
    
    
        printf("文件打开失败\n");
        return 0;
    }
    fgets(arr, size, rFile);
    printf("读取文件成功\n");
    printf("%s", arr);
    printf("读取的字符串长度:%d\n", strlen(arr));
    strcpy(arr, "demo");
    printf("%s", arr);
    printf("复制完成后字符串长度:%d\n", strlen(arr));
fputs(arr, wFile);
fclose(rFile);
    fclose(wFile);
    return 0;
}

运行结果如下:
在这里插入图片描述


四、sprintf()函数

  我们将strcpy()函数替换为sprintf()函数试一试。
  sprintf()函数原型如下:

int sprintf(char *str, const char *format, ...);

  该函数主要将多个数量不同变量类型的参数转换为字符串的形式写入到str中,返回值为字符数。
  示例用法如下:

int a;
char c;
sprintf(str, "demo%d%c等等", a, c);

  我们还是从上述代码的基础上读取文本中的数据,由strcpy()函数改为sprintf()函数将字符串"demo"写入到arr中,代码如下:

int main() 
{
    
    
    int size =1024;
    //创建一个大一点的空间存储字符串
    char arr[20];
    FILE* rFile = fopen("demo.txt","r");
    if(NULL == rFile)
    {
    
    
        printf("文件打开失败\n");
        return 0;
    }
    FILE* wFile = fopen("demoput.txt","w");
    if(NULL == rFile)
    {
    
    
        printf("文件打开失败\n");
        return 0;
    }
    fgets(arr, size, rFile);
    printf("读取文件成功\n");
    printf("%s", arr);
    printf("读取的字符串长度:%d\n", strlen(arr));
    sprintf(arr, "demo");
    printf("%s", arr);
printf("复制完成后字符串长度:%d\n", strlen(arr));
fputs(arr, wFile);
    fclose(rFile);
    fclose(wFile);
    return 0;
}

运行结果如下:
在这里插入图片描述
在这里插入图片描述
  可以发现,用sprintf()函数替换strcpy()函数后运行的结果是一样的,这是因为将字符串复制到str时,均是以字符’\0’作为结束,所以复制完成后,从str首地址开始到最近的一个’\0’字符就作为新的一个字符串。当写入新文件后,写入该新的字符串。


五、strncpy()函数

  那么再使用strncpy函数试一试。
  strncpy()函数原型如下:

char *strncpy(char *dest, const char *src, size_t n);

  该函数将源字符串src中的n个长度字符复制到目标字符串中,返回值为目标字符串dest的地址。
  strncpy()与strcpy()和sprintf()函数最大的区别在于,strncpy()、strcpy()、sprintf()函数均是从源字符串复制多个字符到目标字符串,strncpy()函数是以指定长度作为复制字符的个数,strcpy()和sprintf()函数均是从源字符串的起始位置到最近的’\0’字符作为复制字符的个数,所以strcpy()和sprintf()函数在复制时不可避免会在字符串末尾添加’\0’字符。
  使用strncpy()函数可以实现将指定字符复制到目标地址,从而不改变目标地址复制完指定字符的后续字符。代码如下:

int main() 
{
    
    
    int size =1024;
    //创建一个大一点的空间存储字符串
    char arr[20];
    FILE* rFile = fopen("demo.txt","r");
    if(NULL == rFile)
    {
    
    
        printf("文件打开失败\n");
        return 0;
    }
    FILE* wFile = fopen("demoput.txt","w");
    if(NULL == rFile)
    {
    
    
        printf("文件打开失败\n");
        return 0;
    }
    fgets(arr, size, rFile);
    printf("读取文件成功\n");
    printf("%s", arr);
    printf("读取的字符串长度:%d\n", strlen(arr));
    strncpy(arr, "demo", strlen("demo"));
    printf("%s", arr);
    printf("复制完成后字符串长度:%d\n", strlen(arr));
    fputs(arr, wFile);
    fclose(rFile);
    fclose(wFile);
    return 0;
}

运行结果如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  可以看到,最初demo.txt文件中的目标字符串为"012345678\n",读取该字符串复制到arr数组中,使用strncpy()函数将字符串"demo"复制到arr,然后写入到demoputt.txt文件中,只是改变了arr原有的前4个字符,对于后面字符保持原样没有改变。


总结

  通过strcpy()、sprintf()、strncpy()的使用,我们对于字符串有了更加清晰的认知,空字符’\0’是字符串结束的标志,strcpy()向目标字符串成功复制字符串时,说明是遇到了源字符串的结尾’\0’,只有找到’\0’计算机才会认为字符串结束了,否则,计算机就会去找内存中最近的一个字符串从而引起错误。

猜你喜欢

转载自blog.csdn.net/zjrwinner/article/details/132189899