【问题标题】:What is the difference between a 2D string of the type string[10][20] compared to a 2D string of the type *string [10][20] in C?string[10][20] 类型的 2D 字符串与 C 中 *string [10][20] 类型的 2D 字符串有什么区别?
【发布时间】:2020-07-28 14:39:14
【问题描述】:

我是 C 初学者,我在 Windows 上使用 CodeBlocks。

我了解到字符串是一个字符序列(字符),但我需要一个字符串序列。

在一个视频中,我看到如果我在字符串中使用指针(它是 char string[20][10],现在是 char* string[20][10]),我可以将字符串的每个“空格”打印为字符串而不是 @987654324 @。 (我的意思是空格,例如,string[0][0])。但是后来我尝试在该字符串的两个空格中使用strcpy(),但程序没有工作。谁能告诉我为什么会发生这种情况以及指针在这种字符串中发生了什么变化?

编辑:这是无效的代码:

#include <stdio.h>
#include <string.h>
int main()
{
    int i, j;
    char* array[3][10];
    for(i = 0; i != 3; i++)
    {
        for(j = 0; j != 10; j++)
        {
            if(i == 0)
            {
                array[i][j] = "ABC";
            }
            else if(i == 1)
            {
                array[i][j] = "DEF";
            }
            else if(i == 2)
            {
                array[i][j] = "GHI";
            }    
        }
    }
    for(i = 0; i != 3; i++)
    {
        for(j = 0; j != 10; j++)
        {
            printf("%s", array[i][j]);
        }
        printf("\n");
    }
    strcpy(array[2][0], array[1][0]);
    return 0;
}

(这不是实际代码,我有一个问题在这里很难解释。但是如果您在阅读此代码后仍然觉得这个问题令人困惑,我将尝试解释原始问题)。

【问题讨论】:

  • 你能提供一个minimal reproducible example吗?
  • 请提供“无效”的代码。
  • char* string[20][10]char * 的二维数组,在这种情况下,string[0][0] 将保存char * 类型的值。如果这样的值用作strcpy 的第二个参数,则它需要指向空终止字符串的第一个元素。如果它被用作strcpy 的第一个参数,它需要指向一个足够大的缓冲区来保存第二个参数指向的空终止字符串。如果两者都不是,这将解释为什么它“不起作用”。
  • @IanAbbott 我在 strcpy 的两个参数中都使用了 char* 类型的两个值。究竟什么是空终止字符串?
  • @KazzioBots 以空结尾的字符串是char 的数组(或像char 的数组一样组织的内存块),其中一个零值的char 元素标记了细绳。空终止字符串的“长度”(strlen 返回的是空终止符之前的chars 的数量。当使用strcpy 将空终止的源字符串复制到目标缓冲区时,目标缓冲区需要大到足以容纳整个字符串直到并包括空终止符(至少1+strlen(srcstring)chars 长)。

标签: c string windows codeblocks string.h


【解决方案1】:

我将间接回答您的问题,因为我认为从根本上您需要了解的是数组和指针之间的区别。

C 可能会使初学者感到困惑,因为它对指针和数组使用相同的语法。在一个数组中,它为其所有元素定义空间,a[n] 检索元素n。如果a 是一个指针,它只为指针定义空间,a[n] 指的是从a 指向的任何位置开始的nth 位置。如果a 是一个数组,您仍然可以使用指针语法 *(a + n) 来引用a[n]。就此而言,n[a] 为您提供相同的功能。

有经验,语法方便。正如我所说,对于学生来说,对两个概念使用相同的语法可能会造成混淆。

这两个概念都出现在您的main 过程中的argv 中:

int main( int argc, char *argv[] )

argv 是什么? argv[0] 是什么?

argv 不是字符串。这是一个数组。什么数组?每个元素(当然包括第一个元素)都是一个char *,一个指向字符的指针。 一个字符。碰巧的是,那个字符后面可能跟着另一个,另一个,在一个 ... string ... 中,直到 NUL 字符,表示终点。

argv 中的每个元素都是固定大小:sizeof(char*)argv 的长度由argc 给出。每个元素指向的每个字符串的长度在编译时是未知的;这取决于调用程序时传递给程序的参数。

记住argv,你会发现你的定义char* array[3][10]更容易理解。您还声明了一个 char * 数组。你还没有做的是操作系统在调用main 时所做的事情:定义一些东西让它们指向,并将它们的地址分配给指针。

使用指针时,总是要问,它指向什么?指针在哪里分配了值,以及该内存是如何分配的(静态、动态或自动)?如果您不确定,系统提醒您它也不知道只是时间问题。

【讨论】:

    【解决方案2】:

    欢迎。

    你的问题有点混乱。

    在 C 中,字符串是带有 NULL 终止符的字符或字节序列,例如最后一个是 '\0' 或 NULL 或 0。 因此:

    char string ="ABCDEF"; char string[7]={'A', 'B', 'C', 'D', 'E', 'F', '\0'}; byte string[7]={'A', 'B', 'C', 'D', 'E', 'F', 0};

    大致相同。

    你可以有一个指向字符串的指针,例如:

    char *ptr = string;

    但不要将其与

    混淆

    char* ptr[7] 因为这是一个指向 char 类型的指针数组

    现在 strcpy 将复制所有元素,直到它检测到一个 NULL 终止符,所以如果你有:

    char string[]= {'A', 'B', 'C', 'D', '\0','E', 'F' };
    

    它只会复制“ABCD”,然后忽略“EF”。

    我不确定为什么您似乎认为 string[0][0] 是您的字符串中的一个空格。

    所有这些都是二维数组中的第一个元素,即 20 x 10。

    您可以通过以下方式遍历数据:

    char *ptr;
    for(int i=0; i<20; i++)
    {
      ptr = string[i][0];
      //do something with ptr
    }
    

    请进一步解释您正在尝试做什么。

    【讨论】:

      猜你喜欢
      • 2021-11-08
      • 2019-09-20
      • 2021-12-21
      • 2013-08-14
      • 2019-06-11
      • 2021-07-02
      • 1970-01-01
      相关资源
      最近更新 更多