这个C程序接受行星名称作为参数,并打印它们是否是行星.好的 case 正在奏效

./planets Venus Mercury

但如果加上坏的情况,我会得到Segmentation Fault分.

./planets Venus Mercury mercury

造成这种情况的原因可能是什么?先谢谢你.

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

#define NUM_PLANETS 9

int main(int argc, char* argv[]) {
    char *planets[] = { "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Pluto" };
    int i, j;
    for (i = 1; i < argc; i++) {
        for (j = 0; j < NUM_PLANETS; j++) {
            if (strcmp(argv[i], planets[j]) == 0) {
                printf("%s is planet %d\n", argv[i], j + 1);
                break;
            }
        }
        if (j == NUM_PLANETS) {
            printf("%s is not a planet\n", argv[i]);
        }
    }
}

推荐答案

您声明了一个包含8个元素的数组

char *planets[] = { "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Pluto" };

但在内部for循环的条件下

for (j = 0; j < NUM_PLANETS; j++) {

您正在使用设置为9的宏NUM_PLANETS

#define NUM_PLANETS 9

因此,在for循环内,可能会访问数组外部的内存,从而导致未定义的行为.

使用宏会使您的程序容易出错.

相反,您可以通过以下方式在main内确定数组中元素的实际数量

char *planets[] = { "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Pluto" };
const size_t NUM_PLANETS = sizeof( planets ) / sizeof( *planets );

在这种情况下,即使数组将被扩大,并提供用作初始值设定项的新字符串文字,您的程序也将是正确的,您将不需要更改任何内容.

第二点是,在内部for循环中使用语句break会降低程序的可读性.这只是一种糟糕的编程风格.

并且您应该在使用变量的最小范围内声明变量.

相反,您可以用以下方式编写程序

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

int main(int argc, char* argv[]) 
{
    const char *planets[] = 
    { 
        "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Pluto" 
    };
    const size_t NUM_PLANETS = sizeof( planets ) / sizeof( *planets );

    for ( int i = 1; i < argc; i++ ) 
    {
        size_t j = 0;

        while ( j < NUM_PLANETS && strcmp( argv[i], planets[j] ) != 0 ) ++j;

        if ( j != NUM_PLANETS ) 
        {
            printf( "%s is planet %zu\n", argv[i], j + 1 );
        }
        else
        {
            printf( "%s is not a planet\n", argv[i] );
        }
    }
}

注意数组声明中类型说明符中的限定符const.尽管在C中字符串文字具有非常数字符数组类型(由于历史原因),但是任何更改字符串文字的try 都会导致未定义的行为.因此,最好使用限定符const定义程序中的此类array.此外,在C++中,字符串文字具有常量字符数组类型.因此,您甚至可以使用C++编译器编译您的程序.

C++相关问答推荐

gcc已编译的可执行文件TSB是否同时暗示最低有效字节和最低有效位?

C:gcc返回多个错误定义,但msvc—不""'

ATmega328P USART发送字符重复打印

如何判断宏参数是否为C语言中的整型文字

如何将已分配的数组(运行时已知的大小)放入 struct 中?

将整数的.csv文件解析为C语言中的二维数组

难以理解Makefile隐含规则

在我的代码中,我需要在哪里编写输出函数?

函数内的局部字符指针

`#if`条件中是否允许`sizeof`?

在WSL关闭/重新启动后,是什么原因导致共享对象依赖关系发生更改?

在vfork()之后,链接器如何在不 destruct 父内存的情况下解析execve()?

pthread_create的用法

Fprintf正在写入多个 struct 成员,并且数据过剩

我可以创建适用于不同endian的 colored颜色 struct 吗?

在我的函数中实现va_arg的问题

哪些C++功能可以在外部C块中使用

在同一范围内对具有相同类型的变量执行的相同操作在同一C代码中花费的时间不同

如何修复数组数据与列标题未对齐的问题?

C语言程序流程解释