c - C - 函数从 char 矩阵返回指向字符串的指针,仅使用指针
问题描述
我需要编写一个名为 MakeString 的函数。该函数返回一个指向字符串的指针,该字符串包含一个由小矩阵的每一行按顺序组成的单词,这样每个换行符将表示为字符串中单词之间的单个空格。(最后一个单词后没有空格。)
推论:在函数中没有使用[],而是通过使用指针来执行。
功能。此外,旅行应该与选民一起进行,这意味着他们实际上会为彼此投票
不管需要什么,都不会一直呆在同一个地方。函数返回的“答案”是一个指针,将被输入到 MAIN 中的一个指针中。
我试着做这个功能,但它不像指令而且不好......
#define SIZE 4
static char allocbuf[SIZE][];
static char *allocp = allocbuf;
char matrix[SIZE][SIZE]
{
{U,N,T,E},
{C,P,G,X},
{D,L,A,B},
{J,T,N,N}
};
char MakeString(int n) /*return pointer to n charachters*/
{
if (allocbuf + SIZE - allocp >=n)
{
allocp += n;
return allocp - n;
}
else
return 0;
}
例如:
小矩阵:
U N T E
C P G X
D L A B
J T N N
pStr = UNTE CPGX DLAB JTNN
谢谢 (:
解决方案
如果我理解您的问题,您想编写一个函数来将字符从matrix
(的 2D 数组char
)读取到分配的字符串中,在每行字符之间放置一个空格,并将以nul 结尾的字符串返回给调用函数。您需要使用指针而不是数组[index]
表示法来执行此操作。
首先,您的声明matrix
是错误的。E
不是字符,是变量。'E'
是字符文字。(注意单引号)所以正确的声明matrix
是:
char matrix[SIZE][SIZE] = { {'U','N','T','E'}, /* don't use globals */
{'C','P','G','X'}, /* declare in main and */
{'D','L','A','B'}, /* pass as a parameter */
{'J','T','N','N'} };
(注意:简单char matrix[][SIZE] = {{...}};
就足够了,其中行数将根据您的初始化进行调整)
如评论中所述,除非绝对必要,否则避免使用全局变量。(非常有限的情况——不在这里)。相反,matrix
在需要它的范围内声明并matrix
作为参数传递给需要处理数据的任何函数。相比之下,定义常量#define
是完全正确的,您应该根据需要定义常量以避免在代码中使用幻数。
由于matrix
是二维数组,要将其作为参数传递,您必须将列数作为传递参数的一部分。您可以将参数声明为char matrix[SIZE][SIZE]
或等效地声明为char (*matrix)[SIZE]
反映第一级间接转换为访问时指向第一个元素的指针这一事实。请参阅:C11 标准 - 6.3.2.1 其他操作数 - 左值、数组和函数指示符(p3)(注意 4 异常)
在您的makestring()
函数中,您必须至少分配存储SIZE * SIZE + SIZE
空间(每个字符的空间 + 3 个空格 + 以nul 结尾的字符)。将新内存块的起始地址分配给一个指针,然后创建指向该块的第二个指针将允许您对其进行迭代,将字符复制到它——同时保留一个指向开头的指针。
将这些部分放在一起,您可以执行以下操作:
char *makestring (char (*a)[SIZE])
{
char *str = malloc (SIZE * SIZE + SIZE), *p = str; /* allocate */
if (!str) { /* validate EVERY allocation */
perror ("malloc-str");
return NULL;
}
for (int i = 0; i < SIZE; i++) { /* for each row */
if (i) /* if row not 1st */
*p++ = ' '; /* add space */
for (int j = 0; j < SIZE; j++) /* for each char */
*p++ = *(*(a + i) + j); /* copy to str */
}
*p = 0; /* nul-terminate string */
return str; /* return pointer to allocated string */
}
(注意:虽然不是错误,但 C 通常避免使用camelCase
或MixedCase
变量名,而支持所有小写,同时保留大写名称以用于宏和常量。)
把它放在一个简短的例子中,你可以这样做:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 4
char *makestring (char (*a)[SIZE])
{
char *str = malloc (SIZE * SIZE + SIZE), *p = str; /* allocate */
if (!str) { /* validate EVERY allocation */
perror ("malloc-str");
return NULL;
}
for (int i = 0; i < SIZE; i++) { /* for each row */
if (i) /* if row not 1st */
*p++ = ' '; /* add space */
for (int j = 0; j < SIZE; j++) /* for each char */
*p++ = *(*(a + i) + j); /* copy to str */
}
*p = 0; /* nul-terminate string */
return str; /* return pointer to allocated string */
}
int main (void) {
char matrix[SIZE][SIZE] = { {'U','N','T','E'}, /* don't use globals */
{'C','P','G','X'}, /* declare in main and */
{'D','L','A','B'}, /* pass as a parameter */
{'J','T','N','N'} },
*str;
if ((str = makestring (matrix))) { /* validate call to makestring */
printf ("str: '%s'\n", str); /* output string */
free (str); /* free allocated memory */
}
}
(注意:不要忘记free
你分配的内存。虽然它会在程序退出时被释放,但要养成跟踪你的分配并确保你分配的所有块都被释放的习惯)
示例使用/输出
$ ./bin/makestring
str: 'UNTE CPGX DLAB JTNN'
内存使用/错误检查
在您编写的任何动态分配内存的代码中,对于分配的任何内存块,您有两个责任:(1)始终保留指向内存块起始地址的指针,(2)它可以在没有时被释放更需要。
您必须使用内存错误检查程序来确保您不会尝试访问内存或写入超出/超出分配块的边界,尝试读取或基于未初始化值的条件跳转,最后确认释放所有分配的内存。
对于 Linuxvalgrind
是正常的选择。每个平台都有类似的内存检查器。它们都易于使用,只需通过它运行您的程序即可。
$ valgrind ./bin/makestring
==6576== Memcheck, a memory error detector
==6576== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==6576== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==6576== Command: ./bin/makestring
==6576==
str: 'UNTE CPGX DLAB JTNN'
==6576==
==6576== HEAP SUMMARY:
==6576== in use at exit: 0 bytes in 0 blocks
==6576== total heap usage: 1 allocs, 1 frees, 20 bytes allocated
==6576==
==6576== All heap blocks were freed -- no leaks are possible
==6576==
==6576== For counts of detected and suppressed errors, rerun with: -v
==6576== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
始终确认您已释放所有已分配的内存并且没有内存错误。
如果您还有其他问题,请仔细查看并告诉我。
推荐阅读
- algorithm - 总和为值 b 的浮点数数组。给定一个整数 c,我如何确保 sum(每个数组元素 / c) == b / c
- java - 如何更改 JEditorPane 中选定文本的颜色?
- scala - 奇怪的 scala 元组行为
- python - 我该如何解决?该应用程序在 API 密钥中显示错误,就像 (KeyError: 'Api Key not found.')
- swift - SwiftUI 中@State 变量的生命周期是什么?
- git - 每次更改相同的文件时是否会发生合并冲突?
- javascript - 从数组中计算单词分数
- linux - 如何让我的 VPS 开始使用通过 HostMonster 购买的额外磁盘空间?
- swift - macOS 本地和远程通知停止工作——不再有设备令牌
- python - 站在数组中的附近元素 - python