[英]Connecting array to a structure by a pointer C
I have a structure: 我有一个结构:
struct s
{
unsigned size;
char *var;
};
And an array of pointers to structures 以及指向结构的指针数组
for(i=0;i<rows;i++)
{
for(j=0;j<columns;j++)
{
array[i][j] = (struct s*)malloc(sizeof(struct s));
printf("Give the size to structure nr. %d: \n",i*columns+j+1);
scanf("%d",&(array[i][j]->size));
}
}
and a function which returns a pointer to an array of random characters with a size chosen by user: 以及一个返回指向随机字符数组的指针的函数,该数组的大小由用户选择:
char* ChainOfCharacters(int liczba)
{
int i;
char *tabc = NULL;
tabc = (char*)malloc(liczba*sizeof(char));
if(tabc==NULL) exit(-1);
else
{
char *tab=NULL;
tab=tabc;
for(tabc;tabc<tab+liczba;tabc++)
{
*tabc=rand()%(122-97)+97;
}
return tabc;
}
}
How to connect an array of characters which is a result of this function to pointer char *var
of the structure s
by using an array of pointers to structures? 如何通过使用指向结构的指针数组将作为此函数结果的字符数组连接到
structure s
的指针char *var
? Is there any mistake in my code? 我的代码有什么错误吗?
I tried this: array[i][j]->var=ChainOfCharacters(array[i][j]->size);
我试过了:
array[i][j]->var=ChainOfCharacters(array[i][j]->size);
but it seems to be wrong because i have wrong characters while trying to check this by printf. 但这似乎是错误的,因为在尝试通过printf检查此字符时我输入了错误的字符。 I don't even know how to write the array of characters on the screen by printf.
我什至不知道如何通过printf在屏幕上写入字符数组。 I tried this
printf("%c ", *(array[i][j]->var));
我尝试了这个
printf("%c ", *(array[i][j]->var));
but it shows totaly random signs. 但显示完全随机的迹象。 I will be very thankful for answers for my questions :)
我将非常感谢您对我的问题的回答:)
First, let's straighten out a few issues with the posted code. 首先,让我们理顺所发布代码的一些问题。
size_t
is the correct type for array indices and sizes, so the .size
member of the s
structure should have type size_t
. size_t
是数组索引和大小的正确类型,因此s
结构的.size
成员应具有size_t
类型。 This also means that the ChainOfCharacters()
function should take an argument of type size_t
, and this has ramifications for the format string specifiers in the calls to printf()
and scanf()
. 这也意味着
ChainOfCharacters()
函数应采用size_t
类型的参数,这对printf()
和scanf()
的调用中的格式字符串说明符有影响。
A user may not enter a number at the input prompt, in which case no assignment would be made; 用户可能不会在输入提示下输入数字,在这种情况下,将不会进行分配。 but since the posted code does not check the value returned from
scanf()
to verify that a correct input was made, the code would continue with an indeterminate value in that .size
field, leading to undefined behavior. 但是由于发布的代码没有检查从
scanf()
返回的值来验证是否进行了正确的输入,因此代码将在该.size
字段中继续使用不确定的值,从而导致未定义的行为。 The code below checks for this, and exits with an error message if the user fails to input a number here, though this input validation could be further improved. 下面的代码对此进行了检查,如果用户未能在此处输入数字,则退出并显示一条错误消息,尽管可以进一步改进此输入验证。
Note that it is better to use the EXIT_FAILURE
macro than to use -1
, as this is clearer and more portable. 请注意,使用
EXIT_FAILURE
宏比使用-1
更好,因为它更清晰,更可移植。
The ChainOfCharacters()
function does not return a string, but only a pointer to an array of characters, so the characters will need to be printed one-by-one. ChainOfCharacters()
函数不会返回字符串,而只会返回指向字符数组的指针,因此,这些字符需要一张一张地打印出来。
Note that there is no need to cast the result of malloc()
in C, and it is better to use identifers rather than explicit types for operands of the sizeof
operator: this is less error-prone and easier to maintain when types change. 请注意,无需在C中
malloc()
的结果,最好将identifers而不是显式类型用于sizeof
运算符的操作数:这更容易出错,并且在类型更改时更易于维护。
The loop that assigns characters in the ChainOfCharacters()
function is needlessly complex and contains an error, possibly as a result of this complexity; 在
ChainOfCharacters()
函数中分配字符的循环不必要地复杂,并且可能由于这种复杂性而包含错误。 the tabc
pointer points to one past the end of the allocated storage when it is returned. 当返回时,
tabc
指针指向已分配存储区末尾的1。 This can be resolved by rewriting the loop to use an index instead of pointer arithmetic. 这可以通过重写循环以使用索引而不是指针算术来解决。 It is generally clearer and less error-prone to use array indexing instead of pointer arithmetic when possible.
通常,在可能的情况下使用数组索引而不是指针算术更清晰,更不易出错。 Avoid using magic numbers:
rand() % ('z' - 'a') + 'a'
is much clearer in intent than rand()%(122-97)+97
(and don't be afraid to use a little whitespace). 避免使用幻数:
rand() % ('z' - 'a') + 'a'
意图要比rand()%(122-97)+97
清晰得多(不要害怕使用一点空格)。 Further, note that the C Standard makes few restrictions on the character encodings that may be used by an implementation, and in particular this is not required to be ASCII. 此外,请注意,C标准对实现可能使用的字符编码进行了很少的限制,尤其是不需要将其限制为ASCII。 The letters of the Latin alphabet need not even be encoded in a contiguous sequence, as is the case with EBCDIC (which still exists in the real world).
甚至不需要像EBCDIC (仍然存在于现实世界中)那样以连续的顺序对拉丁字母进行编码。 This is unlikely to be a problem here, but know that there are portable ways to handle this issue.
在这里这不太可能成为问题,但是知道有一些可移植的方法来处理此问题。
To assign the result from ChainOfCharacters()
, simply assign the pointer to the appropriate array[][]
field: 要分配
ChainOfCharacters()
的结果,只需将指针分配给适当的array[][]
字段即可:
array[i][j]->var = ChainOfCharacters(array[i][j]->size);
To print the contents of the .var
fields, iterate over the array, and for each struct
, loop over the contents of the allocated storage for .var
, printing the characters: 要打印的内容
.var
字段,迭代在阵列上,并且对于每个struct
,在循环对所分配的存储的内容.var
,打印字符:
/* print characters */
for (size_t i = 0; i < rows; i++)
{
for (size_t j = 0; j < columns; j++)
{
printf("array[%zu][%zu]->val: ", i, j);
for (size_t k = 0; k < array[i][j]->size; k++) {
putchar(array[i][j]->var[k]);
}
putchar('\n');
}
}
After all of this, you will need remember to free()
the allocated memory. 完成所有这些操作后,您将需要记住
free()
分配的内存。 Here is a complete program that implements these changes. 这是实现这些更改的完整程序。
#include <stdio.h>
#include <stdlib.h>
struct s
{
size_t size;
char *var;
};
char* ChainOfCharacters(size_t liczba);
int main(void)
{
size_t rows = 3;
size_t columns = 3;
struct s *array[rows][columns];
for (size_t i = 0; i < rows; i++)
{
for (size_t j = 0; j < columns; j++)
{
array[i][j] = malloc(sizeof *array[i][j]);
printf("Give the size to structure nr. %zu: \n",
i * columns + j + 1);
if (scanf("%zu", &(array[i][j]->size)) != 1) {
fprintf(stderr, "Incorrect input\n");
exit(EXIT_FAILURE);
};
array[i][j]->var = ChainOfCharacters(array[i][j]->size);
}
}
/* print characters */
for (size_t i = 0; i < rows; i++)
{
for (size_t j = 0; j < columns; j++)
{
printf("array[%zu][%zu]->val: ", i, j);
for (size_t k = 0; k < array[i][j]->size; k++) {
putchar(array[i][j]->var[k]);
}
putchar('\n');
}
}
/* free allocated memory */
for (size_t i = 0; i < rows; i++)
{
for (size_t j = 0; j < columns; j++)
{
free(array[i][j]->var);
free(array[i][j]);
}
}
return 0;
}
char* ChainOfCharacters(size_t liczba)
{
char *tabc = NULL;
tabc = malloc(sizeof *tabc * liczba);
if (tabc == NULL) {
exit(EXIT_FAILURE);
} else {
for (size_t i = 0; i < liczba; i++) {
tabc[i] = rand() % ('z' - 'a') +'a';
}
return tabc;
}
}
Sample interaction: 样本互动:
Give the size to structure nr. 1:
1
Give the size to structure nr. 2:
2
Give the size to structure nr. 3:
3
Give the size to structure nr. 4:
9
Give the size to structure nr. 5:
8
Give the size to structure nr. 6:
7
Give the size to structure nr. 7:
4
Give the size to structure nr. 8:
5
Give the size to structure nr. 9:
6
array[0][0]->val: i
array[0][1]->val: lc
array[0][2]->val: psk
array[1][0]->val: lryvmcpjn
array[1][1]->val: bpbwllsr
array[1][2]->val: ehfmxrk
array[2][0]->val: ecwi
array[2][1]->val: trsgl
array[2][2]->val: rexvtj
As I said at the beginning of the answer, size_t
is the correct type for array indices, as it is an unsigned
type that is guaranteed to be able to hold any array index value. 正如我在答案开头所说的那样,
size_t
是数组索引的正确类型,因为它是unsigned
类型,可以保证能够保存任何数组索引值。 But, unsigned
is also fine, though unsigned int
and size_t
may not have the same ranges. 但是,
unsigned
也可以,尽管unsigned int
和size_t
可能没有相同的范围。
A significant problem in the OP code is that the .size
field is unsigned
, while the scanf()
statement that stores input in this field uses the d
conversion specifier, which is meant to be used with int
s. OP代码中的一个重要问题是
.size
字段是unsigned
,而在此字段中存储输入的scanf()
语句使用d
转换说明符,该说明符应与int
s一起使用。 According to the Standard, mismatched conversion specifiers and arguments lead to undefined behavior, which includes appearing to work in some instances. 根据该标准,不匹配的转换说明符和参数会导致未定义的行为,包括在某些情况下似乎起作用。 But you can't rely on undefined behavior doing what you expect.
但是您不能依靠未定义的行为来完成您的期望。 In the posted code,
%u
should have been used to store an unsigned
value in the .size
field. 在发布的代码中,应该使用
%u
在.size
字段中存储unsigned
值。 Further, the ChainOfCharacters()
function was declared to accept an argument of type int
, but was called with an unsigned
argument (from .size
). 此外,
ChainOfCharacters()
函数被声明为接受int
类型的参数,但使用unsigned
参数(来自.size
)调用。 This may also lead to implementation-defined behavior, since an unsigned
value may not be representable in an int
. 这也可能导致实现定义的行为,因为在
int
unsigned
值可能无法表示。
Another place that this problem could arise is in the loop that prints the characters. 可能出现此问题的另一个地方是在打印字符的循环中。 For example, consider:
例如,考虑:
struct s
{
unsigned size;
char *var;
};
/* ... */
int rows = 3;
int columns = 3;
struct s *array[rows][columns];
/* ... */
/* print characters */
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < columns; j++)
{
printf("array[%d][%d]->val: ", i, j);
for (int k = 0; k < array[i][j]->size; k++) {
putchar(array[i][j]->var[k]);
}
putchar('\n');
}
}
Here, k
is a signed int
, while array[i][j]->size
is an unsigned int
type, so the value of k
will be converted to an unsigned
value before the comparison is made. 这里,
k
是有signed int
,而array[i][j]->size
是unsigned int
类型,因此在进行比较之前, k
的值将转换为unsigned
值。 This conversion is well-defined, but can lead to surprises if k
is negative. 此转换定义明确,但如果
k
为负数,可能会导致意外。
Enabling compiler warnings will help to detect issues like this at compile time. 启用编译器警告将有助于在编译时检测到此类问题。 I always use at least
gcc -Wall -Wextra
(and -Wpedantic
too, but you can probably do without this). 我总是至少使用
gcc -Wall -Wextra
(也使用-Wpedantic
,但是您可以不用它)。 Enable compiler warnings, and pay attention to them, and fix them. 启用编译器警告,并注意并修复它们。
In your ChainOfCharacters()
function, you should be returning tab
, not tabc
. 在
ChainOfCharacters()
函数中,您应该返回tab
,而不是tabc
。 tab
is pointing to the beginning of your chain, tabc
is pointing to the end of it. tab
指向链的开头, tabc
指向链的结尾。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.