Sequence reading of space-separated numbers

Asked

Viewed 6,535 times

2

It is necessary to read only a line with a space-separated set of integers, each space-separated item will be inserted in a linked list: 1 41 2 15 6 7 87 4 2 1 9 0

List would be something like = [1, 41, 2, 15, 6, 7, 87, 4, 2, 1, 9, 0]

Example:

$ gcc example.c -o example -g -Wall 
$ ./example 
1 41 2 15 6 7 87 4 2 1 9 0<enter>

The biggest problem is that the amount of numbers that will come in the input is undefined, ie the input can also be: 1 8 6

Lista = [1, 8, 6]

Because the amount is undefined, I thought of two possible solutions:

  • to) scanf ("%[^\n]%*c", sequenciaNumeros);
  • b) Use fgets

In both cases, I would have to the problem of declaring a huge character vector to ensure it does not reach the limit.

If the quantity were set it would be simple:

scanf("%d %d %d, &valor1, &valor2, &valor3)

It is possible with the scanf take this line and be able to manipulate each of the numbers (which are separated by space) to add to the list, knowing the amount of numbers may vary? The input is only one row of a set of numbers separated by space

  • 1

    has other possibilities, such as making 2 readings, one counting the items, and the other allocating and capturing.

  • @Bacco It is necessary to do the reading at once, it is not possible to count and then read.

  • 1

    Is it a rule of utterance? It would be good to put in question tb. About what you said about allocating, you don’t need to allocate a huge space, you can go allocating with leftovers, and relocating if it doesn’t fit. 1-in-1 is a lot of silly allocation, but you don’t have to predict that they all fit.

  • 1

    @Bacco The statement has several pages and rules, will end up escaping the scope of the question. The entry must be like this with only one line.

  • 1

    You run the risk of someone responding and not playing by the rules, and then people waste their time and not serve you. It would be nice to see if there’s no more "prank" like that, and at least mention it. If I stopped to help you with code and you told me about it later, I imagine I’d be very unhappy. It can happen to other people. If you describe the important details all, you will get better answers.

  • The question is not good, perhaps because it has an artificial requirement that does not help to have a good code. That is why the answers so far command to do otherwise than what is stated (at least what you can understand about it). The answers are good to solve the problem the way everyone would solve it, they just don’t solve it the way asked by the question, which is a weird way.

  • @bigown I edited the question again. I don’t know if the input way is hard to be manipulated or I’m used to simple entries.

  • I think the question is clear, the requirement is that it doesn’t make much sense, as Bacco said. I think that because of this the people who decided to answer preferred not to pay attention to him because they were something out of the ordinary and were in what is intuitive to do.

  • 1

    In fact, the fact that the input is in "one line" does not change anything when the reading is done using scanf.

  • I don’t know if you understood what I called two readings. I speak two readings inside the typed string once. The first counting how many numbers, and the second reading the values. Depending on what technique is used to read, of course. It only makes sense to treat the line as one thing.

  • "Interpreting" the requirements, what is probably being asked is something like this: "read a sequence of integer numbers separated by spaces etc...". In the terminal, in the example above, after <enter> (or instead of <enter>) there would be a control-d or control-z to finish reading the integers.

Show 6 more comments

3 answers

1


You can use the scanf(), for with it it is possible to distinguish the numbers between themselves.

To solve your problem, one possible way is read a number at a time and at each reading, dynamically allocate enough memory to read that number, using malloc(). For this you would need a structure that expands its size dynamically. This avoids the problem of:

  1. Statically allocate too small a vector and fail to store all data.
  2. Statically allocate a very large vector, wasting space in memory.

A data structure that assists you in this is a chain list. An alternative can be a dynamically sized array.

Either way you need to define an end identifier. Some character will dictate when the sequence ends. If it is a sequence of integer numbers, you can use a negative character to indicate the end of the sequence. For example, -1. Or EOF.

However, perhaps the following reflection should be made here: it is necessary for all the numbers to be in memory at once?

A very simple example to illustrate this scenario is a accumulator.

Setting: Imagine being asked a program to add up all the numbers the user enters.
Solution: One approach is to store everyone in memory and then iterate on them by adding them up. A simpler approach would be, just to make an accumulator:

soma = soma + numero_da_entrada;

I hope I’ve helped!

Issue 1: Apparently, you can use the return of scanf() to know when there are no more numbers to read:

int numero;
while(scanf("%d", &numero) == 1) { // scanf retorna 1 quando a leitura for bem sucedida
    printf("%d", numero);
}

Issue 2: To read the entire line and stop when press enter:

int numero;
char proxChar;
while(scanf("%d%c", &numero, &proxChar) == 2) { 
        printf("%d", numero);
        if(proxChar == '\n') break; 
}
  • The biggest problem is: How to read and distinguish all numbers from a single line with scanf? It is not possible to read one at a time with a for loop. For example: send 1 and enter, send 6 and enter etc.

  • When you single-line Liz, what do you mean by that? If it’s from stdin there is no concept of line. In this case, scanf will understand spaces and line breaks as number separators in case you use the mask %d.

  • Edited question

  • 1

    The answer still applies.

  • 1

    The scanf will store the entire line, right? If so, how will I give the malloc when it has already burst in size? If not, how will I read number by number without asking the user to type again? It is not clear to me what the manipulation of the scanf will be like

  • The scanf("%d", ...) nay will save the entire line! If you involve the scanf() in a loop while, on each call it will return you the next integer, until there is no more.

  • 1

    Thank you, I’ve always gotten used to doing "normal" scan readings and didn’t even know your return.

Show 2 more comments

1

Read only one number at a time. The result of scanf will then be 1 if reading was successful, or zero if failed, and in this case the line was read completely.

For each number read, allocate space dynamically with malloc. Use a chained list to store read numbers.

0

You can use the fgets to take the entrance and strtok to break into pieces:

char entrada[100];   // Para obter até 100 caracteres da entrada
int * elementos[10]; // Array com capacidade para 10 elementos
int i = 0;

int tamanhoArray = sizeof elementos / sizeof(int);

if(fgets(entrada, sizeof entrada, stdin) != NULL) {
    for (char *pedaco = strtok(entrada, " "); pedaco != NULL; pedaco = strtok(NULL, " ")) {

        // Se atingir a capacidade do array
        if (i >= tamanhoArray) {
            puts("Não foi possível adicionar mais itens na lista!");
            break;
        }
        elementos[i++] = pedaco;
    }

    for (int n = 0; n < tamanhoArray; ++n) {    
        printf("Indice [%d] = %s\n", n, elementos[n]);
    }
} 

See DEMO

If you prefer to create the array with size based on the number of spaces:

char entrada[100];  // Para obter até 100 caracteres da entrada
int qtdEspacos = 1;
int i = 0;

if(fgets(entrada, sizeof entrada, stdin) != NULL) {
    char *ptr = entrada;

    while((ptr = strchr(ptr, ' ')) != NULL) { // Se encontrou espaço
        qtdEspacos++;
        ptr++;
    }

    // Cria o array com tamanho baseado na quantidade de espaços na string
    int * elementos[qtdEspacos];

    for (char *pedaco = strtok(entrada, " "); pedaco != NULL; pedaco = strtok(NULL, " ")) {
        elementos[i++] = pedaco;
    }

    for (int n = 0; n < qtdEspacos; ++n) {    
        printf("Indice [%d] = %s\n", n, elementos[n]);
    }
}

See DEMO

Browser other questions tagged

You are not signed in. Login or sign up in order to post.