Reading in ints and chars from a same file

Hi.
Would someone please help me with this.
I'm trying to read in a sequence of integers from file
but there is a possibility that the file will accidentally contain a char
instead of int and I need to be able to distinguish between the two.
Right now, I'm using fscanf
1
2
3
4
5
6
FILE *fp=fopen(argv[1],"r");
int num;
while(fscanf(fp,"%i",&num)!=EOF){

etc...


but the code chokes soon as it encounters a char(segmentation fault).

I tried using getc or fgetc, that didn't work out either.

What can I do?

Thank you.
Last edited on
Anybody?
You could read each input as a string, then attempt to convert that string to an int.
What would be a typical example of the contents of the input file?
Something like this

2 9 5 4 8 3 9 9 3
4 7 3 8 2 1 6 4 9
2 4 3 7 5 9 1 3 7
3 7 4 9 2 5 4 1 8
3 8 7 1 9 4 3 7 2
3 7 4 1 9 3 4 2 9
2 8 4 9 1 4 8 2 9
2 7 3 8 1 9 3 5 8
1 5 2 8 9 2 4 7 9

or as a single line of 81 digits from1-9.
It's a sudoku board.
Last edited on
Right now I'm doing

1
2
3
4
5
6
7
8
9
int board[9][9];
int num;
char cNum[20];
FILE *fp=fopen(argv(1),"r");
while(fscanf(fp,"%c",&cNum)!=EOF);{
num=atoi(cNum);
printf("%d",num);

etc...


and it prints out a value exatly 10 times more that what it is in a table!

Why?
Last edited on
%c is the code to get a single character. You need %s for a string.
1
2
3
4
5
6
7
8
9
10
11
12
13
    char buf[20];
    int num;
    while (fscanf(fp, "%s", buf) != EOF)
    {
        num = atoi(buf);
        printf("%d ", num);
        if (num == 0)
        {
            printf("Error: %s\n", buf);
            break;
        }
        
    }
Ok, it's working now but now I'm having trouble further down the line.
In subsequent code, I do several checks like

 
if(num==' ')


 
if(isalpha(num))


 
if(num=='\n')


 
if((num<1)||(num>9))


and depending on those conditions, i decide which row and column
to write the value to, or abort whatsoever(like when the value is out of range 1-9)

But none of these seem to be working.

For example: when num=='\n', my code should increment the row number and set column number to 0 so that the next value is written at the beginning of next row, but it's
not happening. The row always remains 0 and column is being incrimented all the way to 80.
And if I put a letter into the table(in the txt file) and feed it to my program,
that letter is being reported as 0.
Does this have something to do with how fscanf treats ' ', '\0' and '\n'?
Last edited on
Well, num is an integer, it doesn't make any sense to compare it with things like space or newline which are characters.

fscanf() specifically ignores all whitespace (whitespace characters include spaces, newline and tab characters).
http://www.cplusplus.com/reference/cstdio/fscanf/
How about simply counting how many values have been read and moving to the next row each time the count gets to 9.
Ok.
I understand.
But what about the case when a letter instead of an integer is found?

Actually, how DO i find that letter?

As i see it, the squence of events goes like this:
fscanf loads integers from the table into a string where they are stored
not as ints but as ..... what?
Than that 'what" is being converted to an int by atoi()
If the value used to be an integer in the table to begin with, there is no problem.
But if it used to be a letter, than it seems that atoi() just turnes it into 0?

How can I work around this?

How can I recognize this letter.

Thank you for your time Chervil.
I really appreciate your help.
In this case, I think previously you said that the numbers must be in the range 1 to 9. If that is so, you could reliably use a zero result to indicate an error.

If that isn't acceptable, you could perhaps try strtol() but then things start to get a bit complicated.

Is there a reason why you are not using C++ ifstream? That makes it pretty simple to detect whether an integer was successfully read of not.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
ifstream fin("input.txt");
int num;
string word;

if (!(fin>> num))
{
    fin.clear();
    fin >> word;
    cout << "error" << word << endl;
}
else
{
    cout << "number is: " << num << endl;
}
Last edited on
This is for my cs141 class which we do purely in C.

I think I'll just go ahead and do what you said.
Use that zero as an indicator of
an error and just print out :"A letter or a number out of range has been detected"

I was just trying to be fancy an separate those two cases. :-)

Anyway, I really appreciate all your help!

Thanks man.
There was another idea which passed through my mind, that is to read the input as single characters. Then if the character is in the range '0' to '9', you could convert it to the corresponding integer. Otherwise, handle the error.
1
2
3
4
5
6
char ch ='3'
int num;
if (ch >= '0' && ch <= '9')
    num = ch - '0';
else
   // error 
Cool!

I would use getc for that, right?
Well, you might. I was thinking in terms of fscanf() with the %c code. Depends on whether you want to ignore all whitespace (which is easier, in my opinion) or not.
Oh, I see.
With getc I'll have to go back to checking for all those "white space character" cases.
Got it!

Thanks.
Last edited on
Topic archived. No new replies allowed.