从标准输入读取到C数组

时间:2015-03-24 17:48:30

标签: c

输入

name number number

就像例子

bank 1 10

我需要将输入读入矩阵n行3列,如下一个示例

{ bank, 1, 10,  
  bank2, 2, 15,  
  bank3, 3, 20  }  

我的主要困难是阅读名称并存储到矩阵中。名称可以在1到41个字符之间变化。

我尝试按以下方式进行操作,但我不知道如何忽略输入中的空格以及如何使for循环仅计数直到读取该单词。

for (b=0; b<41;b++) {
    scanf("%s ",&nome[i]);
}
scanf("%d %d",&rating,&ref);
n[i][0] = *nome;
n[i][1] = rating;
n[i][2] = ref;

我刚开始用C学习编程,所以我不能在代码中使用高级内容。

3 个答案:

答案 0 :(得分:1)

您尝试一次读取一个字符串,但使用编辑描述符读取整个字符串。你试图让它变得比它需要的更难。

此外,术语“矩阵”通常被理解为表示所有相同类型的元素的二维数组,而听起来您想要包含不同类型成员的struct的一维数组。例如:

#define MAX_BANKS 10

struct bank {
    char nome[42];
    int rating;
    int ref;
};

struct bank banks[MAX_BANKS];
int num_banks = 0;

/* ... */

void read_banks(void) {
    while (num_banks < MAX_BANKS) {
        int fields;

        fields = scanf("%41s %d %d", banks[num_banks].nome,
                &banks[num_banks].rating, &banks[num_banks].ref);
        if (fields != 3) {
            /* handle error */
            break;
        } else {
            num_banks += 1;
        }
        /* ... */
    }
}

答案 1 :(得分:0)

在这个例子中,我已经解释了你的&#34;矩阵&#34;要求,使得输入的每一行填充具有不同字段类型的struct,因此我们最终得到struct的1-D数组,而不是不同数据类型的2-D数组

而不是从键盘输入数据,这在每次测试程序时都很无聊,我把数据放在一个文件中并从中读取 - 虽然技术非常相似。

此外,由于您的输入格式不一致,我已跳过任何不构成数据一部分的字符,请参阅delims

该程序可能比您希望的更复杂,但我希望它能帮助您做您想做的事情。当我决定不在struct中使用固定长度的字符串,而是指向字符串内存的指针(为可变长度字符串分配)时,复杂程度会上升。

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

typedef struct {
    char *nome;
    int rating;
    int ref;
    } customer;

void fatal(char *msg) {
    printf("%s\n", msg);
    exit (1);
    }

int main()
{
    FILE *fp;                                       // for fopen
    char line[1000];                                // for fgets
    char *delims = ", {}\t\r\n";                    // for strtok
    char *sptr;                                     // for strtok
    customer *mark = NULL;                          // an empty array
    int marks = 0;                                  // number of customers
    int len;                                        // length of input string
    fp = fopen("input.txt", "r");                   // open the file
    if (fp == NULL)                                 // did it open?
        fatal("Cannot open file");
    while (fgets(line, 1000, fp) != NULL) {         // each line of file
        mark = realloc(mark, sizeof(customer) * (marks+1));  // extend
        if (mark == NULL)
            fatal("Cannot extend array");           // failed extend the array

        sptr = strtok(line, delims);                // split first field
        if (sptr == NULL)
            fatal("Cannot get first field");
        len = strlen(sptr);                         // length of bank name
        mark[marks].nome = malloc(len+1);           // memory for the string
        if (mark[marks].nome == NULL)
            fatal("Cannot allocate string array");
        strcpy(mark[marks].nome, sptr);             // copy string to struct

        sptr = strtok(NULL, delims);                // split second field
        if (sptr == NULL)
            fatal("Cannot get second field");
        mark[marks].rating = atoi(sptr);            // extract number

        sptr = strtok(NULL, delims);                // split third field
        if (sptr == NULL)
            fatal("Cannot get third field");
        mark[marks].ref = atoi(sptr);               // extract number

        marks++;                                    // one more record
    }
    fclose (fp);

    // print the results (re-using len for convenience)
    for (len=0; len<marks; len++)
        printf("%s %d %d\n", mark[len].nome, mark[len].rating, mark[len].ref); 

    // release the data array
    for (len=0; len<marks; len++)
        free(mark[len].nome);
    free(mark);

    return 0;
}

输入文件:

{ bank, 1, 10,  
  bank2, 2, 15,  
  bank3, 3, 20  }  

节目输出:

bank 1 10
bank2 2 15
bank3 3 20

答案 2 :(得分:0)

由于您正在处理不同类型信息的集合(例如char*intint),因此收集此信息的正确方法是在结构中(或{ {1}})。关于如何为任何数组或结构数组创建空间,您有两种选择:(1)在堆栈上静态分配,或(2)在堆上动态分配。鉴于您的问题要求,静态分配是最基本的。但是,它不像动态分配数据那样灵活,而且您只能选择初始大小。

与存储数据一样,您可以选择如何从struct读取数据。作为一般命题,当从stdin读取时,首选方法是一次读取一行到缓冲区,然后解析缓冲区以获得所需内容。如上所述,行输入比将数据压缩为stdin格式字符串更灵活,但更复杂一些。出于此目的,我们将使用scanf,但请注意,使用scanfgetline的行输入可提供某些优势。

接下来,您可以只声明所需的结构数,或者可以花时间初始化每个结构中的所有值。 (这有你的优点,如下所示)。除了允许一些迭代技巧之外,初始化所有变量的主要原因是为了防止未初始化读取它们的可能性。读取未初始化的变量会导致未定义的行为fgets)。因此,请花点时间学习如何初始化每个变量类型。

话虽如此,你可以说有很多有效的方法可以解决任何问题。只要你正确地做到了,你如何做到这一点取决于你。这是另一种满足您要求的方法。请注意,代码顶部定义了最大名称长度bad和最大行数MAXNM。这使您可以在以后轻松调整值。如果您有任何问题,请与我联系:

MAXLN

<强>输入

#include <stdio.h>

#define MAXNM 41
#define MAXLN 100

typedef struct mix {
    char name[MAXNM + 1];
    int num1;
    int num2;
} mix;

int main (void) {

    /* initialize array of structs & variables */
    mix array[MAXLN] = {{ {0}, 0, 0 }};
    size_t i = 0;
    size_t read = 0;

    /* read array of struct contents from stdin */
    while (scanf ("%s %d %d", array[i].name, &array[i].num1, &array[i].num2) == 3) {
        i++;
        /* check if lines > MAXLN allowed */
        if (i >= MAXLN) {
            fprintf (stderr, "warning: lines read from stdin exceed MAXLN.\n");
            break;
        }
    }

    /* set the number of elements read to i */
    read = i;

    /* iterate over elements using 'read' */
    printf ("\nIterating array using 'while (i < read)'\n\n");
    i = 0;
    while (i < read) {
        printf (" array[%zu]  %-41s  %4d  %4d\n", i, array[i].name, array[i].num1, array[i].num2);
        i++;
    }

    /* iterate over array by virtue of initization of name to 0/null */
    i = 0;
    printf ("\nIterating array using 'while (array[i].name[0])'\n\n");
    while (array[i].name[0]) {
        printf (" array[%zu]  %-41s  %4d  %4d\n", i, array[i].name, array[i].num1, array[i].num2);
        i++;
    }

    printf ("\n");

    return 0;
}

<强>输出

$ ./bin/ptrarraystatic< DAT / staticstruct.txt

$ cat dat/staticstruct.txt
TheNamesofVaryingWidth 123 456
SomeOtherName 234 567
Bank_1 12 34
Bank_2 23 45
Bank_3 34 56
OneLastNameThatHasCloseToTheMaximumChars 777 9999