0

I have a C project where the user can type in an 8 bit binary number or open up a text file with an 8 bit binary number. What I'm having trouble with is getting the 8 bit binary number from a file and making that an argument char* argv[] for my program. This is how I'm reading the 8 bit binary number from the file

    fd = open(argv[1], O_RDONLY);
    read(fd,jString, 100);
    close(fd);
    printf("jString: %s\n", jString);

Right now I only know how to put the 8 bit binary number into a string but what I want is to turn each 8 bit binary number input separated by spaces from the file into an argument char* argv[] for my program is this possible if so how do I do it?

Something that I already tried is this.

    fd = open(argv[1], O_RDONLY);
    read(fd,argv[1], 100);

the problem with this is that it just reads the whole file into argv[1] and doesn't seperate them by spaces and into different arguments for my program.

  • 1
    Is the file you're reading from a text file? [Edit] your question and show a minimal example of the input file.You probably want to use `fopen` and `fgets` instead of `open` and `read`. – Jabberwocky Feb 18 '20 at 13:27
  • This is [operating system](https://en.wikipedia.org/wiki/Operating_system) specific. What is your OS? Read [*Modern C*](https://modernc.gforge.inria.fr/) and use [C dynamic memory allocation](https://en.wikipedia.org/wiki/C_dynamic_memory_allocation). Perhaps use [getline](https://stackoverflow.com/a/9171511/841108) and [sscanf](https://www.tutorialspoint.com/c_standard_library/c_function_sscanf.htm) – Basile Starynkevitch Feb 18 '20 at 13:28
  • 1
    `read(fd,jString, 100);` and then `printf("jString: %s\n", jString);` is going to cause problems. `read()` does not terminate string. – Andrew Henle Feb 18 '20 at 13:32
  • In Linux you can "pipe" the file to your program. Portably, it is better to check if command-line args are present, if so copy those to actual variable, else read file and copy that to the actual variable. – Lundin Feb 18 '20 at 13:41
  • @Lundin: I think what you have in mind is not a pipe but [command substitution](https://www.tldp.org/LDP/abs/html/commandsub.html). Using that, OP could just write their program to always expect the values on the command line, and if they want to get it from a file, run the program as `myprog $(cat myfile.txt)` (or in traditional backtick syntax, `myprog \`cat myfile.txt\``). – Nate Eldredge Feb 18 '20 at 15:35

2 Answers2

0

What I'm having trouble with is getting the 8 bit binary number from a file and making that an argument char* argv[] for my program

You can not do this. The usual declaration of

int main(int argc, char** argv){};

means that these 2 arguments are provided for you by the operating system when your program is run. What you can do is build something like this for your program, let's say a int myArgCountand char** myArgValues; but it seems that you do not need that.

If task is you program, running task 00001111 will put 00001111 into argv[1]. And set argcto 2, since argv[0] is always the complete path of your program.

At first you say that a binary number can be provided in a file, but in the next paragraph you said

what I want is to turn each 8 bit binary number input separated by spaces

If in fact the input file can have a list of 8-bit binary numbers separated by spaces --- and not just one --- you will need do build a list just like the system does for you, alocating memory for the numbers and creating an array of pointers to them, and an int with the count of numbers. It is not complicated.

The code below tests for an argument on the command line and if not present tries to open source.txt file to get one. May be it helps.

Note the use of scanf()to read the values from the file. The mask in use "%8[01]" is very convenient: it accepts just 0 and 1 for a maximum of 8 digits.

#define _CRT_SECURE_NO_WARNINGS
#include "stdio.h"
#include "stdlib.h"
#include "string.h"

int main(int argc, char** argv)
{
    char        binary_number[10];
    char*       mask = "%8[01]"; // for scanf()
    const char* FileName = "source.txt";

    if (argc < 2)
    {   // no number on the command line
        fprintf(stderr, "\nNo 8-bit number provided on the command line\n");
        FILE* in_file = fopen(FileName, "r");
        if (in_file == NULL)
        {
            fprintf(stderr, "Could not open [%s]\n", FileName);
            return -1;
        }
        int n = fscanf(in_file, mask, binary_number);
        printf("\nFrom the file [%s] number is [%s]\n", FileName, binary_number);
        fclose(in_file);
    }
    else
    {   // number provided
        strncpy(binary_number, argv[1], 9);
        fprintf(stderr, "\nFrom the command line: [%s]\n", argv[1]);
    };
    return(EXIT_SUCCESS);
};

the program shows

From the command line: [101010]

or

    No 8-bit number provided on the command line
    From the file [source.txt] number is [11110000]
ARFNeto
  • 1
  • 2
0

here your program with dynamic memory allocation:

  • Argument separtor = ' '
  • Argument from commande = your_program_name "10001010" "01010101"
  • Argument from file : command-line = your_program_name "...\yourfile.xyz" Example :

enter image description here

#include <malloc.h>
#include <string.h>
#include <stdio.h>

#define DELIMITER ' '

// Tokenize function
int Tokenize(char* pcLine, char ** pcListeArgs, const char* pcDelim)
{
    int iNumElet = 0;
    size_t len = 0;         

    // Get line size
    int init_size = strlen(pcLine);

    char *ptr = strtok(pcLine, pcDelim);

    while(ptr != NULL)
    {
        len = strlen(ptr);
        pcListeArgs [iNumElet] = (char*) calloc (len+1, sizeof (char));
        memset(pcListeArgs [iNumElet], 0, len+1); // reset content
        memcpy (pcListeArgs [iNumElet], ptr, len); // copy data

        ptr = strtok(NULL, pcDelim);

        iNumElet ++;
    }

    return iNumElet;
}

int main(int argc, char** argv)
{
    FILE * fp;
    char * line = NULL;
    size_t len = 0;
    char ch;
    char *pcFileContent;
    char cDelim = DELIMITER;



    // Case : argument are a file 
    if (argc == 2) 
    {
        const char* pcFilePath = argv[1];
        fp = fopen(pcFilePath, "r");

        if (fp == NULL)
        {
            perror("Error while opening the file.\n");
            return (-1);
        }

        // Put the curso at the end of file
        fseek (fp,0, SEEK_END);

        // Get number of charactes
        len = ftell(fp);

        // Allocat memory 
        pcFileContent = (char*) calloc (len+1, sizeof (char));

        //Erase content to zero
        memset(pcFileContent,'\0',len+1);

        // Put the curso at the begining of file
        fseek (fp,0, SEEK_SET);

        // Read file char by char
        unsigned int i=0;
        unsigned int iNbArgs = 1;

        while((ch = fgetc(fp)) != EOF)
        {
            if (ch == DELIMITER)
                iNbArgs ++; // We have a new arguments              

            pcFileContent[i++] = ch;
        }

        char **pcListeArgs =  (char**) calloc (iNbArgs, sizeof (char*));

        iNbArgs = Tokenize (pcFileContent, pcListeArgs, &cDelim);

        // here you have all you arguments ....
        for ( i=0; i< iNbArgs; i++)
        {
            printf ("Argument %d = %s\n", i, pcListeArgs[i]);
        }

        // Free memory
        for(int i = 0; i < iNbArgs; i++)
            free(pcListeArgs[i]);

        free(pcListeArgs);
        free(pcFileContent);

    }else if ( argc > 2) // Case : argument is binary number
    {
        for ( int i=1; i< argc; i++)
        {
            printf ("Argument %d = %s\n", i, argv[i]);
        }
    }

    return 0;
}

Result:

  • Argument from commande = ArgParsor.exe "10001010" "01010101" "01010111"

enter image description here

  • Argument from file : command-line = ArgParsor.exe "G:\temp.txt"

enter image description here

Landstalker
  • 1,368
  • 8
  • 9