1

I need to gather data written in a text file and use a bash shell which will allow each line of the text file to be used in my c program as separate data points. For a little more context, my program is taking in a set of coordinates(x,y) for as many lines there are in my input.txt file. After that, it will find the nearest and furthest points in reference to the one it is on.

For example input.txt has the following lines:

    input1 3.2 9.3
    input2 5.7 13.6
    input3 18.4 12.2

I have not found out how to do this on bash. I have written the following program to do something very similar but not dynamically using bash redirection.

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

struct coordinates{
    //The label of the coordinates
    char coordinateName[32];
    //The x and y coordinates
    float xCoord;
    float yCoord;

} coordinate;

//Function to calculate distance from another point
float distance(char p1[32], char p2[32], float x1, float x2, float y1, float y2){
    float c;

    c = sqrt( pow((x1-x2),2) + pow((y1-y2),2) );

    printf("\nDistance between %s and %s is: \t\t\t\t%.2f", p1, p2, c);
    return c;
}

int main () {
    // Get the number of inputs being taken in from the user via command line
    char ENTRIESstring[1]; 
    int ENTRIES;

    scanf("%s", ENTRIESstring);
    ENTRIES = atoi(ENTRIESstring);
    // Declare a struct object
    struct coordinates myCoordinates[ENTRIES];

    for(int i = 0; i<ENTRIES; i++){
        // Enter the coordinate name
        //printf("Enter a Coordinate name: ");
        scanf("%s", &*myCoordinates[i].coordinateName);
        // Ask for x coordinate
        //printf("Enter a Coordinate value for x: ");
        scanf("%f", &myCoordinates[i].xCoord);
        // Ask for y coordinate
        //printf("Enter a Coordinate value for y: ");
        scanf("%f", &myCoordinates[i].yCoord);
    }

    //define closest and furthest points
    float closestPoints = INFINITY, furthestPoints = 0.0;
    int closestPoint1, closestPoint2;
    int furthestPoint1, furthestPoint2;
    //define calculation variable to check against closest and furthest point
    float calculation;

    for(int i = 0; i <= ENTRIES-1; i++){
        for (int j = 0; j <= ENTRIES-1; j++) {

            char *p1,*p2;
            float x1,x2,y1,y2;

            p1 = myCoordinates[i].coordinateName;
            x1 = myCoordinates[i].xCoord;
            y1 = myCoordinates[i].yCoord;
            p2 = myCoordinates[j].coordinateName;
            x2 = myCoordinates[j].xCoord;
            y2 = myCoordinates[j].yCoord;
            
            //if coord1 is equal to coord2 skip
            if(i==j){
                continue;
            }
            else{
                printf("\n%s - (x:%.2f,y:%.2f) and %s - (x:%.2f,y:%.2f)", p1,x1,y1,p2,x2,y2);

                calculation = distance(p1, p2, x1, x2, y1, y2);

                if (calculation < closestPoints){
                    closestPoint1 = i;
                    closestPoint2 = j;
                    closestPoints = calculation;
                }
                else if (calculation > furthestPoints){
                    furthestPoint1 = i;
                    furthestPoint2 = j;
                    furthestPoints = calculation;
                }
                printf("\n-----------------------------------------------------------------------");
            }
        }
    }

    printf("\nClosest points:  point %s and point %s - distance:  \t%.2f", myCoordinates[closestPoint1].coordinateName, myCoordinates[closestPoint2].coordinateName, closestPoints);
    printf("\nFurthest points: point %s and point %s - distance: \t%.2f\n", myCoordinates[furthestPoint1].coordinateName, myCoordinates[furthestPoint2].coordinateName, furthestPoints);
    return(0);
}

Any insight or sources to read on this would be greatly appreciated. Thanks

13
  • 3
    For reading from a file connected to standard input, you don't really want the prompts. You run the program ./program < input.txt and the shell takes care of the I/O redirection. Your program simply reads from standard input and does its stuff. On POSIX-like systems, you can use isatty(STDIN_FILENO) to find out whether the input is a terminal and avoid prompting if it is not. Commented Mar 29, 2022 at 0:17
  • 1
    When you use scanf(), it really doesn't care about lines. It will read three values (name, x, y) in turn. With the input file shown, it will start on a new line every three entries, but you could have the whole file on a single line, or each item on a separate line with random numbers of blank lines in between and it would all work the same. An alternative is to rewrite the code so it uses fgets() or an equivalent to read a line and you can then use sscanf() or other tools to parse that line of data. There are some advantages to that technique (especially when reporting errors). Commented Mar 29, 2022 at 0:21
  • 1
    The redirection just enters the data in the file as if it were keystrokes from a keyboard. The data ends up wherever it would end up if you were entering it from the keyboard. If you do want to see individual lines coming in use getline() and then use sscanf() to get the data out of the variable that holds the line. Commented Mar 29, 2022 at 0:22
  • 1
    Yup, it really is that easy. It's one of the reasons Unix and derivative systems are so powerful. (I'm not quite sure where null characters (null bytes, '\0') figure in the discussion. You're reading text files and text files don't contain null bytes in single-byte code sets — or in UTF-8.) Commented Mar 29, 2022 at 0:27
  • 1
    If you use fgets() or equivalent to read lines, then you count how many times you call it before reaching EOF to determine the number of lines in the file. With scanf(), there isn't a reliable way to count physical lines (because scanf() skips white space, including newlines, willy-nilly). You can make assumptions and count the number of times you read three entries and assume each set of three is one input line. You can do various tricks to avoid too much memory allocation. One is to allocate, say, 16 objects, and then when you read a 17th one, reallocate the space (double it)… Commented Mar 29, 2022 at 0:59

1 Answer 1

1

Assuming the C code is compiled to an executable a.out, would you please try the bash code:

#!/bin/bash
./a.out $(wc -l < input.txt) < input.txt > output,txt
  • $(wc -l < input.txt) counts the lines of the input file and is passed to a.out as the 1st argument.
  • The input.txt is redirecred to the standard input of a.out and the output is redirected to output.txt, which is created as a new file.

The C code will work without modifications but may be refined e.g. removing the prompts.

Sign up to request clarification or add additional context in comments.

1 Comment

Yes! Thank you for showing me the syntax on how this works. I removed all of the prompts and this works just fine.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.