无法从stdin读取字符串

时间:2012-11-22 11:22:43

标签: c string getchar

我需要创建以这种格式从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

1 个答案:

答案 0 :(得分:4)

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

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

将导致代码访问内存不正确,导致未定义的行为。将realloc()的结果存储到临时变量,并在更新NULL之前检查非prealloc()的参数也表示字节的数量,而不是元素的数量,因此大小参数计算不正确,因为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