我需要创建以这种格式从stdin获取输入的程序:
abcde //number of characters in word = number of words => square shape
fghij
klmno
pqrst
uvwxy
// \n separates first half from second
word1word //any amount of characters, any amount of words
word
word2
sdf
// \n to end input
我的代码有效,但只有大约50%的时间。我有几个示例输入,用于测试,但对于其中一些我的读取函数失败。
这是我的功能,读取文字。由于我不知道它们有多少单词或多长时间,我使用动态数组和getchar()函数。
void readWords(char **p,int *n,int w) /* before calling: n = 50; w = 20; p = 50x20 char array */
{
int i = 0,j = 0,x;
char tmp,prevtmp;
while (1)
{
prevtmp = tmp;
tmp = getchar();
if ((prevtmp == '\n' && tmp == '\n') || feof(stdin))
break; /* no more words to read */
if (tmp == '\n') /* end of word */
{
p[i][j] = '\0'; /* add \0 to create string format */
i++;
j = 0;
if (i == *n) /* if there is more words than there is space for them, double the size */
if (realloc(p,*n*2) != NULL)
*n*=2;
continue;
}
p[i][j] = tmp;
j++;
if (j == w) /* if width of word is larger than allocated space, double it */
{
for (x = 0; x < *n;x++);
if(realloc (p[x],w*2) != NULL);
w=w*2;
}
}
*n = i;
}
这是其工作原理的输入示例(注意:此函数仅在\ n后行读取后半部分):
dsjellivhsanxrr
riemjudhgdffcfz
<skipping>
atnaltapsllcelo
ryedunuhyxhedfy
atlanta
saltlakecity
<skipping 15 words>
hartford
jeffersoncity
这是我的功能无法正确读取的输入:
<skipping>
...oywdz.ykasm.pkfwb.zazqy...
....ynu...ftk...zlb...akn....
missouri
delaware
<skipping>
minnesota
southdakota
我的功能从此输入中读取的内容:
e
yoming
xas
florida
lvania
ana
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
这两个输入之间没有区别(除了不同的单词和不同的单词数量和长度),前半部分无论如何都能正确读取,但只有下半部分出错。我该如何解决这个问题?
P.S。抱歉很长的帖子,如果你想看到没有跳过字节的完整输入,这里是pastebin:http://pastebin.com/hBGn2tej
答案 0 :(得分:4)
realloc()
返回新分配的内存的地址,它不会更新传递给它的参数。所以这(以及realloc()
的其他用法)是不正确的:
if (realloc(p,*n*2) != NULL)
将导致代码访问内存不正确,导致未定义的行为。将realloc()
的结果存储到临时变量,并在更新NULL
之前检查非p
。 realloc()
的参数也表示字节的数量,而不是元素的数量,因此大小参数计算不正确,因为p
是一个数组char*
的{{1}}应该是realloc(p, sizeof(char*) * (*n * 2));
。但是,调用者可以看到p
的更改不。另请注意,realloc()
的唯一合法参数是从之前调用malloc()
,realloc()
或calloc()
获得的指针。代码中的注释 p = 50x20 char array 建议情况并非如此。
这是一个分配char*
数组的小例子,应该会有所帮助:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void f(char*** p)
{
/* Allocate space for two 'char*' elements.
Add a NULL pointer element as sentinel value
so caller knows where to find end of list. */
*p = malloc(sizeof(**p) * 3);
/* Allocate space for the two strings
and populate. */
(*p)[0] = malloc(10);
(*p)[1] = malloc(10);
strcpy((*p)[0], "hello");
strcpy((*p)[1], "world");
(*p)[2] = NULL;
/* Add a third string. */
char** tmp = realloc(*p, sizeof(**p) * 4);
if (tmp)
{
*p = tmp;
(*p)[2] = malloc(10);
strcpy((*p)[2], "again");
(*p)[3] = NULL;
}
}
int main()
{
char** word_list = 0;
f(&word_list);
if (word_list)
{
for (int i = 0; word_list[i]; i++)
{
printf("%s\n", word_list[i]);
free(word_list[i]);
}
}
free(word_list);
return 0;
}
此外:
prevtmp
首次使用时具有未知价值。getchar()
实际上会返回int
而不是char
。