Taking user input and storing it in an array of strings in C

时间:2015-05-24 21:38:05

标签: c arrays

I'm new to C and trying to write a command line application that does a whole host of things based on the user input. I need to run the program on an infinite loop and read user input into a string array.

I've used the while loop to write it into a string.

while(fgets(str, 256, stdin)){

}

Now I'm a little confused about how to modify this loop to write strings into an array directly using space as a delimiter.

So if I've an input

Terminate client 2345

The array should have 3 elements with the first being Terminate. Any help appreciated.

2 个答案:

答案 0 :(得分:3)

无论您是从stdin读取还是从文件中读取,该过程基本相同。您可以使用面向行的输入(fgetsgetline)阅读每一行,也可以使用面向字符的输入(getcharfgetc等)。 (scanf家族在中间)。阅读时,通常最好的选择是面向行的输入。

当将用户输入读入数组时,您有两种选择,要么声明一个静态指针数组,并希望您分配足够的指针开始,要么动态根据需要分配指针数组realloc以保存所有输入。 (谁知道,用户可能会重定向文件以供阅读)。当您动态分配任何内容时,您负责跟踪其使用,保留指向内存块原始起始地址的指针,并在不再需要时free内存。

以下是从stdin获取输入并将其存储在动态分配的数组中的标准示例。有一个扭曲。代码可以处理来自文件stdin的输入。如果给出一个文件名作为第一个参数,那么它将读取该文件,否则它将从stdin读取。它希望用户提供所需的输入,然后在完成后按[ctrl+d]。 (手动生成EOF)。

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

#define NMAX 128

int main (int argc, char **argv) {

    char *ln = NULL;                /* NULL forces getline to allocate  */
    size_t n = 0;                   /* initial ln size, getline decides */
    ssize_t nchr = 0;               /* number of chars actually read    */
    size_t idx = 0;                 /* array index counter              */
    size_t nmax = NMAX;             /* check for reallocation           */
    char **array = NULL;            /* array to hold lines read         */
    FILE *fp = NULL;                /* file pointer to open file fn     */

    if (argc > 1) {
        if (!(fp = fopen (argv[1], "r"))) {
            fprintf (stderr, "error: file open failed for '%s'\n", argv[1]);
            return 1;
        }
    }
    else
        fp = stdin;

    /* allocate NMAX pointers to char* */
    if (!(array = calloc (NMAX, sizeof *array))) {
        fprintf (stderr, "error: memory allocation failed.");
        return 1;
    }

    if (fp == stdin)
        printf ("\nEnter information to store in array on each line, [ctrl+d] when done:\n\n");

    /* read each line from file or stdin - dynamicallly allocated   */
    while ((nchr = getline (&ln, &n, fp)) != -1)
    {
        /* strip newline or carriage rtn    */
        while (nchr > 0 && (ln[nchr-1] == '\n' || ln[nchr-1] == '\r'))
            ln[--nchr] = 0;

        array[idx] = strdup (ln);   /* allocate/copy ln to array        */

        idx++;                      /* increment value at index         */

        if (idx == nmax) {          /* if lines exceed nmax, reallocate */
            char **tmp = realloc (array, nmax * 2 * sizeof *tmp);
            if (!tmp) {
                fprintf (stderr, "error: memory exhausted.\n");
                break;
            }
            array = tmp;
            nmax *= 2;
        }
    }

    if (ln) free (ln);              /* free memory allocated by getline */
    if (fp != stdin) fclose (fp);   /* close open file descriptor       */

    size_t i = 0;

    /* print array */
    printf ("\nThe lines in the file are:\n\n");
    for (i = 0; i < idx; i++)
        printf (" line[%3zu] : %s\n", i, array[i]);

    /* free array */
    for (i = 0; i < idx; i++)
        free (array[i]);
    free (array);

    return 0;
}

示例/输出

$ ./bin/getline_readstdin_dyn

Enter information to store in array on each line, [ctrl+d] when done:

This is a line of input
This is another
and another
etc..

The lines in the file are:

 line[  0] : This is a line of input
 line[  1] : This is another
 line[  2] : and another
 line[  3] : etc..

或从文件中读取:

$ ./bin/getline_readstdin_dyn dat/ll_replace_poem.txt

The lines in the file are:

 line[  0] : Eye have a spelling chequer,
 line[  1] : It came with my Pea Sea.
 line[  2] : It plane lee marks four my revue,
 line[  3] : Miss Steaks I can knot sea.
 line[  4] : Eye strike the quays and type a whirred,
 line[  5] : And weight four it two say,
 line[  6] : Weather eye am write oar wrong,
 line[  7] : It tells me straight aweigh.
 line[  8] : Eye ran this poem threw it,
 line[  9] : Your shore real glad two no.
 line[ 10] : Its vary polished in its weigh.
 line[ 11] : My chequer tolled me sew.
 line[ 12] : A chequer is a bless thing,
 line[ 13] : It freeze yew lodes of thyme.
 line[ 14] : It helps me right all stiles of righting,
 line[ 15] : And aides me when eye rime.
 line[ 16] : Each frays come posed up on my screen,
 line[ 17] : Eye trussed too bee a joule.
 line[ 18] : The chequer pours over every word,
 line[ 19] : Two cheque sum spelling rule.

重定向输入也很好。 E.g:

$ ./bin/getline_readstdin_dyn < dat/ll_replace_poem.txt

答案 1 :(得分:0)

At the risk of advising parse kludge, you have your read loop. Now use strtok or sscanf to parse string by tokens into storage variables. In this setup I suspect strdup is the better choice.