0

I am trying to do the following the C programming language, any help or if you can finish the code I will be greatly appreciated:

I am trying to write a program in C programming language that uses file io, that will parse through the words using sscanf function and output each word in all the sentences inside a txt document (bar.txt). Here is the instructions.

Write a program that opens the file bar.txt name the program "reader". Pass a parameter to indicate lines to read. Read all the lines in the file based on the parameter 'lines' into a buffer and using sscanf parse all the words of the sentences into different string* variables. Print each of the words to the screen followed by a carriage return. You can hardwire filename (path of bar.xt) or use option to enter filename.

This is the txt file (bar.txt) i am working with:

bar.txt

this is the first sentence
this is the 2nd sentence
this is the 3rd sentence
this is the 4th sentence
this is the 5th sentence

end of file: bar.txt

usage of argv: Usage: updater [-f "filename"] 'lines'

-f is optional (if not provided have a hardwired name from previous program 2 (bar.txt)) 'lines' integer from 1 to 10 (remember the files has 5-10 strings from previous program) a sample input example for the input into the program is:

./reader -f bar.txt 1

OUTPUT:

Opening file "bar.txt"
File Sentence 1 word 1 = this
File Sentence 1 word 2 = is
File Sentence 1 word 3 = the
File Sentence 1 word 4 = first
File Sentence 1 word 5 = sentence

another example

./reader -f bar.txt 5

OUTPUT:

File Sentence 5 word 1 = this
File Sentence 5 word 2 = is
File Sentence 5 word 3 = the
File Sentence 5 word 4 = 5th
File Sentence 5 word 5 = sentence

Examples of commands:

./reader -f bar.txt 5
./reader -f bar.txt 2
./reader -f bar.txt 7
./reader 2
./reader 5
./reader 8
./reader 11

this is the code that I have so far please fix the code to show the desired output:

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

#define MAXCHAR 1000

int main(int argc, char *argv[]) {
    FILE *file;
    char string[MAXCHAR];
    char* filename = "c:\\cprogram\\fileio-activity\\bar.txt";
    int integer = argv[3][0] - 48;
    int i; //for loops

    if (argv[1][0] == '-' && argv[1][1] == 'f')
    {
        file = fopen(filename, "r");
        if (file == NULL){
            printf("Could not open file %s",filename);
            return 1;
        }
        while (fgets(string, MAXCHAR, file) != NULL)
            printf("%s", string);
        fclose(file);
        return 0;
    }
}
3
  • Accessing argv[3] causes undefined behavior when you only pass 1 argument, as in the last 4 examples. You're also never using the filename after -f. Commented Nov 1, 2020 at 17:25
  • 1
    argv[3][0] - 48 will only work if they enter a 1-digit number. You should parse the entire argument as an integer, using a function like atoi() Commented Nov 1, 2020 at 17:26
  • You need to show your attempt at using sscanf if you want help. Commented Nov 1, 2020 at 18:21

2 Answers 2

0

You need to get the filename from argv if they use the -f option. And you need to get the number of lines from a different argument depending on whether this option was supplied.

Use strcmp() to compare strings, rather than testing each character separately. And use atoi() to convert the lines argument to an integer, since your method only works for single-digit numbers.

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

#define MAXCHAR 1000

function usage() {
    fprintf(stderr, "Usage: reader [-f filename] lines\n");
    exit(1);
}

int main(int argc, char *argv[]) {
    FILE *file;
    char string[MAXCHAR];
    char* filename = "c:\\cprogram\\fileio-activity\\bar.txt";
    int integer;
    int i; //for loops

    if (argc < 2) {
        usage();
    }

    # Process arguments
    if (strcmp(argv[1], "-f") == 0)
    {
        if (argc < 4) {
            usage();
        }
        filename = argv[2];
        integer = atoi(argv[3]);
    } else {
        integer = atoi(argc[1]);
    }

    file = fopen(filename, "r");
    if (file == NULL){
        fprintf(stderr, "Could not open file %s\n",filename);
        return 1;
    }
    while (fgets(string, MAXCHAR, file) != NULL)
        printf("%s", string);
    fclose(file);
    return 0;
}
Sign up to request clarification or add additional context in comments.

Comments

0

To add to what Barmar already answered, for the further steps in completing the assignment:

Splitting a string into separate words is usually called tokenization, and we normally use strtok() for this. There are several ways how one can use sscanf() to do it. For example:

  1. Use sscanf(string, "%s %s %s", word1, word2, word3) with however many word buffers you might need. (If you use e.g. char word1[100], then use %99s, to avoid buffer overrun bugs. One character must be reserved for the end-of-string character \0.)

    The return value of sscanf() tells you how many words it copied to the word buffers. However, if string contains more than the number of words you specified, the extra ones are lost.

    If the exercise specifies the maximum length of strings, say N, then you know there can be at most N/2+1 words, each of maximum length N, because each consecutive pair of words must be separated by at least one space or other whitespace character.  
     

  2. Use sscanf(string + off, " %s%n", word, &len) to obtain each word in a loop. It will return 1 (with int len set to a positive number) for each new word, and 0 or EOF when string starting at off does not contain any more words.

    The idea is that for each new word, you increment off by len, thus examining the rest of string in each iteration.  
     

  3. Use sscanf(string + off, " %n%*s%n", &start, &end) with int start, end to obtain the range of positions containing the next word. Set start = -1 and end = -1 before the call, and repeat as long as end > start after the call. Advance to next word by adding end to off.

    The beginning of the next word (when start >= 0) is then string + start, and it has end - start characters.

    To "emulate" strtok() behaviour, one can temporarily save the terminating character (which can be whitespace or the end of string character) by using e.g. char saved = string[off + end];, then replace it with an end-of-string character, string[off + end] = '\0';, so that (string + start) is a pointer to the word, just like strtok() returns. Before the next scan, one does string[off + end] = saved; to restore the saved character, and off += end; to advance to the next word.
     

The first one is the easiest, but is the least useful in practical programs. (It works fine, but we do not usually know beforehand the string length and word count limitations.)

The second one is very useful when you have alternate patterns you can try for the next "word" or item; for example, when reading 2D or 3D vectors (points in a plane, or in three-dimensional space), you can support multiple different formats from <1 2 3> to [1,2,3] to 1 2 3, by trying to parse the most complicated/longest first, and trying the next one, until one of them works. (If none of them work, then the input is in error, of course.)

The third one is most useful in that it describes essentially how strtok() works, and what its side effects are. (It's saved character is hidden internally as a static variable.)

Comments

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.