scanf字符串搞砸了

时间:2013-01-13 20:47:12

标签: c string pointers struct scanf

struct dict {
    int len;
    char (*dict0)[MAX_WORD_LEN+1];
    char (*dict1)[MAX_WORD_LEN+1];
};

/* the memory allocation */
void createDict(struct dict* myDict)
{
    (*myDict).dict0 = malloc((*myDict).len*sizeof(char));
    (*myDict).dict1 = malloc((*myDict).len*sizeof(char));
    if(((*myDict).dict0==0)||((*myDict).dict1==0))
        exit(1);
}

for(int i = 0; i < words; i++)
{
   scanf("%s", p_diction->dict0[i]);
   scanf("%s", p_diction->dict1[i]);
}

for(int i=0; i<words; i++)
{
   printf("%s ", &p_diction->dict0[i]);
   printf("%s\n", &p_diction->dict1[i]);

}

p_diction是指向dict类型的指针。

我将words设置为11并输入以下内容:

one lo
two ba
three li
day night
work eat
great terrible
terrible disaster
A a
start delay
finish never
I you

但是当我printf检查字符串时,会打印以下内容:

one ree
two y
three rk
day eat
work rrible
great terrible
terrible art
A nish
start delay
finish never
I you

任何关于为什么第一个scanf完美地读取它的想法,而第二个只是从随后会出现的单词中读取随机内容?

2 个答案:

答案 0 :(得分:0)

您正在重新声明我并且您不需要(对于printf循环)。对于第二个循环,我已经存在,因此i=0足以“重新启动”变量。

关于读取循环,scanf是'安全的',如果你用enter / return分隔单词。如果你用空格分隔它们,scanf不是一个好选择。第二个scanf正在查找输入/返回,如果你没有通过stdin给它,它将失败并且它可能会存储垃圾直到它找到enter / return(\ n)。

还有一件事,你是如何宣布pdiction的? 如果你这样做:

struct dict *pdiction = malloc(sizeof(struct dict));

您可以通过以下方式访问其“内部”变量:

pdiction->len = 10; /*Setting len to 10*/

但是如果你声明它,在与读/写循环相同的函数内,就像这样:

struct dict pdiction;

您可以通过以下方式访问“内部”变量:

pdiction.len = 10;

第二种方式是如何正常访问C结构。所谓的点符号。 第一种方式有点像C的演变:使用“在字段中指出”指向结构的指针是如此常见,C为您提供了更好/更容易/更易读的方法:箭头表示法。 我在第一种情况下所写的内容完全相同:

(*pdiction).len = 10; /*The (structure) pointed by pdiction in the field len*/

所以要小心。

刚刚结束,我认为你是故意这样做的,但printf可能是打印内存地址而不是实际的字符串,因为你正在使用内存地址'selector'&符号。

[编辑] - 看完你的编辑后我可以看到一个可能的错误。如果在结构中,您已使用静态值声明了字符串:

char (*dict0)[MAX_WORD_LEN+1];
char (*dict1)[MAX_WORD_LEN+1];

您无需为他们“重新分配”空间。 你需要的是有一个字符串向量或字典向量。 访问pdiction->dict[i]只是一个字符。 如果你想要一个向量,你需要改变你的分配。

我会通过在结构中仅声明指针并稍后进行向量分配而不是使用dicts(结构)的向量来实现。

您可以通过将结构更改为此来执行此操作:

struct dict {
    int len;
    char **dict0;
    char **dict1;
};

然后你必须在函数中分配你的向量:

pdiciton->dict0 = malloc(NUMBER_OF WORDS * sizeof (char*));
for(i=0;i<NUMBER_OF_WORDS;i++)
   pdiction->dict0[i] = malloc(MAXIMUM_SIZE_OF_A_WORD*sizeof(char));

dict1也一样。 这可能看起来很奇怪,但如果你认为它实际上是逻辑:如果一个字符串是一个字符向量,字符串向量就是一个字符矩阵。

scanf的问题看起来是一样的:使用enter / return是安全的,但不能使用空格。尝试插入所有数据,然后输入/返回下一个而不是空格,看看它是否有效。

希望这会有所帮助。

答案 1 :(得分:0)

看起来你正在使用一维数组来保存多个字符串(单词),如果你用一个表示单词结尾的唯一字符结束每个字符串(单词),这是可能的。但是不可能使用vanilla函数scanf()和printf()来编写自己的函数。例如,假设您用@结束每个单词。以下循环会将所有单词打印到屏幕上。

int i = 0;
while((*myDict).dict0[i] != '\0')//While index dose not point to end of array
{
  for(; (*myDict).dict0[i] != '@'; i++)//Print one word a single character at a time
  {
    printf("%c", (*myDict).dict0[i]);
  }
  printf("\n"); i++;//Print a newline after the word and then increase the index by one
                    //so that it does not point to '@'.
}

但你也可以将你的dict0和dict1数组变成指针数组,其中每个元素都是一个指向单个单词的指针。