0

I have a basic algorithm i want to try out, and to do so i have a txt file with a number of inputs. To do so i redirect the stdin to my input.txt using the command, in the compiler: ./prog < input.txt. Here's the mentioned code:

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

void ExA(int n, int VALOR, int *sequencia){
  int i,j,z,soma;
  printf("%d - %d - %d\n",sequencia[0],sequencia[1],sequencia[2]);
  for(i=1; i<=n; i++){
    for(j=i; j<=n; j++){
      soma = 0;
      for(z=i; z<=j; z++){
        soma = soma + sequencia[j];
      }
      if(soma == VALOR){
        printf("SUBSEQUENCIA NA POSICAO %d\n", i);
        return;
      }
    }
  }
  printf("SUBSEQUENCIA NAO ENCONTRADA\n");
}


int main(void){
  int n, i, VALOR;
  int *sequencia = malloc(sizeof(int));
  char *buffer = malloc(sizeof(int) * 4);
  while(read(0, buffer ,sizeof(buffer))){
    sscanf(buffer,"%d %d",&n ,&VALOR);
    if(n == 0 && VALOR == 0){
      return 0;
    }
    else{
      for(i = 0; i<n; i++){
        read(0, buffer ,sizeof(buffer));
        sscanf(buffer,"%d",&sequencia[i]);
      }
    }
    ExA(n,VALOR,sequencia);
  }
  return 0;
}

The main function is responsible for reading from the input file and sending the values to the algorithm ExA. In my input.txt file i start with the following:

3 5
1
3
4
4 5
1
5
4
2

However when i print out my array (in the beginning of the ExA function) where the numbers should be stored it prints out 1 - 4 - 5 instead of the wanted 1 - 3 - 4

jonelearn
  • 13
  • 2
  • 9
  • 1
    Note that `read()` does not deal with strings — it does not add a null terminator to what it reads. You are, therefore, passing `sscanf()` a byte array and not a guaranteed (null terminated) string. Also, read pays no attention whatsoever to line breaks. It reads 4 or 8 bytes at a time (unless you're on a very unusual machine these days) because `sizeof(buffer)` is the size of a pointer.' – Jonathan Leffler Feb 11 '18 at 02:05
  • @JonathanLeffler well i changed both `read()` to `fgets()` in compliance to your comment. I noticed two things. The first is that when the printed result should be `1 - 3 - 4` it prints `0 - 1 - 3` basically adding a `0` from nowhere. Also when it exits `ExA` and resumes the `While` loop in the main the result is the same, that is, it reads the file from the beggining instead of continuing from where it left of. – jonelearn Feb 11 '18 at 02:20
  • See my edits to my answer — the code shown there isn't fully operational, but you have some explanations for what you see and guidelines on how to fix the remaining problems. – Jonathan Leffler Feb 11 '18 at 02:27

1 Answers1

2

Note that read() does not deal with strings — it does not add a null terminator to what it reads. You are, therefore, passing sscanf() a byte array and not a guaranteed (null terminated) string.

Also, read() pays no attention whatsoever to line breaks. It reads 4 or 8 bytes at a time (unless you're on a very unusual machine these days) because sizeof(buffer) is the size of a pointer. Assuming you have a 64-bit machine, the first read() processes the first 3 lines (3 5, 1, 3 — they happen to be 8 bytes long); the second read() gets the second 3 lines (4, 4 5, 1) and reports appropriately.

You should capture and test the return value from read(). You should print what it gets. (Partially fixed code — more work to be done to get the program fully working.)

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

static void ExA(int n, int VALOR, int *sequencia)
{
    int i, j, z, soma;
    printf("%d - %d - %d\n", sequencia[0], sequencia[1], sequencia[2]);
    for (i = 1; i <= n; i++)
    {
        for (j = i; j <= n; j++)
        {
            soma = 0;
            for (z = i; z <= j; z++)
            {
                soma = soma + sequencia[j];
            }
            if (soma == VALOR)
            {
                printf("SUBSEQUENCIA NA POSICAO %d\n", i);
                return;
            }
        }
    }
    printf("SUBSEQUENCIA NAO ENCONTRADA\n");
}

int main(void)
{
    int n, i, VALOR;
    int *sequencia = malloc(sizeof(int));
    char *buffer = malloc(sizeof(int) * 4);
    while (read(0, buffer, sizeof(buffer)))
    {
        sscanf(buffer, "%d %d", &n, &VALOR);
        if (n == 0 && VALOR == 0)
        {
            return 0;
        }
        else
        {
            for (i = 0; i < n; i++)
            {
                int nbytes = read(0, buffer, sizeof(buffer));
                printf("Read [%.*s]\n", nbytes, buffer);
                buffer[nbytes] = '\0';
                sscanf(buffer, "%d", &sequencia[i]);
            }
        }
        ExA(n, VALOR, sequencia);
    }
    return 0;
}

Given the input shown in the question, I get the output:

Read [4
4 5
1
]
Read [5
4
2
]
[]
4 - 5 - 5
SUBSEQUENCIA NA POSICAO 1

This much work cleans up the code — and explains some of the odd result you were getting. It doesn't make full use of the space allocated (which is bigger than sizeof(buffer), so the buffer[nbytes] = '\0'; assignment is within bounds of the array. It reads the same value repeatedly in the sscanf() call because you don't tell it to read from different locations in the string. If you need to read multiple values from a buffer using scanf(), read the answers about How to use sscanf() in a loop?

You should consider using fgets() or maybe POSIX getline() to read lines. If you're sure the data is clean, you could even use scanf() directly, but it is usually better to read lines and then parse them with sscanf().

If the exercise requires you to read with the read() system call, then you will have to work out a scheme where you read a buffer full of data and dole the contents out in chunks.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278