- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我像这样动态分配二维数组:
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/
我有一个 1850-2005 年月地表气温的 netCDF 文件。如何在 unix 中截断文件,以便新文件的时间维度从 1855 年到 2005 年?反之亦然,截断文件,使其改为 1850-2000?
我收到此错误 Bulk load data conversion error (truncation) for row 1, column 12 (is_download) 这是 csv...它只有一
我有一个列表,它是电子邮件正文,每行末尾都有一个日期和时间戳。邮票的格式是一致的,所以可以从右边计算表达式。以下是示例数据: Dear Volunteer2018-05-21 19:59:15 You
我正在使用内置 truncatewords_html Django 的过滤器,它在最后添加了“...”,相反,我想用“查看更多”链接替换它。 我怎样才能做到这一点? 最佳答案 最好编写自己的过滤器。您
我正在使用 SQL 加载器将我的数据加载到数据库中。 在插入数据之前,我需要删除表中的现有数据: options(skip=1,load=250000,errors=0,ROWS=30000,BIND
我正在尝试掌握消息队列的窍门。由于某种原因,当显示我在控制台中输入的消息时,字符串有时会被截断或更改。有谁知道为什么会发生这种情况? void *readFromQueue() { int r
我正在使用mediawiki API(例如http://en.wikipedia.org/w/api.php),我希望能够“截断”mysql表以便重置本地安装,同时保留一些表(用户,?...) 。SQ
想要截断一个存在的表: IF EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'mytable') TRUNCATE
我正在实现一个使用 Python Numpy 包的程序。我正在尝试修改数组的元素,以便我只需采用 elem[i][j] 并将其设置为 elem[i][j]/10。但是,我不断收到某种截断,其中元素在操
我有一个 64 位 long int,其中包含一些位域。我需要将存储在第二个和第三个字节中的 16 位带符号整数添加到一个 32 位值中。我正在使用这样的东西: u32 Function( s32 v
我有这样的文字:“我的文字是 blabla blabla, lala lala”。 我希望在我的 UILabel 中有这样的文本:“My text is ...lala”。 如何配置我的 UILabe
Umbraco Truncate 似乎不适合我,当我使用正确的代码(根据互联网)时,它会不断出错。我不知道它有什么问题。 错误代码: Compiler Error Message: CS1502: T
早些时候,我是使用 JS 动态地完成它的。但是我们遇到了一些性能问题,因为我们必须提供一个替代选项。 我现在使用文本溢出样式截断选项卡名称上的长文本。 但我有一个小问题,如果有人能解决的话 目前这是我
使用Rspec时截断、事务和删除数据库策略有什么区别?我找不到任何资源来解释这一点。我阅读了 Database Cleaner 自述文件,但它没有解释它们各自的作用。 为什么我们必须对 capybar
当然, 尚有诸位前辈也曾把以上三种方案结合一二, 以达到更广泛的适应度. 不过, 这厢先前在网路上搜索许久, 却未曾寻到三种方案合为一体的尝试, 于是只好自己动手写一下了:) 没有dem
有没有办法截断HSQLDB中的所有表? 如果这不可能,是否有任何方法可以级联删除具有外键引用的表? 最佳答案 可以截断模式中的所有表: 截断模式并提交 此命令有一些选项在指南中有描述: http://
我有一个要截断的时间戳。我正在使用 trunc oracle中的函数。这似乎做了我想要的但是从文档中它应该只接受日期而不是时间戳 select TRUNC(TO_DATE('22-AUG-13'),
我读到一旦你耗尽了一个节点,你就可以删除文件然后重新启动。它工作正常, 但我只是通过排空所有节点,关闭整个集群,删除文件并重新启动来尝试它。 如果我一次只重启一个节点会怎样?据我了解有风险 重新启动的
我想截断 d3 中超过预定义限制的文本。 我不知道该怎么做。 这是我现在所拥有的: node.append("text") .attr("dx", 20) .attr("dy", ".20
嗨 Guyz 我有一个固定宽度的 WPF TextBlock 说 100 ,如果字符串不适合宽度,则最后一个字符总是被截断,因为所有字符的大小都不相同。我不想剪切字符而是我想从那里跳过文本并只显示没有
我是一名优秀的程序员,十分优秀!