简体   繁体   English

char a[50][50] 在 C 中是什么意思?

[英]What does char a[50][50] mean in C?

I'm working on a homework that has to do with strings.我正在做与字符串有关的作业。 Here's the code这是代码


int main(){
    char a[50][50];
    int n;
    printf("Enter the value of n\n");
    scanf("%d",&n);
    printf("Enter %d names\n",n);
    fflush(stdin);
    for(int i=0; i<n; i++){
        gets(a[i]);
    }

I tried to change the char a[50][50] into char a[50] but the entire program didn't run, came along with this error message: "Invalid conversion from 'char' to '*char' I don't really understand how this works.我试图将字符 a[50][50] 更改为字符 a[50],但整个程序没有运行,并出现以下错误消息:“从 'char' 到 '*char' 的无效转换我不知道”真的不明白这是如何工作的。

char a[50][50] declares a to be an array of 50 arrays of 50 char . char a[50][50] a声明a包含 50 个char的 50 个数组的数组。

Then a[0] is an array of 50 char , and so is a[1] , a[2] .那么a[0]是一个包含 50 个char的数组, a[1]a[2] a[3] , and so on up to a[49] . a[3] ,依此类推直到a[49] There are 50 separate arrays, and each of them has 50 char .有 50 个单独的数组,每个数组都有 50 个char

Since a[0] is an array of 50 char , a[0][0] is a char .由于a[0]是一个包含 50 个char的数组,因此a[0][0]是一个char In general, a[i][j] is character j of array i .通常, a[i][j]是数组i字符j

gets(a[i]) says to read characters from input and put them into a[i] . gets(a[i])表示从输入中读取字符并将它们放入a[i] For this to work, a[i] must be an array of chargets reads multiple characters and puts them in the array.为此, a[i]必须是一个char数组—— gets读取多个字符并将它们放入数组中。 If a[i] were a single character, gets could not work.如果a[i]是单个字符, gets将无法工作。

Although gets(a[i]) says to put characters into a[i] , it works by passing an address instead of passing the array.尽管gets(a[i])表示将字符放入a[i] ,但它的工作原理是传递地址而不是传递数组。 When an array is used in an expression other than as the operand of sizeof or the address operator & , C automatically converts it to a pointer to its first element.当数组在表达式中使用而不是用作sizeof的操作数或地址运算符& ,C 会自动将其转换为指向其第一个元素的指针。 Since a[i] is an array, it is automatically converted to a pointer to its first element (a pointer to a[i][0] ).由于a[i]是一个数组,它会自动转换为指向其第一个元素的指针(指向a[i][0]的指针)。 gets receives this pointer and uses it to fill in characters that it reads from the standard input stream. gets接收这个指针并用它来填充它从标准输入流中读取的字符。

char a[50][50] declares a as a 50-element array of 50-element arrays of char . char a[50][50]声明a作为50元件阵列的50个元素的数组char That means each a[i] is a 50-element array of char .这意味着每个a[i]都是一个包含 50 个元素的char数组。 It will be laid out in memory like:它将在内存中布置,如:

   +---+
a: |   | a[0][0]
   +---+
   |   | a[0][1]
   +---+
   |   | a[0][2]
   +---+
    ...
   +---+
   |   | a[0][49]
   +---+
   |   | a[1][0]
   +---+
   |   | a[1][1]
   +---+
    ...
   +---+
   |   | a[1][49]
   +---+
   |   | a[2][0]
   +---+ 
    ...

This code is storing up to 50 strings , each up to 49 characters long, in a (IOW, each a[i] can store a 49-character string).该代码被存储多达50,每个多达49个字符长,在a (IOW,每a[i]可以存储49个字符的字符串)。 In C, a string is a sequence of character values including a 0-valued terminator.在 C 中,字符串是包含 0 值终止符的字符值序列。 For example, the string "hello" , is represented as the sequence {'h', 'e', 'l', 'l', 'o', 0} .例如,字符串"hello"表示为序列{'h', 'e', 'l', 'l', 'o', 0} That trailing 0 marks the end of the string.尾随0标记字符串的结尾。 String handling functions and output functions like puts and printf with the %s specifier need that 0 terminator in order to process the string correctly.字符串处理函数和输出函数(如带有%s说明符的putsprintf需要该 0 终止符才能正确处理字符串。

Strings are stored in arrays of character type, either char (for ASCII, UTF-8, or EBCDIC character sets) or wchar_t for "wide" strings (character sets that require more than 8 or so bits to encode).字符串存储在字符类型的数组中,可以是char (对于 ASCII、UTF-8 或 EBCDIC 字符集)或wchar_t用于“宽”字符串(需要超过 8 位左右进行编码的字符集)。 An N-character string requires an array that's at least N+1 elements wide to account for the 0 terminator.一个 N 字符的字符串需要一个至少N+1 个元素宽的数组来解释 0 终止符。

Unless it is the operand of the sizeof or unary & operator, or is a string literal used to initialize an array of character type, an expression of type "N-element array of T " will be converted ("decay") to an expression of type "pointer to T ", and the value of the expression will be the address of the first element of the array.除非它是sizeof或一元&运算符的操作数,或者是用于初始化字符类型数组的字符串字面量,否则类型为“ T N 元素数组”的表达式将被转换(“衰减”)为表达式类型为“指向T指针”,表达式的值将是数组第一个元素的地址。

When you call你打电话时

gets( a[i] );

the expression a[i] is converted from type "50-element array of char " to "pointer to char ", and the value of the expression is the address of the first element of the array ( &a[i][0] ) 1 .表达式a[i]从类型“50 元素的char数组”转换为“指向char指针”,表达式的值是数组第一个元素的地址( &a[i][0]1 . gets will read characters from standard input and store them to the array starting at that address. gets将从标准输入读取字符并将它们存储到从该地址开始的数组中。 Note that gets is no longer part of the standard C library - it was removed in the 2011 version of the standard because it is unsafe.请注意, gets不再是标准 C 库的一部分——它在标准的 2011 版本中被删除,因为它不安全。 C does not require any sort of bounds checking on array accesses - if you type in more characters than the target buffer is sized to hold (in this case, 50), those extra characters will be written to memory immediately following the last element of the array, which can cause all sorts of mayhem. C 不需要对数组访问进行任何类型的边界检查 - 如果您输入的字符多于目标缓冲区可容纳的大小(在本例中为 50),这些额外的字符将立即写入内存中的最后一个元素数组,这可能会导致各种混乱。 Buffer overflows are a popular malware exploit.缓冲区溢出是一种流行的恶意软件利用。 You should replace the gets call with此时应更换gets通话用

fgets( a[i], 50, stdin );

which will read up to 49 characters into a[i] from standard input.它将从标准输入读取最多 49 个字符到a[i] Note that any excess characters are left in the input stream.请注意,任何多余的字符都会留在输入流中。

Also, the behavior of fflush is not defined for input streams 2 - there's no good, safe, portable way to clear excess input except to read it using getchar or fgetc .此外,没有为输入流2定义fflush的行为 - 除了使用getcharfgetc读取它之外,没有好的、安全的、可移植的方法来清除多余的输入。


  1. This is why you got the error message you did when you changed a from char [50][50] to char [50] - in that case, a[i] has type char , not char * , and the value of a[i] is not an address .这就是为什么你得到了你没有当您更改错误消息achar [50][50]char [50] -在这种情况下, a[i]有一个类型char ,不char * ,和值a[i]不是地址
  2. Microsoft's Visual Studio C compiler is a notable exception - it will clear excess input from the input stream.微软的 Visual Studio C 编译器是一个明显的例外——它会从输入流中清除多余的输入。 However, that's specific to MSVC, and not portable across different compilers.但是,这是特定于 MSVC 的,不能跨不同编译器移植。 The operation is also a little nonsensical with respect to "flush" semantics.该操作在“刷新”语义方面也有点荒谬。

基本上,在 C 中,这表示长度为 0 到 50 的数组,其中包含数组的每个单元格中的字符值 50

That program seems to store n names in the array a .该程序似乎在数组a存储了n名称。 It first asks for the number of names, and then the names.它首先询问姓名的数量,然后询问姓名。 The method char *gets(char *str) stores each different line in an entry of a .该方法char *gets(char *str)存储在一个条目中的每个不同的线a

n has 2 dimensions. n有 2 个维度。 The first refers to the number of names, and the second is for the length of each name.第一个是指名称的数量,第二个是指每个名称的长度。 Something like n[number_of_names][lenght_of_name]类似于n[number_of_names][lenght_of_name]

However, it will probably crash if the user provides an n > 50, or if a name contains more than 50 chars.但是,如果用户提供 n > 50,或者名称包含超过 50 个字符,它可能会崩溃。

Also, gets() is dangerous.此外, gets()是危险的。 See this other post .请参阅此其他帖子

EDIT: Changing a to one dimensions makes the program try to store a whole line inside a char, hence the error编辑:a更改为一维会使程序尝试在字符内存储整行,因此出现错误

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM