为什么在这种情况下 p+1 不会产生与 p++ 相同的结果?

问题描述 投票:0回答:1

提示:编写以下函数: void get_extension(char *文件名, char *扩展名); file_name 指向包含文件名的字符串。该函数应存储扩展名 字符串中的文件名通过扩展名指向。例如,如果文件名 是memo.txt,该函数会将“txt”存储在扩展名指向的字符串中。如果 文件名没有扩展名,该函数应该存储一个空字符串(单个 扩展名指向的字符串中的空字符。

//Version 1
#include <stdio.h>
#include <stdlib.h>

void get_extension(char *file_name, char* extension);

int main(){
    char file_name[1000], extension[10];
    printf("Enter file name: ");
    scanf("%s", file_name);

    get_extension(file_name, extension);

    printf("%s", extension);

    return 0;
}

void get_extension(char *file_name, char *extension){
    char *p;

    for(p = file_name; *p != '.'; p++);
    for(p++; *p != '\0'; p++, extension++){ //only difference between V1 and V2
        *extension = *p;
    }
    *extension = '\0';
}
//Version 2
#include <stdio.h>
#include <stdlib.h>

void get_extension(char *file_name, char* extension);

int main(){
    char file_name[1000], extension[10];
    printf("Enter file name: ");
    scanf("%s", file_name);

    get_extension(file_name, extension);

    printf("%s", extension);

    return 0;
}

void get_extension(char *file_name, char *extension){
    char *p;

    for(p = file_name; *p != '.'; p++);
    for(p+1; *p != '\0'; p++, extension++){ // only difference between V1 and V2
        *extension = *p;
    }
    *extension = '\0';
}

为什么版本 1 有效而版本 2 无效?我知道它与 p+1 和 p++ 有关。

c for-loop c-strings
1个回答
0
投票

“for”循环(p+1)中的初始化步骤实际上没有执行任何内存位置的增量。它只是评估某个数值。第一个线索可能是编译器警告,例如我在编译程序时收到的警告。

/home/craig/C_Programs/Console/FileExtension/main.c|44|warning: statement with no effect [-Wunused-value]|

我的猜测是,您在编译程序的“版本 2”时也收到了该警告。

考虑到这一点,我构建了程序的混合版本来调用“get_extension”函数的两个版本,以便比较输出数据并希望为您澄清发生了什么。以下是程序的重构版本,可以调用该函数的两个版本。

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

void get_extension(char *file_name, char* extension);
void get_extension2(char *file_name, char* extension);

int main()
{
    char file_name[1000], extension[10];
    printf("Enter file name: ");
    scanf("%s", file_name);

    get_extension(file_name, extension);

    printf("Extension is %s\n", extension);

    get_extension2(file_name, extension);

    printf("Extension is %s\n", extension);

    return 0;
}

void get_extension(char *file_name, char *extension)
{
    char *p;

    for(p = file_name; *p != '.'; p++);             /* Starting at the beginning character array memory location, increment until the "." character is reached              */

    for(p++; *p != '\0'; p++, extension++)          /* The file character array pointer is in effect incremented, and then incremented in synch with the extension pointer  */
    {
        printf("p in first function is.: %p\n", p);
        *extension = *p;
    }
    *extension = '\0';
}

void get_extension2(char *file_name, char *extension)
{
    char *p;

    for(p = file_name; *p != '.'; p++);             /* Starting at the beginning character array memory location, increment until the "." character is reached              */

    for(p+1; *p != '\0'; p++, extension++)          /* A value is calculated but not used and then the two pointers are incremented in synch which then includes "."        */
    {
        printf("p in second function is: %p\n", p);
        *extension = *p;
    }
    *extension = '\0';
}

需要注意的关键点如下:

  • 在该函数的第一个版本中,曾经出现过“.”的位置。找到字符后,第二个“for”循环中的初始化步骤会将内存位置向前增加一个位置,从而有效地越过“.”。字符并将文件名的剩余字符复制到扩展字符数组中。
  • 在该函数的第二个版本中,曾经出现过“.”的位置。字符定位后,第二个“for”循环的初始化步骤只是计算一个实际未使用的值(并且收到了编译器警告),因此“.”字符与剩余的文件名字符一起复制到扩展字符数组中。
  • 为了突出该函数的两个版本之间的对比,添加了列出内存位置的“printf”语句。

以下是程序的执行示例,表明了功能上的差异。

craig@Vera:~/C_Programs/Console/FileExtension/bin/Release$ ./FileExtension 
Enter file name: sample.txt
p in first function is.: 0x7ffeda0b2e57
p in first function is.: 0x7ffeda0b2e58
p in first function is.: 0x7ffeda0b2e59
Extension is txt
p in second function is: 0x7ffeda0b2e56
p in second function is: 0x7ffeda0b2e57
p in second function is: 0x7ffeda0b2e58
p in second function is: 0x7ffeda0b2e59
Extension is .txt

因此,重点是了解内存位置如何以及何时递增、递减和引用,并检查编译器文本中的线索和可能的警告。与往常一样,您可能需要参考一些专注于数组、它们的指针以及指针递增/递减的教程文献。

© www.soinside.com 2019 - 2024. All rights reserved.