gpt4 book ai didi

c - 分配二维数组后字符串被截断(已编辑)

转载 作者:太空宇宙 更新时间:2023-11-04 06:16:55 24 4
gpt4 key购买 nike

我像这样动态分配二维数组:

char ** inputs;
inputs = (char **) malloc(4 * sizeof(char));

这样做之后,我开始遇到字符串问题。我在分配二维数组之前和之后打印了字符串:

printf("%s\n", str);
char ** inputs;
inputs = (char **) malloc(4 * sizeof(char));
printf("%s\n", str);

但是我得到了奇怪的输出:

before: input aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa with len  34
after: input aaaaaaaaaaaaaaaaaaaaaaaaaaaa with len 29

为什么长度变了?我搜索过 stackoverflow 和其他网站,但找不到合理的答案。

这是我所有的函数调用:

int main(int argc, char const *argv[])
{
/* code */

mainProcess();
printf("\nEnd of the program\n");
return 0;
}

// Reading the input from the user
char * getInput(){
printf("Inside of the getInput\n");
char * result;
char * st;
char c;
result = malloc(4 * sizeof(char));
st = malloc(4 * sizeof(char));
// code goes here
printf("$ ");
while(3){
c = fgetc(stdin);
if(c == 10){
break;
}
printf("%c", c);
result[length] = c;
length++;
}

result[length] = '\0';

return result;
}

void mainProcess(){
char * input;

printf("Inside of Main process\n");

input = getInput();
printf("\nthis is input %s with len %d\n", input, strlen(input));

splitInput(input);

printf("\nthis is input %s with len %d\n", input, strlen(input));
}



char ** splitInput(const char * str){
char ** inputs;
inputs = NULL;
printf("inside split\n");
printf("%s\n", str);

inputs = (char **) malloc( sizeof(char));


// free(inputs);
printf("------\n"); // for testing
printf("%s\n", str);
if(!inputs){
printf("Error in initializing the 2D array!\n");
exit(EXIT_FAILURE);
}

return NULL;
}

最佳答案

目前还不完全清楚您要完成什么,但您似乎正在尝试使用 getInput 读取一行文本,然后您打算将输入分成 中的单个单词>splitInput,但不清楚如何去做。将一行文本分成单词的过程称为标记字符串。标准库提供 strtok(恰本地命名)和 strsep(如果您有一个分隔字段的可能性,则主要有用)。

我已经在上面的评论中解释了二维数组和您使用pointer-to-pointer-to-char 之间的区别。

首先,查看 getInput。一个让您苦不堪言的问题是 c 必须是 int 类型,否则您无法检测到 EOF。此外,您可以简单地传递一个指针(类型 size_t)作为参数,并保持 result 中的字符计数,避免需要 strlen 获取返回字符串的长度。无论如何,您必须使用一个计数器来确保您不会在开始时超出 result 的末尾,因此您也可以在调用函数中返回可用的计数,例如

char *getInput (size_t *n)
{
printf ("Inside of the getInput\n");
char *result = NULL;
int c = 0; /* c must be type 'int' or you cannot detect EOF */

/* validate ALL allocations */
if ((result = malloc (MAXC * sizeof *result)) == NULL) {
fprintf (stderr, "error: virtual memory exhausted.\n");
return result;
}

printf ("$ ");
fflush (stdout); /* output is buffered, flush buffer to show prompt */

while (*n + 1 < MAXC && (c = fgetc (stdin)) != '\n' && c != EOF) {
printf ("%c", c);
result[(*n)++] = c;
}
putchar ('\n'); /* tidy up with newline */

result[*n] = 0;

return result;
}

接下来,如上所示,您似乎想要获取 result 中的文本行并使用 splitInput 来填充 pointer-to-pointer- to-char 与单个单词(您将其混淆为二维数组)。为此,您必须牢记 strtok修改它操作的字符串,因此您必须复制您传递的 str作为 const char * 以避免尝试修改常量字符串(和段错误)。

您对如何分配指针到指针到字符对象感到困惑。首先,您必须为足够数量的指针分配空间,例如(使用 #define MAXW 32)你需要这样的东西:

    /* allocate MAXW pointers */
if ((inputs = malloc (MAXW * sizeof *inputs)) == NULL) {
fprintf (stderr, "error: memory exhausted - inputs.\n");
return inputs;
}

然后当您标记输入字符串时,您必须为每个单独的单词(每个单词本身都是一个单独的字符串)分配,例如

        if ((inputs[*n] = malloc ((len + 1) * sizeof *inputs[*n])) == NULL) {
fprintf (stderr, "error: memory exhausted - word %zu.\n", *n);
break;
}
strcpy (inputs[*n], p);
(*n)++;

注意:'n' 是一个指向size_t 的指针,使调用者可以返回字数统计。

要标记输入字符串,您可以将上面的分配包装在:

    for (char *p = strtok (cpy, delim); p; p = strtok (NULL, delim))
{
size_t len = strlen (p);
...
if (*n == MAXW) /* check if limit reached */
break;
}

在您的整个代码中,您还应该验证所有内存分配并为分配的每个函数提供有效的返回值,以允许调用者验证被调用函数是成功还是失败。

将所有部分放在一起,您可以执行以下操作:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXC 256 /* constant for maximum characters of user input */
#define MAXW 32 /* constant for maximum words in line */

void mainProcess();

int main (void)
{
mainProcess();
printf ("End of the program\n");

return 0;
}

char *getInput (size_t *n)
{
printf ("Inside of the getInput\n");
char *result = NULL;
int c = 0; /* c must be type 'int' or you cannot detect EOF */

/* validate ALL allocations */
if ((result = malloc (MAXC * sizeof *result)) == NULL) {
fprintf (stderr, "error: virtual memory exhausted.\n");
return result;
}

printf ("$ ");
fflush (stdout); /* output is buffered, flush buffer to show prompt */

while (*n + 1 < MAXC && (c = fgetc (stdin)) != '\n' && c != EOF) {
printf ("%c", c);
result[(*n)++] = c;
}
putchar ('\n'); /* tidy up with newline */

result[*n] = 0;

return result;
}

/* split str into tokens, return pointer to array of char *
* update pointer 'n' to contain number of words
*/
char **splitInput (const char *str, size_t *n)
{
char **inputs = NULL,
*delim = " \t\n", /* split on 'space', 'tab' or 'newline' */
*cpy = strdup (str);

printf ("inside split\n");
printf ("%s\n", str);

/* allocate MAXW pointers */
if ((inputs = malloc (MAXW * sizeof *inputs)) == NULL) {
fprintf (stderr, "error: memory exhausted - inputs.\n");
return inputs;
}

/* split cpy into tokens (words) max of MAXW words allowed */
for (char *p = strtok (cpy, delim); p; p = strtok (NULL, delim))
{
size_t len = strlen (p);

if ((inputs[*n] = malloc ((len + 1) * sizeof *inputs[*n])) == NULL) {
fprintf (stderr, "error: memory exhausted - word %zu.\n", *n);
break;
}
strcpy (inputs[*n], p);
(*n)++;

if (*n == MAXW) /* check if limit reached */
break;
}

free (cpy); /* free copy */

return inputs;
}

void mainProcess()
{
char *input = NULL,
**words = NULL;
size_t len = 0, nwords = 0;

printf ("Inside of Main process\n\n");

input = getInput (&len);

if (!input || !*input) {
fprintf (stderr, "error: input is empty or NULL.\n");
return;
}

printf ("this is input '%s' with len: %zu (before split)\n", input, len);

words = splitInput (input, &nwords);

printf ("this is input '%s' with len: %zu (after split)\n", input, len);

free (input); /* done with input, free it! */

printf ("the words in input are:\n");

for (size_t i = 0; i < nwords; i++) {
printf (" word[%2zu]: '%s'\n", i, words[i]);
free (words[i]); /* free each word */
}
free (words); /* free pointers */

putchar ('\n'); /* tidy up with newline */
}

示例使用/输出

$ ./bin/mainprocess
Inside of Main process

Inside of the getInput
$ my dog has fleas
my dog has fleas
this is input 'my dog has fleas' with len: 16 (before split)
inside split
my dog has fleas
this is input 'my dog has fleas' with len: 16 (after split)
the words in input are:
word[ 0]: 'my'
word[ 1]: 'dog'
word[ 2]: 'has'
word[ 3]: 'fleas'

End of the program

内存错误检查

在您编写的任何动态分配内存的代码中,您需要通过内存/错误检查程序运行您的代码。在 Linux 上,valgrind 是通常的选择。只需通过它运行您的代码,例如

$ valgrind ./bin/mainprocess
==15900== Memcheck, a memory error detector
==15900== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==15900== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==15900== Command: ./bin/mainprocess
==15900==
Inside of Main process

Inside of the getInput
$ my dog has fleas
my dog has fleas
this is input 'my dog has fleas' with len: 16 (before split)
inside split
my dog has fleas
this is input 'my dog has fleas' with len: 16 (after split)
the words in input are:
word[ 0]: 'my'
word[ 1]: 'dog'
word[ 2]: 'has'
word[ 3]: 'fleas'

End of the program
==15900==
==15900== HEAP SUMMARY:
==15900== in use at exit: 0 bytes in 0 blocks
==15900== total heap usage: 7 allocs, 7 frees, 546 bytes allocated
==15900==
==15900== All heap blocks were freed -- no leaks are possible
==15900==
==15900== For counts of detected and suppressed errors, rerun with: -v
==15900== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

始终验证您已释放分配的所有内存,并且没有内存错误。

检查一下,如果您有任何问题,请告诉我。如果我猜错了你的意图,那么这就是 MCVE 帮助的地方 :)

关于c - 分配二维数组后字符串被截断(已编辑),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43476675/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com