【问题标题】:How to count amount of elements in a row of a matrix in C如何计算C中矩阵行中的元素数量
【发布时间】:2016-06-10 08:14:48
【问题描述】:

使用整数数组,我想首先询问用户他想要在数组中的行数和列数(我们称它们为 x 和 y)(我知道如何执行此步骤)。重要的是,当用户输入将存储在矩阵中的值时,将从一行输入中读取一行,从第二行输入中读取第二行,依此类推。所以一行输入=1 行。

因此,如果他定义了 x 个列,他应该在第一行输入 x 个数字,全部在一行上。我如何检查是否确实在行上输入了 x 个数字?如果输入更少或更多,我将打印一条错误消息。是否有某种命令可以检查 1 行的大小,以便根据用户定义的 x 检查它?

到目前为止,我编写的代码涉及简单的步骤,但我对如何实施此检查以确认用户输入的输入量与他最初定义的输入量几乎没有什么联系。

非常感谢!

【问题讨论】:

  • 分享所写的代码。
  • 如果您使用scanf,则“行”不需要匹配。空格被忽略,因此可以根据需要通过空格或换行符分隔来输入值。如果在按下Enter 之前为一行输入了太多值,它们将被缓冲以准备下一行。如果您想坚持输入一行,请使用fgets,然后使用sscanf,但您让我们猜测
  • 请注意,scanf 系列函数返回成功输入的字段数。您应该始终检查该结果。
  • 探索fgetsstrtok,在提取的令牌上使用sscanf
  • fgetsstrtolstrtol 函数采用 endptr 允许您移动行中的下一个数字。

标签: c arrays matrix input limit


【解决方案1】:

这使用一个函数来获取一个范围内的整数,另一个函数来获取一系列整数。 strtol 用于解析使用fgets 获得的输入中的值。

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

//inputs
// char *line : pointer to text to be parsed
// char **next : pointer to pointer to allow modification of caller's pointer
// char *term : pointer to characters to be considered terminators
// int *value : pointer to int to allow modification of caller's int
// int min : minimum value of range
// int max : maximum value of range
// returns : 0 failure or 1 success
int get_int_range ( char *line, char **next, char *term, int *value, int min, int max)
{
    long int input = 0;
    char *end = NULL;//will point to end of parsed value

    errno = 0;
    input = strtol ( line, &end, 10);//get the integer from the line. end will point to the end of the parsed value
    if ( end == line) {// nothing was parsed. no digits
        printf ( "input MUST be a number\n");
        return 0;// return failure
    }
    // *end is the character that end points to
    if ( *end != '\0' && ( strchr ( term, *end) == NULL)) {// is *end '\0' or is *end in the set of term characters
        printf ( "problem with input: [%s] \n", line);
        return 0;
    }
    if ( ( errno == ERANGE && ( input == LONG_MAX || input == LONG_MIN))
    || ( errno != 0 && input == 0)){// parsing error from strtol
        perror ( "input");
        return 0;
    }
    if ( input < min || input > max) {// parsed value is outside of range
        printf ( "input out of range %d to %d\n", min, max);
        return 0;
    }

    if ( next != NULL) {// if next is NULL, caller did not want pointer to end of parsed value
        *next = end;// *next allows modification to caller's pointer
    }
    *value = input;// *value allows modification to callers int
    return 1;// success
}

//inputs
// int cols : needed to pass in the variable length array
// int dest[][cols] : variable length array to be modified with parsed values
// int inputrow : row of the variable length array to be modified
// int min : mininum value of range
// int max : maximum value of range
// char *line : pointer to text to be parsed
// char *term : pointer to characters to be considered terminators
// returns : 0 failure or 1 success
int get_int_series ( int cols, int dest[][cols], int inputrow, int min, int max, char *line, char *term)
{
    char *end = NULL;// will point to end of parsed value
    char *each = NULL;// will point to start of parsed value
    int valid = 0;
    int input = 0;
    int count = 0;
    int temp[cols];// temporary storage for parsed values

    each = line;// each points to start of line
    do {
        valid = get_int_range ( each, &end, term, &input, INT_MIN, INT_MAX);// call to parse one value
        if ( !valid) {// failure
            printf ( "input MUST be a number\n");
            return 0;
        }
        if ( valid) {// success
            temp[count] = input;// save parsed value in temporary array
            count++;
            if ( count > cols) {
                printf ( "too many integers. %d entered. only enter %d\n", count, cols);
                return 0;
            }
        }
        // *end is the character that end points to
        while ( *end && strchr ( term, *end)) {// if *end not '\0' and *end is in the set of term characters
            end++;// yes. advance end one position
        }
        each = end;// set the end pointer to be the new starting pointer
    } while ( end && *end);// keep looping the above while end is not NULL and *end is not '\0' 

    if ( count < cols) {
        printf ( "too few integers. need %d entered. only entered %d\n", cols, count);
        return 0;
    }
    while ( count) {
        count--;
        dest[inputrow][count] = temp[count];// set the values in the callers array to the values in the temporary array
    }
    return 1;// success
}

int main( int argc, char *argv[])
{
    char line[900] = {'\0'};
    int valid = 0;
    int rows = 0;
    int cols = 0;
    int eachrow = 0;
    int eachcol = 0;

    do {
        printf ( "Enter number of array rows or quit\n");
        fgets ( line, sizeof ( line), stdin);//read a line
        if ( strcmp ( line, "quit\n") == 0) {
            return 1;// if quit is entered, exit the program
        }
        valid = get_int_range ( line, NULL, "\n", &rows, 0, INT_MAX);// call to parse a value
    } while ( !valid);// on failure, keep looping the above

    do {
        printf ( "Enter number of array columns or quit\n");
        fgets ( line, sizeof ( line), stdin);//read a line
        if ( strcmp ( line, "quit\n") == 0) {
            return 1;
        }
        valid = get_int_range ( line, NULL, "\n", &cols, 0, INT_MAX);
    } while ( !valid);

    //once the size is obtained, the variable length array can be declared
    int array[rows][cols];

    for(eachrow = 0; eachrow < rows; eachrow++) {// loop through the rows
        do {
            printf ( "Enter %d integers for row %d or quit. Ex 1 2 3\n", cols, eachrow + 1);
            fgets ( line, sizeof ( line), stdin);//read a line
            if ( strcmp ( line, "quit\n") == 0) {
                return 1;
            }
            valid = get_int_series ( cols, array, eachrow, INT_MIN, INT_MAX, line, " \n");// call to obtain a series of values
        } while ( !valid);// on failure, keep looping the above
    }
    // show the values in the variable length array
    for(eachrow = 0; eachrow < rows; eachrow++) {
        for(eachcol = 0; eachcol < cols; eachcol++) {
            printf("[%d] ", array[eachrow][eachcol]);
        }
        printf("\n");
    }
    printf("\nDone\n");

    return 0;
}

【讨论】:

  • 非常感谢您的回复。您能否简要解释一下您的功能是如何工作的?我不确定我是否完全理解阅读代码。例如为什么列或数组的数量被读取为字符而不是整数?
  • 你能不能解释一下“**next”指针的作用。我很难理解它在 range 函数中究竟做了什么。
【解决方案2】:

这是另一种解决方案,尽管根据您的具体要求,另一个答案比我的要好。

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

int main(void)
{
    int number_of_rows;
    int number_of_columns;

    printf("Enter the number of rows: ");
    scanf("%d", &number_of_rows);
    printf("Ok, enter the number of columns: ");
    scanf("%d", &number_of_columns);

    int matrix[number_of_rows][number_of_columns];

    int i;
    int j;

    for(i = 0; i < number_of_rows; ++i) {
        printf("This is %d row.\n", i+1);
        for(j = 0; j < number_of_columns; ++j) {
            scanf("%d", &matrix[i][j]);
        }
    }

    /* Print's the 2D array. */
    for(i = 0; i < number_of_rows; ++i) {
        printf("\n");
        for(j = 0; j < number_of_columns; ++j) {
            printf("%d   ", matrix[i][j]);
        }
        printf("\n");
    }

    return 0;
}

它的作用是询问用户用户希望矩阵(二维数组)具有的行数和列数,然后根据这些数字声明一个二维数组。然后它遍历每一行,在遍历每一列之前将行号打印到控制台。初始化二维数组后,它会以绘制矩阵的方式打印二维数组。我希望这会有所帮助。

【讨论】:

    【解决方案3】:

    因为你想一次读一行,你应该使用fgets,它就是这样做的。然后您可以使用strtok 用空格/制表符分隔行并尝试将每个值转换为 int。如果您在该行被填充之前用完了数字,或者在该行被填充后仍有更多数字,那么您可以提醒用户。

    这是一个简单的例子:

    void read_array(int **array, int rows, int cols)
    {
        char line[100];
        int i,count;
        char *p;
    
        for (i=0;i<rows;i++) {
            printf("enter row %d: "), i-1);
            fgets(line, sizeof(line), stdin);
            count = 0;
            p = strtok(line, " \t");
            while (p && (count < cols)) {
                matrix[i][count++] = atoi(p);
                p = strtok(NULL, " \t");
            }
            if (count < cols) {
                printf("too few values\n");
                i--;
                continue;
            } else if (p) {
                printf("too many values\n");
                i--;
                continue;
            }
        }
    }
    

    【讨论】:

    • 所以你建议使用 char 数组?我只是以相同的方式声明一个 char 数组吗?只需“char matrix[20][20];”例如?
    • @stellarhawk34 鉴于您将询问用户行数和列数,您应该动态分配该内存。您应该将其定义为int **,为行调用一次malloc,然后为每一行调用malloc
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-22
    • 1970-01-01
    • 2021-01-01
    • 1970-01-01
    相关资源
    最近更新 更多