尝试声明字符串数组时出现分段错误

时间:2016-08-23 17:08:12

标签: c string cs50

在我的程序中,我试图将每个argv [i]复制到关键字[i],但我的程序因分段错误而失败。我做错了什么?

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

int main(int argc, string argv[])    
{
    //prototype
    string keyword = "";
    //int j;

    for (int i = 0, n = strlen(argv[1]); i < n; i++)
    {
        keyword[i] = toupper(argv[1][i]);
        printf("%i-- printing letters\n", keyword[i]);
    }
}

2 个答案:

答案 0 :(得分:4)

正如其他人所观察到的,您将变量keyword初始化为空字符串或指向空字符串文字的指针,具体取决于类型string的定义。无论哪种方式,只有keyword[i]评估等于零的i才有效;任何其他值 - 用于读或写 - 都超出范围。此外,在后者(指向字符串文字的指针)的情况下,您不能尝试修改数组keyword指向。

特别注意,如果您尝试访问越界元素,C不会自动扩展字符串。相反,尝试这样做会产生“未定义的行为”,并且在这种情况下表现出来的常见方式是以分段错误的形式出现。当系统打下你的程序试图访问不属于它的内存时,你可以查看分段错误。

由于您不知道先验参数字符串复制前的长度,keyword最可行的类型是char *。为清楚起见,我将在后面的内容中使用该类型而不是string

如果您确实想要复制参数,那么到目前为止最简单的方法是通过for-purpose函数strdup()

    char *keyword = strdup(argv[1]);

为其参数的副本分配足够的内存,包括终结符,复制它,并返回指向结果的指针。然后,当您完成后,您必须通过free()函数释放生成的内存。以这种方式制作副本后,您可以将每个元素放在原位:

    for (int i = 0, n = strlen(keyword); i < n; i++)
    {
        keyword[i] = toupper(keyword[i]);
        printf("%c-- printing letters\n", keyword[i]);
    }

顺便提一下,请注意,单个字符的printf()格式描述符为%c,而不是%i。您必须使用它将字符打印为字符,而不是它们的整数值。

这是为您尝试做的事情编写C代码的最简单方法之一,尽管有很多变化。我提供给你考虑的唯一另一个是复制参数:

    char *keyword = argv[1];

如果以这种方式初始化keyword,则不分配任何内存或进行复制;相反,您将keyword设置为指向argv[1]指向的相同字符串。您可以就地修改该字符串(但不能延长它),前提是您不需要保留其原始内容。

在我把它包起来之前,我还应该观察到你的程序没有检查是否确实存在参数。如果没有( ie argc < 2),argv[1]要么包含空指针(argc == 1)要么未定义(argc == 0;你不太可能碰到这个)。无论哪种方式,如果程序尝试使用argv[1],就好像它是指向有效字符串的指针,那么程序会产生未定义的行为。您应首先测试此案例,如果没有可用的程序参数,则使用诊断消息终止。

答案 1 :(得分:-2)

您的主要问题:您没有为新字符串分配内存(string keyword = "")。

在C中,编译时未知的每个大小都必须在运行时动态分配。

此外,您永远不会检查可能导致程序崩溃的缺失参数。

请参阅下面的代码了解这两个修补程序

#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, string argv[])

{
    if (argc != 2)
    {
        printf("Usage: %s <word>\n", argv[0]);
        return 1;
    }
    int length = strlen(argv[1]);
    string keyword = malloc(length+1);

    for(int i = 0, n = strlen(argv[1]); i < n; i++)
    {
        keyword[i] = toupper(argv[1][i]);
        printf("%i-- printing letters\n", keyword[i]);

    }
    keyword[length]=0;
    free(keyword);
}