简体   繁体   中英

Parse char from int input in C

I am trying to display a matrix by taking input from a user. Here, the input is a lower triangular matrix and the user may enter the 'x' character which has to be replaced with INT_MAX . The below program is not working correctly as the output is not matching the expected one.


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


int read_int() {
    char input[30] = {0};
    int number;
    for (int i = 0; i < sizeof(input) - 1; i++){
        char c = (char)getc(stdin);
        if (c == 'x' || c == 'X')
            return INT_MAX;

        if (c < '0' || '9' < c){
            if (i == 0) continue;
            input[i] = 0;
            return atoi(input);
        }
        input[i] = c;
    }
    input[29] = 0;
    return atoi(input);
}

int main() { 
    int N = read_int();
    int matrix[N][N];
    memset(matrix, 0, N * N * sizeof(int));

    for(int i = 0; i < N; ++i){
        for(int j = 0; j <= i; ++j){
            int distance = read_int();
            matrix[i][j] = distance;
            matrix[j][i] = distance;
        }
    }

    printf("\n");
    for(int i = 0; i < N; ++i){
        for(int j = 0; j < N; ++j){
            printf("%d\t", matrix[i][j]);
        }
        printf("\n");
    }
    printf("\n");

    return 0; 
} 

For input:

3
x 2
x x 2

The Above program prints:

3           2147483647  2147483647
2147483647  32          2147483647
2147483647  2147483647  32

which is not expected It should be

3           2147483647  2147483647
2147483647  2            2147483647
2147483647  2147483647  2

Update: The answers below, doesn't work for all case [except accepted one]

One such case is -

5
10
50 20
30 5 30
100 20 50 40
10 x x 10 50

it just keeps on taking input

Your logic for skipping whitespace is broken because when you eventually assign a character after skipping position 0, you will always be writing a "wanted" character at position i . That means anything already in position 0 remains.

In your case, it's undefined behavior because input[0] was originally filled with 3 on the first input where no whitespace was skipped, but in subsequent calls to your function it is uninitialized. You then go on to write a 2 into input[1] and thus by pure chance (your array from previous calls has not been overwritten on the stack and the stack is the same), you end up with the string "32" sitting in input .

What you need to do is have some way to count the actual required characters so that you write them into the array at the correct position. One naive approach would be:

int pos = 0;

for(...) {
    // other logic...

    // Actually write a character we want
    input[pos++] = c;
}

Another way that is more like how integer input works is:

int c;
int pos = 0;
while(pos < sizeof(input) - 1 && (c = getc(stdin)) != EOF)
{
    if (c == 'x' || c == 'X')
        return INT_MAX;
    else if (pos == 0 && isspace(c))
        continue;
    else if (!isdigit(c) && !(pos == 0 && (c == '-' || c == '+')))
        break;
    input[pos++] = c;
}
input[pos] = '\0';
return atoi(input);

I think the problem is this part of the loop:

    if (c < '0' || '9' < c){
        if (i == 0) continue;
        input[i] = 0;
        return atoi(input);
    }

If you have entered 3 enter x 2 as your input, then the 3 gets read successfully, and the the x gets returned as INT_MAX as intended, but in the next call to read_int , the next character in the input sequence is a space (ie c == ' ' ), and therefore it branches here. Since i == 0 at this point, the loop continues, which means i is incremented to 1, but this also means that input[0] is never changed. Most likely, input[0] contains the same value from the previous call to read_int (3), but in any case, it's undefined behaviour.

As a quick alternative, you can simply change this condition to:

if (c != ' ' && (c < '0' || '9' < c)){

This will mean input[0] will be set to a space character, which atoi will ignore.

An alternative solution could be to read in an entire line at once and tokenise the line.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM