0

so I can't seem to redirect an input so that my program reads it.

It says in the assignment that the program should NOT print anything to prompt for user input. As many numbers have to be read from stdin to test your programs, you are expected to use INPUT REDIRECTION to read the input from a file.

I have this main function:

int main(int argc, char const *argv[])
{
    int arr[100];
    for (int i = 0; i < SIZE; i++)
    {
        values[i] = 0;
        hashMapLinear[i] = 0;             
    }
    FILE* file = fopen("file_name.txt", "r");             
    int index = 0;
    int k = 0;
    while (!feof(file))
    {
        fscanf(file, "%d", &k);
        arr[index] = k;
        index++;
    }
    fclose(file);
    file = fopen("file_name.txt", "r");
    int i = 0;
    fscanf(file, "%d", &i);
    float size = i;

    fscanf(file, "%d", &i);
    int thresh_hold = i;

    int load_factor = size / 2;
    int j = 0;

    if (size <= 0)
    {
            printf("\nSize of file can not be zero or negative integer:\n");
    }
    else
    {
        while (!feof(file))
        {
            if (num_keys <= load_factor)
            {
                int check_valid_input= fscanf(file, "%d", &i);      
                if (check_valid_input != 0 || check_valid_input== -1)
                {
                    insert_into_hashtable(i, size);
                }
                else
                {
                      printf("\n invalid input:\n");
                      exit(1);
                }
            }
            else
            {
                printf("\nError in inserting more numbers:\n");
                exit(1);
            }
        }
        fclose(file);
        printHashMap(arr,size, thresh_hold);                  
    }
}

How do I edit this main function so that it redirects seq.1 or any other text file to the C program? Any help would be appreciated!

11
  • use fscanf's stdin-reading brother scanf Commented Mar 23, 2017 at 20:47
  • You change it to read from stdin, which is already open when your program starts up. You don't have to call fopen at all. The redirection is done outside the program, by the shell, when you type ./a.out < seq.1. Commented Mar 23, 2017 at 20:47
  • never use feof() to control a while() loop, That function does not work as the posted code expects. also need to avoid overflow of the array Suggest: while ( index < 100 && 1 == fscanf(file, "%d", &k) ) { Commented Mar 24, 2017 at 12:10
  • since the code is closing and reopening the same file all with the "r" mode, Strongly suggest replacing the first call to fclose() and the second call to fopen() with a call to rewind() Commented Mar 24, 2017 at 12:15
  • when compiling, always enable all the warnings, then fix those warnings. (for gcc, at a minimum use: -Wall -Wextra -pedantic I also use: -Wconversion -std=gnu11 ) Commented Mar 24, 2017 at 12:20

4 Answers 4

6

Simply use stdin instead of file, but do not open stdin, and do not close it.

When calling a program like ./program < seq.1, the operating system will pass the content of seq.1 to your program as if it were inputed through the console. Hence, using stdin, which represents console input, will do the job.

Note that stdin is by default already opened when your program starts.

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

Comments

1

Your code is hardcoding the input file, so file redirection from the command line will not do anything. File redirection helps with stdin (console input), stdout (console output), and stderr (console error message output). See linuxcommand.org here for a tutorial.

So to make your code work with stdin, use scanf instead of fscanf. scanf takes input from FILE stdin, whereas fscanf takes input from a specified FILE. Using scanf will result in input from stdin, which can be redirected on the command line as described above. Similarly, if you want to use stdout, use printf instead of fprintf. Neither scanf or printf take a file parameter, but are the same as fscanf and fprint in other respects. See this stackOverflow article for some more explanation.

Here is how I would fix your code to read/write to stdin and stdout:

#include <stdio.h>
int main(int argc, char const *argv[])
{
    int arr[400];
    for (int i = 0; i < SIZE_HASH_MAP; i++)
    {
        values[i] = 0;
        hashMapLinear[i] = 0;             
    }
    // Not Needed: FILE* file = fopen("file_name.txt", "r");             
    int index = 0;
    int k = 0;
    while (!feof(stdin))
    {
        scanf("%d", &k);
        arr[index] = k;
        index++;
    }
    // fclose(file);
    // file = fopen("file_name.txt", "r");
    int i = 0;
    scanf("%d", &i);
    float size = i;
    //printf("%d ", i);
    scanf("%d", &i);
    int thresh_hold = i;
    //printf("%d ", i);
    int load_factor = size / 2;
    int j = 0;
    //int check_valid_input = 0;
    if (size <= 0)
    {
            printf("\nSize of file can not be zero or negative integer:\n");
    }
    else
    {
        while (!feof(stdin))
        {
            if (num_keys <= load_factor)
            {
                int check_valid_input= scanf("%d", &i);      
                if (check_valid_input != 0 || check_valid_input== -1)
                {
                    insert_into_hashtable(i, size);
                }
                else
                {
                      printf("\n invalid input:\n");
                      exit(1);
                }
            }
            else
            {
                printf("\nError in inserting more numbers:\n");
                exit(1);
            }
        }
        // fclose(file);
        printHashMap(arr,size, thresh_hold);                  
    }
}

To use stdin (and file redirection), you will not be able to close and reopen stdin and get the same data. It just does not work that way. So remove one of the read loops so you only read it once. The first loop reads it into array arr[], so the second loop should take the values from that array rather than re-reading it.

#include <stdio.h>
$include <stdlib.h>
int main(int argc, char const *argv[])
{
    int arr[400];
    for (int i = 0; i < SIZE_HASH_MAP; i++)
    {
        values       [i] = 0;
        hashMapLinear[i] = 0;             
    }

    int index = 0;
    int k     = 0;
    while (!feof(stdin))
    {
        scanf("%d", &k);
        arr[index] = k;
        index++;
    }

    float size      = arr[0];
    int thresh_hold = arr[1];
    int load_factor = size / 2;
    int j = 0;

    if (size <= 0)
    {
      printf("\nSize of file can not be zero or negative integer:\n");
      exit(-1);
    }
    else
    {
     int i;
     for(i=2; i<index; i++) // reuse values stored in arr[]
        insert_into_hashtable(arr[i], size);
     printHashMap(arr,size, thresh_hold);                  
    }
}

Comments

0

You may want to use open() instead of fopen(). Open returns a non-negative integer representing the lowest numbered unused file descriptor. With file descriptors it is much easier to redirect your output.

Comments

0

The shell command already redirects input to your program. There is a file pointer called stdin already opened in your program that represents the standard input. When you use < seq.1, it pipes the contents of the file in the standard input of your program, which you can read using fgetc or scanf.

int main(int argc, char const *argv[])
{
    int arr[400];
    for (int i = 0; i < SIZE_HASH_MAP; i++)
    {
        values[i] = 0;
        hashMapLinear[i] = 0;             
    }

    int index = 0;
    int k = 0;
    while (!feof(stdin))
    {
        fscanf(stdin, "%d", &k);
        arr[index] = k;
        index++;
    }
}

This program reads all the numbers from the standard input and stores them in your array. Notice you don't need to open or close it, it is already open when your main is called and closed at the end of your program execution.

Comments

Your Answer

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