0

我需要创建以这种格式从标准输入获取输入的程序:

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% 的时间。我有几个示例输入,用于测试,但对于其中一些输入,我的 readwords 函数失败了。

这是我的功能,读取单词。由于我不知道有多少字或它们将是多长时间,所以我使用动态数组和 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
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ

这两个输入之间没有区别(除了不同的单词以及不同的单词数量和长度),无论如何都可以正确读取前半部分,但只有后半部分会出错。我该如何解决?

PS 很抱歉很长的帖子,如果你想看到没有跳过字节的完整输入,这里是 pastebin:http://pastebin.com/hBGn2tej

4

1 回答 1

4

realloc()返回新分配内存的地址,它不会更新传递给它的参数。所以这个(以及 的其他用法realloc())是不正确的:

if (realloc(p,*n*2) != NULL)

并且会导致代码错误地访问内存,导致未定义的行为。将结果存储到临时变量并在更新前realloc()检查非。to 的参数还指示字节数,而不是元素的数量,因此 size 参数计算不正确,因为它应该是数组。但是,对调用者的更改将可见。另请注意,唯一合法的参数是从先前调用或获得的指针。代码中的注释p = 50x20 char array建议NULLprealloc()pchar*realloc(p, sizeof(char*) * (*n * 2));prealloc()malloc()realloc()calloc()不是这种情况。

这是一个分配数组的小示例,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()实际上返回 aint而不是 a char
于 2012-11-22T11:25:57.520 回答