如何在C中将字符串输入到数组中?

时间:2017-01-07 05:11:30

标签: c arrays string pointers

我试图从用户那里获取输入(字符串)并将它们存储在一个数组中。但是在运行此代码后,程序立即崩溃。

#include <stdio.h>
int main() {
    int i;
    char *word[3];
    for(i=0;i<3;i++)
    {
        printf(" Enter a word: ");
        scanf("%s", &word[i]);
    }
    printf("%s ", word[0]);
    return 0;
}

6 个答案:

答案 0 :(得分:4)

在这一行:

scanf("%s", &word[i]);

您需要确保word[i]指向某处,并且有足够的空间来占用输入的字符串。由于word[i]char *指针,因此您需要在某个时候为此分配内存。否则,它只是一个悬垂的指针,不指向任何地方。

如果您想坚持使用scanf(),那么您可以预先使用malloc分配一些空格。

  

malloc()在堆上分配请求的内存,然后在末尾返回void*指针。

您可以在代码中应用malloc(),如下所示:

size_t malloc_size = 100;

for (i = 0; i < 3; i++) {
    word[i] = malloc(malloc_size * sizeof(char)); /* allocates 100 bytes */
    printf("Enter word: ");
    scanf("%99s", word[i]); /* Use %99s to avoid overflow */
                            /* No need to include & address, since word[i] is already a char* pointer */
} 

注意:必须检查malloc()的返回值,因为失败时它可以返回NULL

此外,无论何时使用malloc()分配内存,都必须使用free在最后解除所请求的内存:

free(word[i]);
word[i] = NULL; /* safe to make sure pointer is no longer pointing anywhere */

没有scanf的另一种方法

读取字符串的更合适的方法应该是fgets

  

char *fgets(char *str, int n, FILE *stream)从输入流中读取一行,并将字节复制到char *str,其大小必须为n个字节,作为它可占用的空间阈值。

有关fgets的注意事项:

  • 在缓冲区末尾添加\n个字符。可以轻松删除。
  • 出错时,返回NULL。如果没有读取任何字符,最后仍会返回NULL
  • 必须使用给定大小n静态声明缓冲区。
  • 读取指定的流。来自stdinFILE *

以下是如何使用stdin读取输入行的示例:

char buffer[100]; /* statically declared buffer */

printf("Enter a string: ");
fgets(buffer, 100, stdin); /* read line of input into buffer. Needs error checking */

带注释的示例代码:

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

#define NUMSTR 3
#define BUFFSIZE 100

int main(void) {
    char *words[NUMSTR];
    char buffer[BUFFSIZE];
    size_t i, count = 0, slen; /* can replace size_t with int if you prefer */

    /* loops only for three input strings */
    for (i = 0; i < NUMSTR; i++) {

        /* read input of one string, with error checking */
        printf("Enter a word: ");
        if (fgets(buffer, BUFFSIZE, stdin) == NULL) {
            fprintf(stderr, "Error reading string into buffer.\n");
            exit(EXIT_FAILURE);
        }

        /* removing newline from buffer, along with checking for overflow from buffer */
        slen = strlen(buffer);
        if (slen > 0) {
            if (buffer[slen-1] == '\n') {
                buffer[slen-1] = '\0';
            } else {
                printf("Exceeded buffer length of %d.\n", BUFFSIZE);
                exit(EXIT_FAILURE);
            }
        } 

        /* checking if nothing was entered */
        if (!*buffer) {
            printf("No string entered.\n");
            exit(EXIT_FAILURE);
        }

        /* allocate space for `words[i]` and null terminator */
        words[count] = malloc(strlen(buffer)+1);

        /* checking return of malloc, very good to do this */
        if (!words[count]) {
            printf("Cannot allocate memory for string.\n");
            exit(EXIT_FAILURE);
        }

        /* if everything is fine, copy over into your array of pointers */
        strcpy(words[count], buffer);

        /* increment count, ready for next space in array */
        count++;
    }  

    /* reading input is finished, now time to print and free the strings */
    printf("\nYour strings:\n");
    for (i = 0; i < count; i++) {
        printf("words[%zu] = %s\n", i, words[i]);
        free(words[i]);
        words[i] = NULL;
    }

    return 0;
}

示例输入:

Enter a word: Hello
Enter a word: World
Enter a word: Woohoo

输出:

Your strings:
words[0] = Hello
words[1] = World
words[2] = Woohoo

答案 1 :(得分:2)

这个领域似乎有些混乱。您的主要问题是您尝试将每个单词写入地址您使用char *word[3];声明的每个指针。 (更不用说你没有在每个指针所指向的位置分配存储空间 - 但是当你尝试用&word[i]写入每个指针的地址时,你永远不会到达那里,而不是到指针本身)

虽然您可以使用scanf,但很快就会遇到许多陷阱中的一个,因为scanf用户输入会困扰所有新的C程序员(例如无法处理{{1}在输入缓冲区中留下无法处理字符串中的空格无法限制读/写字符数无法验证读取或处理EOF 等......

更好的方法是简单地使用'\n',然后修剪fgets 读取的'\n',并在其存储字符串的缓冲区中包含。一个简单的例子是:

fgets

通过在输入期间生成#include <stdio.h> #include <string.h> #define NWDS 3 /* declare a constant for the maximum number of words */ int main (void) { int i, n = 0; char word[NWDS][50] = { "" }; /* provide storage or allocate */ for (i = 0; i < NWDS; i++) { /* for a max of NWDS */ printf ("Enter word : "); /* prompt */ if (!fgets (word[i], sizeof word[i], stdin)) /* read/validate */ break; /* protect against EOF */ size_t len = strlen (word[i]); /* get length */ if (word[i][len-1] == '\n') /* check for trailing '\n' */ word[i][--len] = 0; /* overwrite with nulbyte */ } n = i; /* store number of words read */ putchar ('\n'); /* make it pretty */ for (i = 0; i < n; i++) /* output each word read */ printf (" word[%d] : %s\n", i, word[i]); #if (defined _WIN32 || defined _WIN64) getchar(); /* keep terminal open until keypress if on windows */ #endif return 0; } (在Linux上 ctrl + d 或在windoze上 ctrl + z ),随时取消输入,你被覆盖。

示例使用/输出

EOF

仔细查看,考虑其他答案,如果您有其他问题,请与我们联系。

答案 2 :(得分:0)

char *word[3]; // <-- this is an array of 3 dangling pointers, of type char*
// they still point nowhere, we later need to set them to some allocated location.
 ...
 for(i=0;i<3;i++) {
     word[i] = malloc(some_max_size * sizeof(char)); // <-- allocate space for your word
     printf(" Enter a word: ");
     scanf("%s", word[i]); // <-- not &word[i]; word[i] is already a char* pointer
 }

答案 3 :(得分:0)

您将单词声明为指针数组(char * word [3];)。您必须分配内存来存储数据。在分配值之前,使用malloc或类似函数分配内存。

答案 4 :(得分:0)

是的,代码崩溃是因为声明了一个字符数组 指针是不够的,你需要设置指向指针 记忆字符串的存储位置。

E.g。

const int maxLen = 32;
char* word[3] = {NULL,NULL,NULL};

word[i] = malloc(maxLen);

然后从键盘读取字符串,以确保字符串不是太多 长期使用fgets和maxLen:

printf("Enter a word:");
fgets(word[i],maxLen,stdin);

答案 5 :(得分:-2)

代码char *word[3]创建了一个3元素的指针数组!

看,你基本上已经创建了一个指针的字符数组,所以你不能放一个&#34;字符串&#34;进入每一个,因为指针变量的类型是长十六进制。