C 함수를 호출하고 데이터를 .txt 파일로 리디렉션하는 Unix 쉘 스크립트 작성

C 함수를 호출하고 데이터를 .txt 파일로 리디렉션하는 Unix 쉘 스크립트 작성

저는 쉘 스크립팅을 처음 접했습니다. 나는 C 프로그램을 호출하는 Unix 스크립트를 작성 N= 2^{i}하고 i= 1,2 ....20이 데이터를 파일에 기록하고 싶습니다.

(이 프로그램은 C에서 사다리꼴 법칙을 사용하여 정적분을 계산하고 각 항 N에 대한 반복 결과와 오차를 반환합니다.)

처음 C를 배우기 시작했을 때 사다리 규칙에 대한 코드를 작성했습니다.

#include<stdio.h>

#include<math.h>
#define PI 3.14159265358979323846

float fn(float x)
{ 
  float integrand;
  integrand = (1.0/(1.0+x*x));
  return integrand;
}
int main()
{
  int i,N;
  float a,b,sum=0,result=0,h;
  float error;


  printf("Enter the no of equally spaced points =");
  scanf("%d",&N);
  printf("Enter the lower limit=");
  scanf("%f",&a);
  printf("Enter the upper limit=");
  scanf("%f",&b);
  h=(b-a)/(N-1);
  for(i=1;i<=N;i++)
  {
    sum=sum+fn(a+i*h);
    result=(fn(a)+fn(b)+2*sum)*h/2;
    error = fabs((atan(b)-atan(a))-result);
    //error = PI/2.0 - result;

    printf("N=%d result=%f error=%f\n", i, result, error);
  }
  printf("final result =%f\n", result);
  printf("cumulative error =%f\n", error);

}

나는 다음을 통해 이 코드를 실행한다.

gcc -o err.o trap_error.c -lm

내 gcc 버전은gcc (Ubuntu 5.4.0-6ubuntu1~16.04.2) 5.4.0 20160609

온라인에서 무작위로 검색했지만 유용한 정보를 찾지 못했습니다. 코드도 수정해야 할 것 같습니다. Unix 스크립트를 작성하고 출력을 파일로 리디렉션하는 데 도움을 주신다면 .txt. 설명이 포함된 Unix 스크립트가 매우 도움이 될 것입니다.

답변1

사용자에게 메시지를 표시하고 표준 입력에서 인수를 읽는 대신 수락해야 합니다.유닉스 철학, 대신 명령줄 매개변수를 사용하세요.

아래 예제는 내가 선호하는 매개변수 검사 기능을 보여주고 싶었기 때문에 약간 깁니다. scanf()함수 계열은 오버플로를 확인하지 않으므로 strto*()사용해야 합니다. 또한 때로는 숫자 뒤에 정크가 있을 수 있으며(예: "12l" - 마지막 문자는 "121" 대신 문자 L임), 개인적으로 이를 캡처하고 싶습니다.

#include <stdlib.h>
#include <locale.h>
#include <ctype.h>
#include <stdio.h>
#include <errno.h>

/* Helper function to parse a double.
 * Returns 0 if successful, nonzero otherwise.
*/
static int parse_double(const char *s, double *v)
{
    const char *end;
    double      val;

    if (!s)
        return errno = EINVAL;

    end = s;
    errno = 0;
    val = strtod(s, (char **)&end);
    if (errno)
        return errno;

    if (!end || end == s)
        return errno = EINVAL;

    while (*end != '\0' && isspace(*end))
        end++;

    if (*end != '\0')
        return errno = EINVAL;

    if (v)
        *v = val;

    return 0;
}

/* Helper function to parse a long.
 * Returns 0 if successful, nonzero otherwise.
*/
static int parse_long(const char *s, long *v)
{
    const char *end;
    long        val;

    if (!s)
        return errno = EINVAL;

    end = s;
    errno = 0;
    val = strtol(s, (char **)&end, 0);
    if (errno)
        return errno;

    if (!end || end == s)
        return errno = EINVAL;

    while (*end != '\0' && isspace(*end))
        end++;

    if (*end != '\0')
        return errno = EINVAL;

    if (v)
        *v = val;

    return 0;
}

그 중 parse_long()10진수( 987), 16진수( 0x3DB), 8진수( 01733) 표기가 지원됩니다.

그럼 main()그것은 같다

int main(int argc, char *argv[])
{
    double min, max;
    long   n;

    setlocale(LC_ALL, "");

    /* Require "command N min max" -- four parameters,
     * including the executable file name (argv[0]). */

    if (argc != 4 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
        fprintf(stderr, "Usage: %s [ -h | --help ]\n", argv[0]);
        fprintf(stderr, "       %s N min max\n", argv[0]);
        return EXIT_FAILURE;
    }

    if (parse_long(argv[1], &n) || n < 1L) {
        fprintf(stderr, "%s: Invalid N.\n", argv[1]);
        return EXIT_FAILURE;
    }

    if (parse_double(argv[2], &min)) {
        fprintf(stderr, "%s: Invalid minimum.\n", argv[2]);
        return EXIT_FAILURE;
    }

    if (parse_double(argv[3], &max)) {
        fprintf(stderr, "%s: Invalid maximum.\n", argv[3]);
        return EXIT_FAILURE;
    }

    if (min > max) {
        const double tmp = min;
        min = max;
        max = tmp;
    }

    /* ... */

    return EXIT_SUCCESS;
}

setlocale(LC_ALL, "");C 라이브러리에 현재 환경을 확인하고 이에 맞게 현지화를 설정하도록 지시합니다 . 프로그램은 이 클래스를 사용하여 LC_CTYPE어떤 문자가 공백(공백 또는 탭)인지 확인합니다. 그래도 좋은 습관입니다. 어느 시점에서 ä및 같은 문자를 지원하려는 경우 와이드 문자 및 I/O로 전환할 수 있습니다.

학습자는 절 에서 parse_long()parse_double()를 생략하고 로 대체 할 수 있으며 현지화를 무시할 수 있습니다. 몇 줄의 코드를 절약할 수 있습니다.ifsscanf()

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

int main(int argc, char *argv[])
{
    double min, max;
    long   n;

    /* Require "command N min max" -- four parameters,
     * including the executable file name (argv[0]). */

    if (argc != 4 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
        fprintf(stderr, "Usage: %s [ -h | --help ]\n", argv[0]);
        fprintf(stderr, "       %s N min max\n", argv[0]);
        return EXIT_FAILURE;
    }

    if (sscanf(argv[1], " %ld", &n) != 1 || n < 1L) {
        fprintf(stderr, "%s: Invalid N.\n", argv[1]);
        return EXIT_FAILURE;
    }

    if (sscanf(argv[2], " %lf", &min) != 1) {
        fprintf(stderr, "%s: Invalid minimum.\n", argv[2]);
        return EXIT_FAILURE;
    }

    if (sscanf(argv[3], " %lf", &max) != 1) {
        fprintf(stderr, "%s: Invalid maximum.\n", argv[3]);
        return EXIT_FAILURE;
    }

    if (min > max) {
        const double tmp = min;
        min = max;
        max = tmp;
    }

    /* ... */

    return EXIT_SUCCESS;
}

그런데 제 생각에는 실제로는 불충분한 방법을 왜 배우는 걸까요? 나는 개인적으로 어리석은 가정이 이루어진 상황을 알고 있습니다."사람의 이름에는 A부터 Z까지의 문자만 포함됩니다."해결하는 데 수십 시간이 걸렸습니다(컴퓨팅 클러스터의 411 서비스, 사용자 이름이 영어가 아님). 우리는 세계화된 세상에 살고 있습니다. 영어를 구사하는 여러분은 줄을 서서 어리석은 가정을 포기하는 것이 좋습니다.

사람들은 또한 사실 이후에 현지화를 배울 수 없는 것 같습니다. 내가 만난 대부분의 "경험이 풍부한 C 프로그래머"는 현지화나 문자 집합 문제에 대해 알지도 관심도 없는 것 같습니다. (아주 멀리어디에서나 UTF-8을 사용하세요.) 이는 다른 사람들이 자신의 잘못된 가정을 파악하는 데 많은 시간을 소비해야 하고 시간과 에너지를 낭비해야 함을 의미합니다...부끄러운 일입니다.


프로그램이 명령줄 인수를 허용하는 형식을 취할 때 Bash 루프를 사용할 수 있습니다.

for (( i=1; i<=20; i++ )); do ./yourprog $i 0.0 10.0 ; done > output.txt

공백 또는 탭으로 구분된 열에 데이터를 출력하거나 *열에 데이터가 누락된 경우 이를 -사용하여 데이터를 그릴 수 있습니다 gnuplot.

예를 들어 다음과 같은 output.txt경우

#N result error
1  3.1   0.04159265359
2  3.14  0.00159265359
3  3.141 0.00059265359

등. 예를 들어 다음을 사용하여 데이터를 볼 수 있습니다.

gnuplot -p -e 'plot "output.txt" u 2:3 notitle w lines'

Gnuplot은 로 시작하는 줄을 무시하므로 #파일 시작 부분에 이러한 주석이나 헤더를 사용하여 각 열의 목적을 설명할 수 있습니다. 보다문서더 많은 정보를 알고 싶습니다. 저는 개인적으로 그림을 작은 파일로 저장하거나 고품질의 벡터 그래픽을 가질 수 있는 형식으로 SVG저장 하는 것을 선호합니다. PDF제가 특히 추천하는 강좌입니다.

답변2

컴파일하고 링크하는 중이므로 출력은 개체 파일이 아닌 실행 파일이 됩니다. 이로 인해 .o 접미사가 오해의 소지가 있습니다.

gcc -o err trap_error.c -lm

더 나은 생각일 수도 있습니다.

요청하신 내용이 명확하지 않지만 자동 생성된 입력을 제공하고 모든 출력을 파일로 리디렉션하려는 것 같습니다. N= 2^{i}, i= 1,2 ....20;다음 명령을 사용하여 bash에서 생성 할 수 있습니다 .

for ((i=2;i<2**20;i*=2)); do echo "$i" ; done

-1과 1이 각각 하한과 상한인 경우 $i 뒤에 추가하고 각 트리플을 프로그램 호출에 파이프할 수 있습니다.

for ((i=2;i<2**20;i*=2)); do echo "$i -1 1" | ./err ; done > out.txt

> out.txt섹션에서는 모든 ./err 호출의 모든 출력을 out.txt.

관련 정보