【问题标题】:Changing one character in a char* array without converting to char[][]更改 char* 数组中的一个字符而不转换为 char[][]
【发布时间】:2014-06-23 18:26:09
【问题描述】:

我有一个不同长度的字符串字面量的一维数组,如下所示:

char *map[] = {
"ABC",
"ABCDEF",
...
};

我想用map[y][x]='X'; 更改数组中的某个字符,根据Wikipedia,它不(也不应该)工作。我还读到将其声明为char map[][] 将修复该错误。但是,这是一个非常大的数组,因此将其转换为 char map[][] 是不切实际的。还有其他方法可以完成我想要的吗?

【问题讨论】:

  • 如果您不介意浪费一点空间,我会选择@VladfromMoscow 的答案。这是迁移代码的最简单方法。
  • @RSahu,弗拉德的回答有效,但打印数组也会打印出一些垃圾(打印时)。

标签: c arrays segmentation-fault


【解决方案1】:
#include <stdio.h> 

#define CNV(x) (char []){ x }

int main(void){
    char *map[] = {
    CNV("ABC"),
    CNV("ABCDEF"),
    //...
    };
    map[1][2]='c';
    printf("%s\n", map[1]);//ABcDEF
    return 0; 
} 

【讨论】:

  • 这实际上比弗拉德的答案更好,因为它允许我打印它
【解决方案2】:

您不能更改字符串文字。它们在 C/C++ 中是不可变的。

你对数组的定义越正确

const char *map[] = {
"ABC",
"DEF",
...
};

您必须使用能够更改其元素的二维字符数组。

例如

char map[][4] = {
    "ABC",
    "DEF",
    ...
    };

或者您可以使用指针数组通过分配一个新的字符串字面量来更改所需的元素。

【讨论】:

  • 我忘了说字符串的长度不同。
  • @theunamedguy 查看我更新的帖子。请注意,如果所有字符串文字都不同,则将字符串存储在数组中或存储指向字符串文字的指针没有区别。
  • 这就是我要找的。 +1
  • 但是,当我尝试打印它时,它也会打印一些垃圾。
  • @theunamedguy 您没有指定数组最左边的大小。它必须足够大,以容纳每个字符串文字,包括其终止零。请参阅我的帖子中二维数组的定义。您应该将值 4 替换为最大字符串文字的实际大小。
【解决方案3】:

如果您希望能够更改数组中包含的字符串,您将不得不使用动态分配的内存。我会分配一个char* 的数组,然后运行并为每个数组分配内存,然后调用strncpy 或类似的方法。

char** ptrArray = malloc(sizeof(char*)*NUM_STRINGS); 
...
ptrArray[0] = malloc(sizeof(someString)*sizeof(char));
strncpy(ptrArray[0], someString, sizeof(someString)); 

这实际上取决于您的应用程序的上下文。

【讨论】:

  • sizeof(char) 定义为1
  • 这可行,但需要在启动时初始化整个数组。
  • 我总是倾向于把它放在那里。我了解 char 是什么,但我没有意识到它在所有编译器中都是标准的。我从未遇到过sizeof(char) &gt; 1,但以防万一我想我总是包含它。
  • @theunamedguy,这取决于您的应用程序的上下文。如果您需要更多(如果您小心的话,可以减少)字符串,您可以随时realloc。当然,可以随时为每个指针分配内存并复制数据。
  • @sherrellbc: sizeof 基本上以char 为单位进行度量。评估sizeof(char) 就像问“一米有多少米?”
【解决方案4】:

这是一个指向位于只读内存段中的字符串的指针数组:

char* map[] =
{
    "ABC",
    "DEF",
    ...
};

你可以改变每个指针的值,但是你不能改变指向内存的内容。


这是一个指向位于读/写内存段中的字符串的指针数组:

char map[][MAX_STR_LEN+1] =
{
    "ABC",
    "DEF",
    ...
};

你不能改变每个指针的值,但是你可以改变指向的内存的内容。


请注意,在第二种方案中,您基本上有两种选择:

  1. 将数组声明为全局变量,在这种情况下,它将驻留在可执行映像的数据部分并与它一起加载到内存中(即不执行初始化代码)。

  2. 将数组声明为局部变量,在这种情况下,函数将包含一段额外的代码,用于在每次调用时初始化数组(将 RO-data-section 中的所有字符串复制到堆栈中) )。

【讨论】:

    【解决方案5】:
    #include <stdio.h>
    
    char s1[] = "abcd";
    char s2[] = "efghi";
    char s3[] = "jklmnop";
    
    char *s[] = {
      s1, s2, s3
    };
    
    int main(void)
    {
      s[0][0] = '$';
      printf("%s %s %s\n", s[0], s[1], s[2]);
      return 0;
    }
    

    编辑:上面的代码将指向字符串的指针替换为指向(可写)字符数组的指针,从而产生所需的可写行为。

    【讨论】:

      猜你喜欢
      • 2019-08-04
      • 2011-06-08
      • 2013-06-06
      • 2016-03-10
      • 1970-01-01
      • 1970-01-01
      • 2013-11-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多