从stdin逐行读取

时间:2018-02-11 01:57:14

标签: c stdin

我有一个我想尝试的基本算法,为此我有一个txt文件,其中包含许多输入。为此,我使用编译器stdin中的命令将input.txt重定向到我的./prog < input.txt。这是提到的代码:

#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;
}

主函数负责从输入文件中读取并将值发送到算法ExA。在我的input.txt文件中,我从以下内容开始:

3 5
1
3
4
4 5
1
5
4
2

但是,当我打印出我应该存储数字的数组(在ExA函数的开头)时,它打印出1 - 4 - 5而不是想要的1 - 3 - 4

1 个答案:

答案 0 :(得分:2)

请注意read()不处理字符串 - 它不会为它读取的内容添加空终止符。因此,您传递sscanf()一个字节数组而不是保证(空终止)字符串。

此外,read()并不关注换行符。它一次读取4或8个字节(除非你这些天在一台非常不寻常的机器上),因为sizeof(buffer)是指针的大小。假设您有一台64位计算机,第一个read()处理前3行(3 513 - 它们恰好是8个字节长);第二个read()获得后三行(44 51)并进行适当报告。

您应该从read()捕获并测试返回值。你应该打印它得到的东西。 (部分修复的代码 - 要使程序完全正常工作还需要做更多的工作。)

#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;
}

鉴于问题中显示的输入,我得到输出:

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

这项工作清理了代码 - 并解释了一些你得到的奇怪结果。它没有充分利用分配的空间(大于sizeof(buffer),因此buffer[nbytes] = '\0';赋值在数组的范围内。它在sscanf()中重复读取相同的值调用,因为你没有告诉它从字符串中的不同位置读取。如果你需要使用scanf()从缓冲区读取多个值,请阅读关于How to use sscanf() in a loop?的答案

您应该考虑使用fgets()或POSIX getline()来读取行。如果您确定数据是干净的,您甚至可以直接使用scanf(),但通常最好先读取行,然后使用sscanf()解析它们。

如果练习要求您使用read()系统调用进行阅读,那么您将需要制定一个方案,在该方案中,您读取一个充满数据的缓冲区并以块的形式发送内容。