1

Can any one explain to me how to make a C program to read input from a file according to the following scenario:

12
2-4,7,9;
1,4,11-12;
1,4,10,12;
1,4-8,10-12;
1,8;
1,3-6,8,10-12;
1,3,5-6,8,11;
1,8,10-12;
1-8;
;
2;
2-4,7-10,12;

The first number (on the first line) describes what size the grid should be, in this case a 12x12 grid. The following lines describe how many cells are occupied on each row of the grid. For example, in the first row the cells from 2 to 4 and 7 and 9 are occupied; in the second row, the cells 1, 4 and from 11 to 12 are occupied and so on.

Right now I have this code, but it is not solving my problem ...

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

void main()
{   
    char content[3000];

    int value;
    FILE *ptr_file = fopen("data.txt", "r");
    if(!ptr_file)
        return 1;
    int j;

    while(fgets(content, 3000, ptr_file)!=NULL){
        printf("%s", content);
        value = atoi(content);   

        for(j=0; j<3000; j++){
            value = content[j];
            printf("%i", value);
        }
    }
    return 0;
}

Console throws just a bunch of random numbers ...

5
  • 2
    Btw, don't write void main(). Use int main(void) or int main(int argc, char *argv[]) instead (especially when you write return 0; at the end). Commented Jun 14, 2015 at 23:11
  • 1
    You can't just use atoi on the entire content buffer. atoi only converts a single string to an integer. You need to use something like sscanf or strtok to parse the buffer into individual string tokens. Commented Jun 14, 2015 at 23:18
  • You're going to need to read lines (as you are doing), and then parse the line, looking for commas, dashes and semicolons. Beware: strtok() obliterates the delimiter, so you can't really use that. strtol() tells you where it stopped scanning — it looks like a good candidate for this. It's what I use in my library functions that parse ranges of numbers like the ones shown. Commented Jun 14, 2015 at 23:21
  • So guys now i tried to use strtol <code> while(fgets(buf, 3000, ptr_file)!=NULL){ value = strtol(buf, &tbuf, 10); printf("%i", value); } <code> and it gives me output >> 1616714455 Commented Jun 15, 2015 at 0:03
  • the very first line is a special use case. so, read the first line: fgets(). Then gridSize = atoi( theInputBuffer ). Then malloc the requsite (in this case) 12x12 buffer by (assuming each cell is a char) char grid = malloc( gridSizegridSize); then access by grid[row][column] = value; where 'row' is which data row is currently being processed, column is a cell in that row to be 'marked' Commented Jun 15, 2015 at 0:57

3 Answers 3

1

Pseudo-code:

Open your file
Read the first line
    Extract the value N
    Allocate your grid
Loop N times
    Read a line
    If not an empty line, ie. semi-colon only
       Split into tokens by comma
       Check for a range or a single digit
       Extract numbers
       Set cells accordingly
Sign up to request clarification or add additional context in comments.

Comments

1

The "random" numbers are the byte values from your file and you forgot to stop at end of line. Dave's solution is not quite right for c. After read a line:

while not semicolon
    strtoul a number
    if no number
        exit error
    if next char is hyphen
        shift to next char
        strtoul end of range
        if no number
            exit error
        set cells
    else
        set cell
    if next char is not semicolon
        shift to next char

You should not use atoi for anything ever. Use sscanf or strto….

1 Comment

It will return a number even if there are none. Also you don't know if anything is after the read number. It leads to poor parsing. With sscanf or the strto-family you know, how much is read if any, and if supplied with an address of a pointer you also know how far into the string the parsing has gone.
0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

enum { EOD = -1, EOL = -2, ERR = -3, OFF = 0, ON = 1 };//End Of Data, End Of Line

int getValue(FILE *fp){
    static int on_yield = OFF, prev, end;

    if(on_yield == ON && prev < end){
        return ++prev;
    }
    on_yield = OFF;

    int n, ch = fgetc(fp);

    if(ch == EOF)
        return EOD;
    else if(ch == ';')
        return EOL;
    else if(ch == ',' || ch == '\n')
        return getValue(fp);//or change to using loop
    else if(isdigit(ch)){
        ungetc(ch, fp);
        fscanf(fp, "%d", &n);
        return prev=n;
    } else if(ch == '-'){
        on_yield = ON;
        fscanf(fp, "%d", &n);
        end = n;
        return getValue(fp);
    }
    fprintf(stderr, "(%c) invalid format in file\n", ch);
    return ERR;
}

int main(void){
    FILE *ptr_file = fopen("data.txt", "r");
    if(!ptr_file){
        perror("fopen");
        return 1;
    }

    int size;
    fscanf(ptr_file, "%d", &size);//check omitted
    char (*cell)[size] = malloc(size * sizeof(*cell));
    memset(&cell[0][0], ' ', size*size);

    int r = 0, c, value;
    while((value=getValue(ptr_file))!=EOD){
        if(value == EOL){
            ++r;
            continue;
        }
        if(value > 0)
            cell[r][value-1] = '*';
    }
    fclose(ptr_file);

    for(r = 0; r < size; ++r){
        for(c = 0; c < size; ++c){
            putchar(cell[r][c]);
        }
        putchar('\n');
    }
    free(cell);

    return 0;
}

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.