使用scanf将字符串读入字符串数组

时间:2016-03-18 03:23:34

标签: c

我正在尝试创建一个简单的程序,使用scanf从标准输入中读取字符串并将它们放入字符串数组中(现在我只是使用3个单词测试它,因此只有3个打印语句在结束)。我能够继续阅读,直到没有更多的字符串,但是我遇到了一个错误,在循环完成后,数组中的所有字符串都是读入的最后一个字符串。我试过在其中放入一个print语句要调试的循环,它正在读取正确的字符串。但是当循环结束时,数组中的所有字符串都是读入的最后一个字符串。任何人都可以指出我在哪里出错吗?感谢。

#include <stdio.h>
#include <stdlib.h>



int main(void) {
    int c = 0;
    char** w_arr = malloc(3*sizeof(char*));
    char* w = malloc(10*sizeof(char));

    while (scanf("%s", w) == 1) {
        w_arr[c] = w;
        //printf("%s", w_arr[c]); debug print statement
        c++;
    }

    printf("%s, %s, %s\n", w_arr[0], w_arr[1], w_arr[2]);
    return 0;
}

5 个答案:

答案 0 :(得分:1)

您正在为每个w元素重复使用w_arr(即它们都指向同一个位置)。您需要为每个字符串分配一个

变化:

w_arr[c] = w;

要:

w_arr[c] = strdup(w);

答案 1 :(得分:1)

声明

    w_arr[c] = w;

确保w_arr的所有元素都指向同一个指针ww循环结束后保存在while的数据是读取的最后一个输入。因此,您会看到w_arr的所有元素的相同输出。

我可以想到几种解决这个问题的方法。

  1. 分配到strdup

    时使用w_arr[c]
    w_arr[c] = strdup(w);
    

    如果您的平台上没有strdup,则很容易实现。{/ p>

    char* strdup(char const* in)
    {
        char* ret = malloc(strlen(in)+1);
        strcpy(ret, in);
        return ret;
    }
    
  2. w循环中为while分配第二,第三等输入的内存。

    而不是

    char* w = malloc(10*sizeof(char));
    while (scanf("%s", w) == 1) {
       w_arr[c] = w;
       //printf("%s", w_arr[c]); debug print statement
       c++;
    }
    

    使用

    char* w = malloc(10*sizeof(char));
    while (scanf("%s", w) == 1) {
       w_arr[c] = w;
       //printf("%s", w_arr[c]); debug print statement
       c++;
       w = malloc(10*sizeof(char));
    }
    
  3. 确保在函数结束前添加对deallocate mmory的调用。

        free(w);
        for (int i = 0; i < 3; ++i )
           free(w_arr[i]);
    

答案 2 :(得分:1)

您正在将w_arr的每个元素设置为仅分配一次的单个缓冲区w。您可以通过在循环后添加以下行来打印出w_arr的内容来看到这一点:

printf("Addresses of strings: %p, %p, %p\n", w_arr[0], w_arr[1], w_arr[2]);

您应该看到类似于以下内容的输出:

[hwibell@localhost tmp]$ ./strings
123
456
789
Addresses of strings: 0x1b0b030, 0x1b0b030, 0x1b0b030 <-- Same address!
Contents of strings: 789, 789, 789

如您所见,w_arr的每个元素都指向内存中的相同地址。要解决此问题,您需要每次分配w,然后将新字符数组分配给w_arr。

#define NUM_OF_STRINGS 3
#define MAX_CHARS      10

int main(void) {
    char** w_arr = malloc(NUM_OF_STRINGS * sizeof(char*));

    for (int i = 0; i < NUM_OF_STRINGS; ++i) {
        w_arr[i] = malloc(MAX_CHARS * sizeof(char)); // allocate a new buffer for each element in w_arr
        scanf("%s", w_arr[i]);
    }

    printf("%s, %s, %s\n", w_arr[0], w_arr[1], w_arr[2]);
    return 0;
}

答案 3 :(得分:0)

 w_arr[c] = w;

由于w_arr[c]指向w,其循环结尾处的内容是最后一个读取字符串,因此您将打印最后一个字符串。

您为w_arr -

中的每个指针分配内存
 char** w_arr = malloc(3*sizeof(char*));      //allocated memory for 3 char *

 while (scanf("%s", w) == 1 && c<3) {
      w_arr[c]=malloc(10*sizeof(**w_arr));    // allocate memory to each char *
      strcpy(w_arr,w);                        //copy string
    //printf("%s", w_arr[c]); debug print statement
      c++;
 }

然后在阅读后使用strcpy -

注意 - 将scanf更改为while (scanf("%9s", w) == 1) {,以避免在w中获得超过必需的字符数。

答案 4 :(得分:0)

您最好使用strdup并添加string.h

w_arr[c] = w;

要:

w_arr[c] = strdup(w);

并且strcpy不安全,您最好使用strncpy;